Wait for ICE gathering completion before requesting video track + create file e2e test fix (#5193)

* Test main e2e

* Create projects separately in home page tests

I think creating them in Promise.all was introducing nondeterminism and
making tests flaky.

* Query the homepage projects in an order-insensitive way

* Wait for ICE candidate gathering to complete before requesting video track

* Update src/lang/std/engineConnection.ts

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

* Fix create file e2e failure

* Yarn fmt

* Fix typo: s/that/this

yarn tsc was failing with this error:

```
src/lang/std/engineConnection.ts:1285:7 - error TS2304: Cannot find name 'that'.

1285       that.triggeredStart = false
           ~~~~
```

* Fix up revolve tests

* Turn off 3 flaky Windows tests

* Fix tags

---------

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
This commit is contained in:
49fl
2025-02-03 13:41:23 -05:00
committed by GitHub
parent 3e8ee3ffc4
commit 56d861f2cc
10 changed files with 281 additions and 237 deletions

View File

@ -248,6 +248,8 @@ class EngineConnection extends EventTarget {
mediaStream?: MediaStream
idleMode: boolean = false
promise?: Promise<void>
sdpAnswer?: Models['RtcSessionDescription_type']
triggeredStart = false
onIceCandidate = function (
this: RTCPeerConnection,
@ -553,6 +555,7 @@ class EngineConnection extends EventTarget {
* did not establish.
*/
connect(reconnecting?: boolean): Promise<void> {
const that = this
return new Promise((resolve) => {
if (this.isConnecting() || this.isReady()) {
return
@ -583,8 +586,38 @@ class EngineConnection extends EventTarget {
},
}
const initiateConnectingExclusive = () => {
if (that.triggeredStart) return
that.triggeredStart = true
// Start connecting.
that.state = {
type: EngineConnectionStateType.Connecting,
value: {
type: ConnectingType.WebRTCConnecting,
},
}
// As soon as this is set, RTCPeerConnection tries to
// establish a connection.
// @ts-expect-error: Have to ignore because dom.ts doesn't have the right type
void that.pc?.setRemoteDescription(that.sdpAnswer)
that.state = {
type: EngineConnectionStateType.Connecting,
value: {
type: ConnectingType.SetRemoteDescription,
},
}
}
this.onIceCandidate = (event: RTCPeerConnectionIceEvent) => {
console.log('icecandidate', event.candidate)
// This is null when the ICE gathering state is done.
// Windows ONLY uses this to signal it's done!
if (event.candidate === null) {
initiateConnectingExclusive()
return
}
@ -595,7 +628,6 @@ class EngineConnection extends EventTarget {
},
}
// Request a candidate to use
this.send({
type: 'trickle_ice',
candidate: {
@ -605,8 +637,38 @@ class EngineConnection extends EventTarget {
usernameFragment: event.candidate.usernameFragment || undefined,
},
})
// Sometimes the remote end doesn't report the end of candidates.
// They have 3 seconds to.
setTimeout(() => {
initiateConnectingExclusive()
}, 3000)
}
this.pc?.addEventListener?.('icecandidate', this.onIceCandidate)
this.pc?.addEventListener?.(
'icegatheringstatechange',
function (_event) {
console.log('icegatheringstatechange', this.iceGatheringState)
if (this.iceGatheringState !== 'complete') return
initiateConnectingExclusive()
}
)
this.pc?.addEventListener?.(
'iceconnectionstatechange',
function (_event) {
console.log('iceconnectionstatechange', this.iceConnectionState)
console.log('iceconnectionstatechange', this.iceGatheringState)
}
)
this.pc?.addEventListener?.('negotiationneeded', function (_event) {
console.log('negotiationneeded', this.iceConnectionState)
console.log('negotiationneeded', this.iceGatheringState)
})
this.pc?.addEventListener?.('signalingstatechange', function (event) {
console.log('signalingstatechange', this.signalingState)
})
this.onIceCandidateError = (_event: Event) => {
const event = _event as RTCPeerConnectionIceErrorEvent
@ -634,6 +696,8 @@ class EngineConnection extends EventTarget {
})
)
break
case 'connecting':
break
case 'disconnected':
case 'failed':
this.pc?.removeEventListener('icecandidate', this.onIceCandidate)
@ -1126,25 +1190,8 @@ class EngineConnection extends EventTarget {
},
}
// As soon as this is set, RTCPeerConnection tries to
// establish a connection.
// @ts-ignore
// Have to ignore because dom.ts doesn't have the right type
void this.pc?.setRemoteDescription(answer)
this.sdpAnswer = answer
this.state = {
type: EngineConnectionStateType.Connecting,
value: {
type: ConnectingType.SetRemoteDescription,
},
}
this.state = {
type: EngineConnectionStateType.Connecting,
value: {
type: ConnectingType.WebRTCConnecting,
},
}
break
case 'trickle_ice':
@ -1235,6 +1282,7 @@ class EngineConnection extends EventTarget {
if (closedPc && closedUDC && closedWS) {
// Do not notify the rest of the program that we have cut off anything.
this.state = { type: EngineConnectionStateType.Disconnected }
this.triggeredStart = false
}
}
}