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,
|
||||
num2: 14.44,
|
||||
}
|
||||
|
||||
let log: { index: number; timestamp: number; payload: string | Buffer }[] = []
|
||||
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 === 'failed') return
|
||||
|
||||
@ -91,6 +98,32 @@ test.beforeEach(async ({ context, page }) => {
|
||||
)
|
||||
// kill animations, speeds up tests and reduced flakiness
|
||||
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)
|
||||
@ -7173,7 +7206,90 @@ test.describe('Test network and connection issues', () => {
|
||||
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,
|
||||
browserName,
|
||||
}) => {
|
||||
@ -7197,20 +7313,33 @@ test.describe('Test network and connection issues', () => {
|
||||
|
||||
// click on "Start Sketch" button
|
||||
await u.clearCommandLogs()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
await waitForWSMessage(
|
||||
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
|
||||
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(
|
||||
`const sketch001 = startSketchOn('XZ')`
|
||||
)
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
||||
|
||||
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 expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||
@ -7218,8 +7347,6 @@ test.describe('Test network and connection issues', () => {
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|
Reference in New Issue
Block a user