Skip to content

Commit 1dbcec9

Browse files
committed
improvement(desktop): retype and resend a message the hydrating composer dropped
1 parent f4daf79 commit 1dbcec9

1 file changed

Lines changed: 24 additions & 14 deletions

File tree

‎apps/desktop/e2e/desktop-tools-live-sim.spec.ts‎

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,28 +176,31 @@ test.describe('desktop tools against a live Sim', () => {
176176

177177
const composer = (page: Page) => page.getByRole('textbox').last()
178178

179+
/** The dev app's error overlay, if it is up, with the errors the window reported. */
180+
async function devOverlayError(page: Page): Promise<string | undefined> {
181+
const overlay = page.locator('nextjs-portal [data-nextjs-dialog]')
182+
if ((await overlay.count()) === 0) return undefined
183+
return `Next.js error overlay: ${await overlay.first().innerText()}\n${pageErrors.join('\n')}`
184+
}
185+
179186
/**
180187
* Clicks `target`, failing at once with the dev app's error instead of waiting out a click the
181188
* Next.js error overlay intercepts.
182189
*/
183190
async function click(page: Page, target: Locator, timeout = 15_000): Promise<void> {
184-
const overlay = page.locator('nextjs-portal [data-nextjs-dialog]')
185-
const blocked = async () =>
186-
(await overlay.count()) > 0
187-
? `Next.js error overlay: ${await overlay.first().innerText()}\n${pageErrors.join('\n')}`
188-
: undefined
189-
const before = await blocked()
191+
const before = await devOverlayError(page)
190192
if (before) throw new Error(before)
191193
try {
192194
await target.click({ timeout })
193195
} catch (error) {
194-
throw new Error((await blocked()) ?? String(error))
196+
throw new Error((await devOverlayError(page)) ?? String(error))
195197
}
196198
}
197199

198200
/**
199201
* Sends `message` and waits until the turn reached Sim. A page still hydrating can drop the
200-
* typed text or the click, so the message is typed and sent again only while no turn went out.
202+
* typed text (the Send button only shows for a non-empty message) or the click, so the message
203+
* is typed and sent again only while no turn went out.
201204
*/
202205
async function send(page: Page, message: string, timeout = 60_000): Promise<void> {
203206
const since = Date.now()
@@ -207,13 +210,20 @@ test.describe('desktop tools against a live Sim', () => {
207210
.some((entry) => entry.method === 'POST' && entry.path === '/api/mothership/chat')
208211
const deadline = Date.now() + timeout
209212
while (!sent()) {
213+
const overlay = await devOverlayError(page)
214+
if (overlay) throw new Error(overlay)
210215
if (Date.now() > deadline) throw new Error(`The message was never sent: ${message}`)
211216
if ((await composer(page).inputValue()) !== message) await composer(page).fill(message)
212-
await click(page, page.getByRole('button', { name: 'Send message' }))
213-
await expect
214-
.poll(sent, { timeout: 10_000 })
215-
.toBe(true)
216-
.catch(() => {})
217+
const clicked = await page
218+
.getByRole('button', { name: 'Send message' })
219+
.click({ timeout: 5_000 })
220+
.then(() => true)
221+
.catch(() => false)
222+
if (clicked)
223+
await expect
224+
.poll(sent, { timeout: 10_000 })
225+
.toBe(true)
226+
.catch(() => {})
217227
}
218228
}
219229

@@ -224,7 +234,7 @@ test.describe('desktop tools against a live Sim', () => {
224234
title: string,
225235
timeout = 30_000
226236
): Promise<void> {
227-
await click(page, page.getByRole('link', { name: title }).first())
237+
await click(page, page.getByRole('link', { name: title }).first(), timeout)
228238
await expect(page).toHaveURL(new RegExp(`${user.chats[title]}$`), { timeout })
229239
}
230240

0 commit comments

Comments
 (0)