Compare commits
6 Commits
nested_dir
...
ryanrosell
Author | SHA1 | Date | |
---|---|---|---|
ce4b0771a1 | |||
9be36d4220 | |||
21f96db70b | |||
7ffc605267 | |||
ddb41c45e8 | |||
9293826cda |
@ -49,8 +49,15 @@ const commonPoints = {
|
|||||||
num1: 7.25,
|
num1: 7.25,
|
||||||
num2: 14.44,
|
num2: 14.44,
|
||||||
}
|
}
|
||||||
|
let log: { index: number; timestamp: number; payload: string | Buffer }[] = []
|
||||||
test.afterEach(async ({ context, page }, testInfo) => {
|
test.afterEach(async ({ context, page }, testInfo) => {
|
||||||
|
// attach the websocket logs to the html report
|
||||||
|
if (log?.length > 0)
|
||||||
|
await testInfo.attach(`WebSocket log`, {
|
||||||
|
body: String(
|
||||||
|
log.map((l) => `(${l.index})_${l.timestamp}_${l.payload}\n`).join('')
|
||||||
|
),
|
||||||
|
})
|
||||||
if (testInfo.status === 'skipped') return
|
if (testInfo.status === 'skipped') return
|
||||||
if (testInfo.status === 'failed') return
|
if (testInfo.status === 'failed') return
|
||||||
|
|
||||||
@ -91,6 +98,32 @@ test.beforeEach(async ({ context, page }) => {
|
|||||||
)
|
)
|
||||||
// kill animations, speeds up tests and reduced flakiness
|
// kill animations, speeds up tests and reduced flakiness
|
||||||
await page.emulateMedia({ reducedMotion: 'reduce' })
|
await page.emulateMedia({ reducedMotion: 'reduce' })
|
||||||
|
// get playwright to listen for websocket messages
|
||||||
|
page.on('websocket', (ws) => {
|
||||||
|
console.log(`WebSocket opened: ${ws.url()}>`)
|
||||||
|
ws.on('framesent', (event) =>
|
||||||
|
log.push({
|
||||||
|
index: log.length,
|
||||||
|
timestamp: new Date().valueOf(),
|
||||||
|
payload: event.payload,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
ws.on('framereceived', (event) =>
|
||||||
|
log.push({
|
||||||
|
index: log.length,
|
||||||
|
timestamp: new Date().valueOf(),
|
||||||
|
payload: event.payload,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
ws.on('close', () =>
|
||||||
|
log.push({
|
||||||
|
index: log.length,
|
||||||
|
timestamp: new Date().valueOf(),
|
||||||
|
payload: 'Websocket closed',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await page.goto('/')
|
||||||
})
|
})
|
||||||
|
|
||||||
test.setTimeout(120000)
|
test.setTimeout(120000)
|
||||||
@ -7173,7 +7206,90 @@ test.describe('Test network and connection issues', () => {
|
|||||||
await expect(networkToggle).toContainText('Connected')
|
await expect(networkToggle).toContainText('Connected')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Engine disconnect & reconnect in sketch mode', async ({
|
async function waitForWSMessage(
|
||||||
|
action: Promise<void>,
|
||||||
|
waitForCommand:
|
||||||
|
| 'select_with_point'
|
||||||
|
| 'set_selection_filter'
|
||||||
|
| 'default_camera_set_orthographic'
|
||||||
|
| 'select_add',
|
||||||
|
timeout = 5_000
|
||||||
|
) {
|
||||||
|
const actionTimestamp = new Date().valueOf()
|
||||||
|
const logCursor = log.length
|
||||||
|
await action
|
||||||
|
const delay = 10
|
||||||
|
const attempts = timeout / delay
|
||||||
|
for (let i = 0; i < attempts; i += 1) {
|
||||||
|
const cmdFound = findMatchingWsEvent(actionTimestamp, waitForCommand)
|
||||||
|
if (cmdFound) {
|
||||||
|
// command found, now wait for the success message
|
||||||
|
// by waiting on the matching success response corresponding to the request_id
|
||||||
|
const cmdId = safeParseJson(String(cmdFound.payload)).cmd_id
|
||||||
|
const successMessage = findSuccessResponse(actionTimestamp, cmdId)
|
||||||
|
if (successMessage) {
|
||||||
|
console.log(`✅ "${waitForCommand}" was found in the websocket logs`)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, delay))
|
||||||
|
}
|
||||||
|
console.log(`⚠️ "${waitForCommand}" was not found in the websocket logs`)
|
||||||
|
console.log(
|
||||||
|
`\t inspect the websocket logs between (${logCursor})th and (${log.length})th event`
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
|
||||||
|
function findSuccessResponse(timestamp: number, cmdId: string) {
|
||||||
|
// filter the logs to only show entries with timestamp greater than the timestamp of the command
|
||||||
|
const relevantLogEntries = log.filter((wsEvent) => {
|
||||||
|
try {
|
||||||
|
return wsEvent && wsEvent.timestamp > timestamp
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return relevantLogEntries?.find((wsEvent) => {
|
||||||
|
try {
|
||||||
|
const jsonObj = safeParseJson(String(wsEvent.payload))
|
||||||
|
return jsonObj && jsonObj.request_id === cmdId && jsonObj.success
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function findMatchingWsEvent(timestamp: number, cmdType: string) {
|
||||||
|
// filter the logs to only show entries with timestamp greater
|
||||||
|
// than the timestamp of when the playwright action was performed
|
||||||
|
const relevantLogEntries = log.filter((wsEvent) => {
|
||||||
|
try {
|
||||||
|
return wsEvent && wsEvent.timestamp > timestamp
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return relevantLogEntries.find((wsEvent) => {
|
||||||
|
try {
|
||||||
|
const wsMessage = safeParseJson(String(wsEvent.payload))
|
||||||
|
return wsMessage && wsMessage.cmd && wsMessage.cmd.type === cmdType
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeParseJson(jsonString: string) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(jsonString)
|
||||||
|
} catch (error) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test.only('Engine disconnect & reconnect in sketch mode', async ({
|
||||||
page,
|
page,
|
||||||
browserName,
|
browserName,
|
||||||
}) => {
|
}) => {
|
||||||
@ -7197,20 +7313,33 @@ test.describe('Test network and connection issues', () => {
|
|||||||
|
|
||||||
// click on "Start Sketch" button
|
// click on "Start Sketch" button
|
||||||
await u.clearCommandLogs()
|
await u.clearCommandLogs()
|
||||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
await waitForWSMessage(
|
||||||
await page.waitForTimeout(100)
|
page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
|
'set_selection_filter'
|
||||||
|
)
|
||||||
|
// ^ this is similar to ⤵️
|
||||||
|
// await u.doAndWaitForCmd(
|
||||||
|
// () => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
|
// 'set_selection_filter'
|
||||||
|
// )
|
||||||
|
|
||||||
// select a plane
|
// select a plane
|
||||||
await page.mouse.click(700, 200)
|
await waitForWSMessage(
|
||||||
|
page.mouse.click(700, 200),
|
||||||
|
'default_camera_set_orthographic'
|
||||||
|
)
|
||||||
|
// ^ this is similar to ⤵️
|
||||||
|
// await u.doAndWaitForCmd(
|
||||||
|
// () => page.mouse.click(700, 200),
|
||||||
|
// 'default_camera_set_orthographic'
|
||||||
|
// )
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`const sketch001 = startSketchOn('XZ')`
|
`const sketch001 = startSketchOn('XZ')`
|
||||||
)
|
)
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
|
||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
|
// The issue is that these types of interactions do not trigger any WebSocket messages for synchronization. :( ⤵️
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||||
@ -7218,8 +7347,6 @@ test.describe('Test network and connection issues', () => {
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||||
await page.waitForTimeout(100)
|
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt(${commonPoints.startAt}, %)
|
|> startProfileAt(${commonPoints.startAt}, %)
|
||||||
|
Reference in New Issue
Block a user