2026-08-22 16:02:10 +02:00
import { expect , test } from '@playwright/test'
2026-08-22 17:02:30 +02:00
test ( 'pasting, connecting, and citing one patent screenshot completes the Scene 7 report lesson' , async ({ page , request }) => {
2026-08-22 16:02:10 +02:00
test . setTimeout ( 60 _000 )
2026-08-22 23:19:46 +02:00
const pageErrors :Error [] = []
page . on ( 'pageerror' , error => pageErrors . push ( error ))
let sceneSeven : { id :string } | undefined
await expect . poll ( async () => {
const levels = await ( await request . get ( '/api/levels' )). json () as { id :string }[]
sceneSeven = levels . find ( level => level . id . startsWith ( 'barricelli-inventor-proof-case-' ))
return Boolean ( sceneSeven )
},{ timeout :20_000 , message : 'Scene 7 playable clone should be seeded' }). toBe ( true )
2026-08-22 16:02:10 +02:00
if ( ! sceneSeven ) throw new Error ( 'Scene 7 playable clone was not seeded' )
2026-08-22 23:19:46 +02:00
const sceneSevenId = sceneSeven . id
2026-08-22 16:02:10 +02:00
2026-08-22 23:19:46 +02:00
await page . goto ( `/level/ ${ sceneSevenId } ` )
await page . waitForTimeout ( 250 )
if ( pageErrors . length ) throw new Error ( `Scene 7 failed to render: ${ pageErrors . map ( error => error . message ). join ( '; ' ) } ` )
2026-08-22 16:02:10 +02:00
await expect ( page . getByRole ( 'heading' , { name : 'The Barricelli Files' })). toBeVisible ()
await expect ( page . locator ( '.brief-panel' )). toBeVisible ()
await expect ( page . locator ( '.brief-goals' )). toContainText ( 'Prove Nils Aall Barricelli was an inventor' )
await expect ( page . locator ( '.brief-goals section' )). toHaveClass ( /\bpending\b/ )
await page . getByRole ( 'button' , { name : 'BEGIN INVESTIGATION' , exact :true }). click ()
const uploadResponse = page . waitForResponse ( response => response . request (). method () === 'POST'
2026-08-22 23:19:46 +02:00
&& response . url (). includes ( `/api/levels/ ${ sceneSevenId } /documents` ) && response . status () === 201 )
2026-08-22 16:02:10 +02:00
await page . evaluate ( async () => {
const canvas = document . createElement ( 'canvas' )
canvas . width = 1280
canvas . height = 520
const context = canvas . getContext ( '2d' ) !
context . fillStyle = '#fff'
context . fillRect ( 0 , 0 , canvas . width , canvas . height )
context . fillStyle = '#111'
context . font = 'bold 56px Arial, sans-serif'
context . fillText ( 'GB695913A' , 70 , 95 )
context . font = '48px Arial, sans-serif'
context . fillText ( 'Improved chest of drawers' , 70 , 175 )
context . font = '34px Arial, sans-serif'
context . fillText ( 'Inventor' , 70 , 280 )
context . font = 'bold 52px Arial, sans-serif'
context . fillText ( 'Nils Aall Barricelli' , 70 , 355 )
context . font = '30px Arial, sans-serif'
context . fillText ( 'Priority date 1951-05-31 Publication date 1953-08-19' , 70 , 445 )
const blob = await new Promise < Blob >(( resolve , reject ) => canvas . toBlob ( value => value ? resolve ( value ) : reject ( new Error ( 'Could not render screenshot' )), 'image/png' ))
const transfer = new DataTransfer ()
transfer . items . add ( new File ([ blob ], 'google-patents.png' , { type : 'image/png' }))
window . dispatchEvent ( new ClipboardEvent ( 'paste' , { clipboardData :transfer , bubbles :true , cancelable :true }))
})
const uploaded = await ( await uploadResponse ). json ()
expect ( uploaded . analysis ). toMatchObject ({ extractionStatus : 'succeeded' , matchedFlags : [ 'scene7.nils_inventor_proved' ],
goals : [ expect . objectContaining ({ key : 'barricelli.inventor-proof' , status : 'complete' , newlyCompleted :true })] })
2026-08-22 19:28:06 +02:00
await expect ( page . getByRole ( 'dialog' ,{ name : 'What kind of evidence is this?' })). toBeVisible ()
await page . getByRole ( 'button' ,{ name : 'Classify as Clip' }). click ()
2026-08-22 16:02:10 +02:00
await expect ( page . locator ( '.source-file-widget' )). toHaveCount ( 1 )
2026-08-22 19:28:06 +02:00
await expect ( page . locator ( '.source-file-widget' )). toHaveAttribute ( 'data-capture-kind' , 'clipping' )
2026-08-22 23:19:46 +02:00
await expect ( page . locator ( '.source-file-widget > strong' )). toHaveCount ( 0 )
2026-08-22 16:02:10 +02:00
await expect ( page . locator ( '.source-file-widget' )). toHaveClass ( /\barriving\b/ )
2026-08-22 17:02:30 +02:00
await expect ( page . locator ( '.goal-complete-card' )). toHaveCount ( 0 )
await expect ( page . locator ( '.evidence-card.claim' )). toContainText ( 'Nils Aall Barricelli was an inventor' )
2026-08-22 19:28:06 +02:00
await page . locator ( '.source-file-widget' ). dblclick ()
await page . getByRole ( 'button' ,{ name : 'TYPE' , exact :true }). click ()
await page . getByRole ( 'menuitemradio' ,{ name : /Mugshot/ }). click ()
await expect ( page . locator ( '.source-file-widget' )). toHaveAttribute ( 'data-capture-kind' , 'photo' )
await page . getByRole ( 'button' ,{ name : 'TYPE' , exact :true }). click ()
await page . getByRole ( 'menuitemradio' ,{ name : /Clip/ }). click ()
await expect ( page . locator ( '.source-file-widget' )). toHaveAttribute ( 'data-capture-kind' , 'clipping' )
await page . getByRole ( 'button' ,{ name : 'FILE' , exact :true }). click ()
await page . getByRole ( 'menuitem' ,{ name : /INFO/ }). click ()
await expect ( page . getByLabel ( 'Board presentation' )). toHaveValue ( 'clipping' )
2026-08-22 23:19:46 +02:00
await expect ( page . getByLabel ( 'Document title' )). toHaveValue ( '' )
await page . getByLabel ( 'Published date' ). fill ( '1953-08-19' )
await expect ( page . getByLabel ( 'Published time' )). toHaveValue ( '' )
await page . getByLabel ( 'Source publication' ). fill ( 'Google Patents · GB695913A' )
await page . getByLabel ( 'Source URL' ). fill ( 'https://patents.google.com/patent/GB695913A/en' )
await page . getByRole ( 'button' ,{ name : 'SAVE METADATA' }). click ()
await expect ( page . locator ( '.file-editor' )). toHaveCount ( 0 )
await page . getByRole ( 'button' ,{ name : 'FILE' , exact :true }). click ()
await page . getByRole ( 'menuitem' ,{ name : /INFO/ }). click ()
await expect ( page . getByLabel ( 'Document title' )). toHaveValue ( 'Google Patents · GB695913A' )
await expect ( page . getByLabel ( 'Source publication' )). toHaveValue ( 'Google Patents · GB695913A' )
2026-08-22 19:28:06 +02:00
await page . getByRole ( 'button' ,{ name : 'Close file editor' }). click ()
2026-08-22 23:19:46 +02:00
await page . getByRole ( 'button' ,{ name : 'Close document' , exact :true }). click ()
2026-08-22 19:28:06 +02:00
2026-08-22 17:02:30 +02:00
await page . locator ( '.evidence-card.claim' ). click ()
await page . getByRole ( 'button' ,{ name : 'Red thread' }). click ()
await page . locator ( '.source-file-widget' ). click ()
await expect ( page . locator ( '.thread-editor' )). toBeVisible ()
await expect ( page . getByLabel ( 'Thread tag' )). toHaveValue ( 'Proof that…' )
2026-08-22 23:19:46 +02:00
await page . getByLabel ( 'Thread tag' ). fill ( 'Proof that Nils Aall Barricelli is named as inventor on patent GB695913A.' )
2026-08-22 17:02:30 +02:00
await page . getByRole ( 'button' ,{ name : 'ADD TAG & TIGHTEN' }). click ()
await page . getByRole ( 'button' ,{ name : 'Case report' }). click ()
await expect ( page . locator ( '.case-report' )). toBeVisible ()
await expect ( page . locator ( '.report-claim' )). toContainText ( 'Nils Aall Barricelli was an inventor' )
await expect ( page . locator ( '.report-evidence' )). toContainText ( 'Exhibit 1' )
2026-08-22 23:19:46 +02:00
await expect ( page . locator ( '.report-evidence' )). toContainText ( 'Proof that Nils Aall Barricelli is named as inventor on patent GB695913A.' )
await expect ( page . locator ( '.report-evidence' )). toContainText ( '1953-08-19' )
await expect ( page . locator ( '.report-evidence' )). toContainText ( 'Google Patents · GB695913A' )
await expect ( page . locator ( '.report-evidence a' )). toHaveAttribute ( 'href' , 'https://patents.google.com/patent/GB695913A/en' )
2026-08-22 17:02:30 +02:00
await page . getByRole ( 'button' ,{ name : 'SUBMIT CASE REPORT' }). click ()
await expect ( page . locator ( '.report-verdict' )). toContainText ( 'Case report accepted' )
await expect ( page . getByRole ( 'button' ,{ name : /CLOSE CASE/ })). toBeVisible ()
2026-08-22 16:02:10 +02:00
2026-08-22 23:19:46 +02:00
const level = await ( await request . get ( `/api/levels/ ${ sceneSevenId } ` )). json ()
2026-08-22 16:02:10 +02:00
expect ( level . goals ). toEqual ([ expect . objectContaining ({ key : 'barricelli.inventor-proof' , status : 'complete' , newlyCompleted :false })])
2026-08-22 23:19:46 +02:00
const savedDocuments = level . exhibits . filter (( exhibit : { type : string }) => exhibit . type === 'document' )
expect ( savedDocuments ). toEqual ([
expect . objectContaining ({ title : 'Google Patents · GB695913A' , captureKind : 'clipping' , width :230 , height :290 }),
2026-08-22 19:28:06 +02:00
])
2026-08-22 23:19:46 +02:00
expect ( savedDocuments [ 0 ]. rotation ). toBeGreaterThanOrEqual ( - 10 )
expect ( savedDocuments [ 0 ]. rotation ). toBeLessThanOrEqual ( 10 )
2026-08-22 17:02:30 +02:00
expect ( level . report ). toMatchObject ({ status : 'accepted' , investigatorName : 'Player' })
2026-08-22 16:02:10 +02:00
})