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:
@ -127,54 +127,54 @@ test.describe('Command bar tests', () => {
|
|||||||
await expect(commandLevelArgButton).toHaveText('level: project')
|
await expect(commandLevelArgButton).toHaveText('level: project')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Command bar keybinding works from code editor and can change a setting', async ({
|
test(
|
||||||
page,
|
'Command bar keybinding works from code editor and can change a setting',
|
||||||
homePage,
|
{ tag: ['@skipWin'] },
|
||||||
}) => {
|
async ({ page, homePage }) => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
|
|
||||||
// Put the cursor in the code editor
|
// Put the cursor in the code editor
|
||||||
await page.locator('.cm-content').click()
|
await page.locator('.cm-content').click()
|
||||||
|
|
||||||
// Now try the same, but with the keyboard shortcut, check focus
|
// Now try the same, but with the keyboard shortcut, check focus
|
||||||
await page.keyboard.press('ControlOrMeta+K')
|
await page.keyboard.press('ControlOrMeta+K')
|
||||||
|
|
||||||
let cmdSearchBar = page.getByPlaceholder('Search commands')
|
let cmdSearchBar = page.getByPlaceholder('Search commands')
|
||||||
await expect(cmdSearchBar).toBeVisible()
|
await expect(cmdSearchBar).toBeVisible()
|
||||||
await expect(cmdSearchBar).toBeFocused()
|
await expect(cmdSearchBar).toBeFocused()
|
||||||
|
|
||||||
// Try typing in the command bar
|
// Try typing in the command bar
|
||||||
await cmdSearchBar.fill('theme')
|
await cmdSearchBar.fill('theme')
|
||||||
const themeOption = page.getByRole('option', {
|
const themeOption = page.getByRole('option', {
|
||||||
name: 'Settings · app · theme',
|
name: 'Settings · app · theme',
|
||||||
})
|
})
|
||||||
await expect(themeOption).toBeVisible()
|
await expect(themeOption).toBeVisible()
|
||||||
await themeOption.click()
|
await themeOption.click()
|
||||||
const themeInput = page.getByPlaceholder('dark')
|
const themeInput = page.getByPlaceholder('dark')
|
||||||
await expect(themeInput).toBeVisible()
|
await expect(themeInput).toBeVisible()
|
||||||
await expect(themeInput).toBeFocused()
|
await expect(themeInput).toBeFocused()
|
||||||
// Select dark theme
|
// Select dark theme
|
||||||
await page.keyboard.press('ArrowDown')
|
await page.keyboard.press('ArrowDown')
|
||||||
await page.keyboard.press('ArrowDown')
|
await page.keyboard.press('ArrowDown')
|
||||||
await page.keyboard.press('ArrowDown')
|
await page.keyboard.press('ArrowDown')
|
||||||
await expect(page.getByRole('option', { name: 'system' })).toHaveAttribute(
|
await expect(
|
||||||
'data-headlessui-state',
|
page.getByRole('option', { name: 'system' })
|
||||||
'active'
|
).toHaveAttribute('data-headlessui-state', 'active')
|
||||||
)
|
await page.keyboard.press('Enter')
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
|
|
||||||
// Check the toast appeared
|
// Check the toast appeared
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(`Set theme to "system" as a user default`)
|
page.getByText(`Set theme to "system" as a user default`)
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
// Check that the theme changed
|
// Check that the theme changed
|
||||||
await expect(page.locator('body')).not.toHaveClass(`body-bg dark`)
|
await expect(page.locator('body')).not.toHaveClass(`body-bg dark`)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test('Can extrude from the command bar', async ({ page, homePage }) => {
|
test('Can extrude from the command bar', async ({ page, homePage }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
|
@ -966,106 +966,106 @@ test.describe('Editor tests', () => {
|
|||||||
|> close(%)`)
|
|> close(%)`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Can undo a sketch modification with ctrl+z', async ({
|
test(
|
||||||
page,
|
'Can undo a sketch modification with ctrl+z',
|
||||||
homePage,
|
{ tag: ['@skipWin'] },
|
||||||
}) => {
|
async ({ page, homePage }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn('XZ')
|
`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.61, -10.01], %)
|
|> startProfileAt([4.61, -10.01], %)
|
||||||
|> line([12.73, -0.09], %)
|
|> line([12.73, -0.09], %)
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5, %)`
|
|> extrude(5, %)`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'default_camera_look_at',
|
type: 'default_camera_look_at',
|
||||||
vantage: { x: 0, y: -1250, z: 580 },
|
vantage: { x: 0, y: -1250, z: 580 },
|
||||||
center: { x: 0, y: 0, z: 0 },
|
center: { x: 0, y: 0, z: 0 },
|
||||||
up: { x: 0, y: 0, z: 1 },
|
up: { x: 0, y: 0, z: 1 },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'default_camera_get_settings',
|
type: 'default_camera_get_settings',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
const startPX = [1200 / 2, 500 / 2]
|
const startPX = [1200 / 2, 500 / 2]
|
||||||
|
|
||||||
const dragPX = 40
|
const dragPX = 40
|
||||||
|
|
||||||
await page.getByText('startProfileAt([4.61, -10.01], %)').click()
|
await page.getByText('startProfileAt([4.61, -10.01], %)').click()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Edit Sketch' })
|
page.getByRole('button', { name: 'Edit Sketch' })
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
await page.waitForTimeout(400)
|
await page.waitForTimeout(400)
|
||||||
let prevContent = await page.locator('.cm-content').innerText()
|
let prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
|
||||||
|
|
||||||
// drag startProfileAt handle
|
// drag startProfileAt handle
|
||||||
await page.dragAndDrop('#stream', '#stream', {
|
await page.dragAndDrop('#stream', '#stream', {
|
||||||
sourcePosition: { x: startPX[0] + 68, y: startPX[1] + 147 },
|
sourcePosition: { x: startPX[0] + 68, y: startPX[1] + 147 },
|
||||||
targetPosition: { x: startPX[0] + dragPX, y: startPX[1] + dragPX },
|
targetPosition: { x: startPX[0] + dragPX, y: startPX[1] + dragPX },
|
||||||
})
|
})
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
prevContent = await page.locator('.cm-content').innerText()
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
|
||||||
// drag line handle
|
// drag line handle
|
||||||
// we wait so it saves the code
|
// we wait so it saves the code
|
||||||
await page.waitForTimeout(800)
|
await page.waitForTimeout(800)
|
||||||
|
|
||||||
const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
|
const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.dragAndDrop('#stream', '#stream', {
|
await page.dragAndDrop('#stream', '#stream', {
|
||||||
sourcePosition: { x: lineEnd.x - 5, y: lineEnd.y },
|
sourcePosition: { x: lineEnd.x - 5, y: lineEnd.y },
|
||||||
targetPosition: { x: lineEnd.x + dragPX, y: lineEnd.y + dragPX },
|
targetPosition: { x: lineEnd.x + dragPX, y: lineEnd.y + dragPX },
|
||||||
})
|
})
|
||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
prevContent = await page.locator('.cm-content').innerText()
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
|
||||||
// we wait so it saves the code
|
// we wait so it saves the code
|
||||||
await page.waitForTimeout(800)
|
await page.waitForTimeout(800)
|
||||||
|
|
||||||
// drag tangentialArcTo handle
|
// drag tangentialArcTo handle
|
||||||
const tangentEnd = await u.getBoundingBox('[data-overlay-index="1"]')
|
const tangentEnd = await u.getBoundingBox('[data-overlay-index="1"]')
|
||||||
await page.dragAndDrop('#stream', '#stream', {
|
await page.dragAndDrop('#stream', '#stream', {
|
||||||
sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 },
|
sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 },
|
||||||
targetPosition: {
|
targetPosition: {
|
||||||
x: tangentEnd.x + dragPX,
|
x: tangentEnd.x + dragPX,
|
||||||
y: tangentEnd.y + dragPX,
|
y: tangentEnd.y + dragPX,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line([15.4, -2.78], %)
|
|> line([15.4, -2.78], %)
|
||||||
|> tangentialArcTo([27.6, -3.05], %)
|
|> tangentialArcTo([27.6, -3.05], %)
|
||||||
@ -1073,26 +1073,26 @@ test.describe('Editor tests', () => {
|
|||||||
|> extrude(5, %)
|
|> extrude(5, %)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// Hit undo
|
// Hit undo
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
await page.keyboard.press('KeyZ')
|
await page.keyboard.press('KeyZ')
|
||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line([15.4, -2.78], %)
|
|> line([15.4, -2.78], %)
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5, %)`)
|
|> extrude(5, %)`)
|
||||||
|
|
||||||
// Hit undo again.
|
// Hit undo again.
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
await page.keyboard.press('KeyZ')
|
await page.keyboard.press('KeyZ')
|
||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line([12.73, -0.09], %)
|
|> line([12.73, -0.09], %)
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
@ -1100,20 +1100,21 @@ test.describe('Editor tests', () => {
|
|||||||
|> extrude(5, %)
|
|> extrude(5, %)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// Hit undo again.
|
// Hit undo again.
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
await page.keyboard.press('KeyZ')
|
await page.keyboard.press('KeyZ')
|
||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.61, -10.01], %)
|
|> startProfileAt([4.61, -10.01], %)
|
||||||
|> line([12.73, -0.09], %)
|
|> line([12.73, -0.09], %)
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5, %)`)
|
|> extrude(5, %)`)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test.fixme(
|
test.fixme(
|
||||||
`Can use the import stdlib function on a local OBJ file`,
|
`Can use the import stdlib function on a local OBJ file`,
|
||||||
|
@ -19,7 +19,7 @@ test.describe('integrations tests', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [clickObj] = await scene.makeMouseHelpers(600, 300)
|
const [clickObj] = await scene.makeMouseHelpers(726, 272)
|
||||||
|
|
||||||
await test.step('setup test', async () => {
|
await test.step('setup test', async () => {
|
||||||
await homePage.expectState({
|
await homePage.expectState({
|
||||||
@ -61,6 +61,7 @@ test.describe('integrations tests', () => {
|
|||||||
})
|
})
|
||||||
await test.step('setup for next assertion', async () => {
|
await test.step('setup for next assertion', async () => {
|
||||||
await toolbar.openFile('main.kcl')
|
await toolbar.openFile('main.kcl')
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
await clickObj()
|
await clickObj()
|
||||||
await scene.moveNoWhere()
|
await scene.moveNoWhere()
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
|
@ -89,18 +89,11 @@ export class HomePageFixture {
|
|||||||
* Maybe there a good sanity check we can do each time?
|
* Maybe there a good sanity check we can do each time?
|
||||||
*/
|
*/
|
||||||
expectState = async (expectedState: HomePageState) => {
|
expectState = async (expectedState: HomePageState) => {
|
||||||
await expect
|
await expect.poll(this._serialiseSortBy).toEqual(expectedState.sortBy)
|
||||||
.poll(async () => {
|
|
||||||
const [projectCards, sortBy] = await Promise.all([
|
for (const projectCard of expectedState.projectCards) {
|
||||||
this._serialiseProjectCards(),
|
await expect.poll(this._serialiseProjectCards).toContainEqual(projectCard)
|
||||||
this._serialiseSortBy(),
|
}
|
||||||
])
|
|
||||||
return {
|
|
||||||
projectCards,
|
|
||||||
sortBy,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toEqual(expectedState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
|
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
|
||||||
|
@ -62,7 +62,9 @@ export class ToolbarFixture {
|
|||||||
this.filePane = page.locator('#files-pane')
|
this.filePane = page.locator('#files-pane')
|
||||||
this.featureTreePane = page.locator('#feature-tree-pane')
|
this.featureTreePane = page.locator('#feature-tree-pane')
|
||||||
this.fileCreateToast = page.getByText('Successfully created')
|
this.fileCreateToast = page.getByText('Successfully created')
|
||||||
this.exeIndicator = page.getByTestId('model-state-indicator-execution-done')
|
this.exeIndicator = page.getByTestId(
|
||||||
|
'model-state-indicator-receive-reliable'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get logoLink() {
|
get logoLink() {
|
||||||
|
@ -2273,10 +2273,6 @@ radius = 8.69
|
|||||||
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve({angle = 360, axis = getOppositeEdge(rectangleSegmentA001)}, sketch002) `
|
const newCodeToFind = `revolve001 = revolve({angle = 360, axis = getOppositeEdge(rectangleSegmentA001)}, sketch002) `
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
@ -2328,10 +2324,6 @@ radius = 8.69
|
|||||||
const lineCodeToSelection = `|> xLine(2.6, %)`
|
const lineCodeToSelection = `|> xLine(2.6, %)`
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve({ angle = 360, axis = seg01 }, sketch003)`
|
const newCodeToFind = `revolve001 = revolve({ angle = 360, axis = seg01 }, sketch003)`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
|
@ -1527,34 +1527,32 @@ test(
|
|||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page, cmdBar, homePage }, testInfo) => {
|
async ({ context, page, cmdBar, homePage }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await Promise.all([
|
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
||||||
fsp.mkdir(path.join(dir, 'router-template-slate'), { recursive: true }),
|
recursive: true,
|
||||||
fsp.mkdir(path.join(dir, 'bracket'), { recursive: true }),
|
})
|
||||||
])
|
await fsp.copyFile(
|
||||||
await Promise.all([
|
path.join(
|
||||||
fsp.copyFile(
|
'src',
|
||||||
path.join(
|
'wasm-lib',
|
||||||
'src',
|
'tests',
|
||||||
'wasm-lib',
|
'executor',
|
||||||
'tests',
|
'inputs',
|
||||||
'executor',
|
'router-template-slate.kcl'
|
||||||
'inputs',
|
|
||||||
'router-template-slate.kcl'
|
|
||||||
),
|
|
||||||
path.join(dir, 'router-template-slate', 'main.kcl')
|
|
||||||
),
|
),
|
||||||
fsp.copyFile(
|
path.join(dir, 'router-template-slate', 'main.kcl')
|
||||||
path.join(
|
)
|
||||||
'src',
|
await fsp.mkdir(path.join(dir, 'bracket'), { recursive: true })
|
||||||
'wasm-lib',
|
await fsp.copyFile(
|
||||||
'tests',
|
path.join(
|
||||||
'executor',
|
'src',
|
||||||
'inputs',
|
'wasm-lib',
|
||||||
'focusrite_scarlett_mounting_braket.kcl'
|
'tests',
|
||||||
),
|
'executor',
|
||||||
path.join(dir, 'bracket', 'main.kcl')
|
'inputs',
|
||||||
|
'focusrite_scarlett_mounting_braket.kcl'
|
||||||
),
|
),
|
||||||
])
|
path.join(dir, 'bracket', 'main.kcl')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
@ -312,32 +312,40 @@ test.describe('Sketch tests', () => {
|
|||||||
|> line([1.97, 2.06], %)
|
|> line([1.97, 2.06], %)
|
||||||
|> close(%)`)
|
|> close(%)`)
|
||||||
}
|
}
|
||||||
test('code pane open at start-handles', async ({ page, homePage }) => {
|
test(
|
||||||
// Load the app with the code panes
|
'code pane open at start-handles',
|
||||||
await page.addInitScript(async () => {
|
{ tag: ['@skipWin'] },
|
||||||
localStorage.setItem(
|
async ({ page, homePage }) => {
|
||||||
'store',
|
// Load the app with the code panes
|
||||||
JSON.stringify({
|
await page.addInitScript(async () => {
|
||||||
state: {
|
localStorage.setItem(
|
||||||
openPanes: ['code'],
|
'store',
|
||||||
},
|
JSON.stringify({
|
||||||
version: 0,
|
state: {
|
||||||
})
|
openPanes: ['code'],
|
||||||
)
|
},
|
||||||
})
|
version: 0,
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, ['code'])
|
})
|
||||||
})
|
)
|
||||||
|
})
|
||||||
|
await doEditSegmentsByDraggingHandle(page, homePage, ['code'])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test('code pane closed at start-handles', async ({ page, homePage }) => {
|
test(
|
||||||
// Load the app with the code panes
|
'code pane closed at start-handles',
|
||||||
await page.addInitScript(async (persistModelingContext) => {
|
{ tag: ['@skipWin'] },
|
||||||
localStorage.setItem(
|
async ({ page, homePage }) => {
|
||||||
persistModelingContext,
|
// Load the app with the code panes
|
||||||
JSON.stringify({ openPanes: [] })
|
await page.addInitScript(async (persistModelingContext) => {
|
||||||
)
|
localStorage.setItem(
|
||||||
}, PERSIST_MODELING_CONTEXT)
|
persistModelingContext,
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, [])
|
JSON.stringify({ openPanes: [] })
|
||||||
})
|
)
|
||||||
|
}, PERSIST_MODELING_CONTEXT)
|
||||||
|
await doEditSegmentsByDraggingHandle(page, homePage, [])
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Can edit a circle center and radius by dragging its handles', async ({
|
test('Can edit a circle center and radius by dragging its handles', async ({
|
||||||
|
@ -209,5 +209,6 @@
|
|||||||
"wasm-pack": "^0.13.1",
|
"wasm-pack": "^0.13.1",
|
||||||
"ws": "^8.17.0",
|
"ws": "^8.17.0",
|
||||||
"yarn": "^1.22.22"
|
"yarn": "^1.22.22"
|
||||||
}
|
},
|
||||||
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,8 @@ class EngineConnection extends EventTarget {
|
|||||||
mediaStream?: MediaStream
|
mediaStream?: MediaStream
|
||||||
idleMode: boolean = false
|
idleMode: boolean = false
|
||||||
promise?: Promise<void>
|
promise?: Promise<void>
|
||||||
|
sdpAnswer?: Models['RtcSessionDescription_type']
|
||||||
|
triggeredStart = false
|
||||||
|
|
||||||
onIceCandidate = function (
|
onIceCandidate = function (
|
||||||
this: RTCPeerConnection,
|
this: RTCPeerConnection,
|
||||||
@ -553,6 +555,7 @@ class EngineConnection extends EventTarget {
|
|||||||
* did not establish.
|
* did not establish.
|
||||||
*/
|
*/
|
||||||
connect(reconnecting?: boolean): Promise<void> {
|
connect(reconnecting?: boolean): Promise<void> {
|
||||||
|
const that = this
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (this.isConnecting() || this.isReady()) {
|
if (this.isConnecting() || this.isReady()) {
|
||||||
return
|
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) => {
|
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) {
|
if (event.candidate === null) {
|
||||||
|
initiateConnectingExclusive()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +628,6 @@ class EngineConnection extends EventTarget {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request a candidate to use
|
|
||||||
this.send({
|
this.send({
|
||||||
type: 'trickle_ice',
|
type: 'trickle_ice',
|
||||||
candidate: {
|
candidate: {
|
||||||
@ -605,8 +637,38 @@ class EngineConnection extends EventTarget {
|
|||||||
usernameFragment: event.candidate.usernameFragment || undefined,
|
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?.('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) => {
|
this.onIceCandidateError = (_event: Event) => {
|
||||||
const event = _event as RTCPeerConnectionIceErrorEvent
|
const event = _event as RTCPeerConnectionIceErrorEvent
|
||||||
@ -634,6 +696,8 @@ class EngineConnection extends EventTarget {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
case 'connecting':
|
||||||
|
break
|
||||||
case 'disconnected':
|
case 'disconnected':
|
||||||
case 'failed':
|
case 'failed':
|
||||||
this.pc?.removeEventListener('icecandidate', this.onIceCandidate)
|
this.pc?.removeEventListener('icecandidate', this.onIceCandidate)
|
||||||
@ -1126,25 +1190,8 @@ class EngineConnection extends EventTarget {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// As soon as this is set, RTCPeerConnection tries to
|
this.sdpAnswer = answer
|
||||||
// establish a connection.
|
|
||||||
// @ts-ignore
|
|
||||||
// Have to ignore because dom.ts doesn't have the right type
|
|
||||||
void this.pc?.setRemoteDescription(answer)
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
type: EngineConnectionStateType.Connecting,
|
|
||||||
value: {
|
|
||||||
type: ConnectingType.SetRemoteDescription,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
type: EngineConnectionStateType.Connecting,
|
|
||||||
value: {
|
|
||||||
type: ConnectingType.WebRTCConnecting,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'trickle_ice':
|
case 'trickle_ice':
|
||||||
@ -1235,6 +1282,7 @@ class EngineConnection extends EventTarget {
|
|||||||
if (closedPc && closedUDC && closedWS) {
|
if (closedPc && closedUDC && closedWS) {
|
||||||
// Do not notify the rest of the program that we have cut off anything.
|
// Do not notify the rest of the program that we have cut off anything.
|
||||||
this.state = { type: EngineConnectionStateType.Disconnected }
|
this.state = { type: EngineConnectionStateType.Disconnected }
|
||||||
|
this.triggeredStart = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user