mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
test(mobile): time the artifact image against the frame's attachment
CI's second read showed the frame did issue the request -- it has a resource-timing entry and decode rejected with EncodingError -- while the rig saw only the CSS background, and a fresh image created later from the same frame was both issued and seen. The remaining question is whether the entry starts before anything was listening to that frame. So the entry is now reported in full for the element under test: responseStatus, transferSize, encodedBodySize, nextHopProtocol, startTime and duration. A zero status with a zero transferSize is a fetch that reached the network stack and came back with nothing, which is what an unintercepted request looks like once `.invalid` fails to resolve. Both sides of the comparison get a wall clock: `Target.attachedToTarget` and Playwright's own `frameattached` now carry the moment they fired, and every recorded request carries the moment it was seen. An entry that starts before the attachment is the race stated rather than inferred. Abort path only; the passing run is unchanged. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
This commit is contained in:
@@ -61,6 +61,21 @@ async function describeImageEvidence(page, frame, { originPrefix, requestLog, pa
|
||||
// Every subresource this document actually fetched, from the document's own side. An entry
|
||||
// here for a URL the rig never saw would mean the request left the frame and died before it.
|
||||
resources: performance.getEntriesByType('resource').map((one) => one.name),
|
||||
// The same entry in full for the element under test. A zero `responseStatus` with a zero
|
||||
// `transferSize` is a fetch that reached the network stack and came back with no response,
|
||||
// which is what a request the rig never intercepted looks like once the host cannot resolve;
|
||||
// `startTime` is what an attachment time is early or late against.
|
||||
remoteTiming: performance
|
||||
.getEntriesByType('resource')
|
||||
.filter((one) => one.name === remote?.src)
|
||||
.map((one) => ({
|
||||
responseStatus: one.responseStatus ?? null,
|
||||
transferSize: one.transferSize,
|
||||
encodedBodySize: one.encodedBodySize,
|
||||
nextHopProtocol: one.nextHopProtocol,
|
||||
startTime: Math.round(one.startTime),
|
||||
duration: Math.round(one.duration)
|
||||
})),
|
||||
navigations: performance.getEntriesByType('navigation').map((one) => one.type),
|
||||
remote: remote
|
||||
? {
|
||||
|
||||
@@ -27,9 +27,15 @@ export async function recordRequestsTo(page, originPrefix) {
|
||||
|
||||
page.on('request', (request) => {
|
||||
if (request.url().startsWith(originPrefix)) {
|
||||
asked.push(request.url())
|
||||
asked.push({ url: request.url(), at: Math.round(performance.now()) })
|
||||
}
|
||||
})
|
||||
// When this page first had any frame at all, so an attachment time has something to be early or
|
||||
// late against.
|
||||
const frameAttached = []
|
||||
page.on('frameattached', (frame) => {
|
||||
frameAttached.push({ url: frame.url(), at: Math.round(performance.now()) })
|
||||
})
|
||||
page.on('requestfailed', (request) => {
|
||||
if (request.url().startsWith(originPrefix)) {
|
||||
failed.push({ url: request.url(), errorText: request.failure()?.errorText ?? null })
|
||||
@@ -47,7 +53,13 @@ export async function recordRequestsTo(page, originPrefix) {
|
||||
// Playwright did record. Flattened auto-attach puts each child target on this same connection,
|
||||
// and `Network.enable` on the child is what makes its requests visible here.
|
||||
cdp.on('Target.attachedToTarget', (event) => {
|
||||
attached.push({ type: event.targetInfo?.type ?? null, url: event.targetInfo?.url ?? null })
|
||||
// The moment, not just the fact: a request whose resource-timing entry starts before this was
|
||||
// issued by a frame nothing was listening to yet, which is a different bug from a refusal.
|
||||
attached.push({
|
||||
type: event.targetInfo?.type ?? null,
|
||||
url: event.targetInfo?.url ?? null,
|
||||
at: Math.round(performance.now())
|
||||
})
|
||||
cdp.send('Network.enable', {}, event.sessionId).catch(() => {})
|
||||
})
|
||||
await cdp
|
||||
@@ -83,8 +95,8 @@ export async function recordRequestsTo(page, originPrefix) {
|
||||
}
|
||||
|
||||
return {
|
||||
asked: () => [...asked],
|
||||
asked: () => asked.map((one) => one.url),
|
||||
describe: () =>
|
||||
`asked ${JSON.stringify(asked)}; failed ${JSON.stringify(failed)}; cdp ${cdp ? 'on' : 'off'} attached ${JSON.stringify(attached)} sent ${JSON.stringify(sent)}; cdp loadingFailed ${JSON.stringify(loadingFailed)}`
|
||||
`asked ${JSON.stringify(asked)}; failed ${JSON.stringify(failed)}; frameAttached ${JSON.stringify(frameAttached)}; cdp ${cdp ? 'on' : 'off'} attached ${JSON.stringify(attached)} sent ${JSON.stringify(sent)}; cdp loadingFailed ${JSON.stringify(loadingFailed)}`
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user