mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
refactor(scanner): type plist and file-api helpers
Convert the scanner's plist parser and Node-style file shim to TypeScript and add small unit tests so common parser and file-reader failures are caught before we need to lean on Playwright or the higher-level scanner test. Constraint: Must preserve current scanner behavior while tightening the lowest-level helper surface Rejected: Jump straight to Mach-O parser conversion | harder to isolate regressions without first proving the smaller helper-test pattern Confidence: high Scope-risk: narrow Reversibility: clean Directive: Add small module-level regression tests for repeatable scanner breakage before expanding browser coverage Tested: pnpm run typecheck; pnpm exec vitest run test/scanner/plist.test.ts test/scanner/file-api.test.ts test/scanner/client.test.ts; pnpm run test; pnpm run test:browser Not-tested: Production deploy behavior prior to push
This commit is contained in:
parent
6d858d2a19
commit
cd41143f0d
7 changed files with 851 additions and 723 deletions
72
test/scanner/file-api.test.ts
Normal file
72
test/scanner/file-api.test.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import { Buffer } from 'buffer'
|
||||
|
||||
import {
|
||||
describe,
|
||||
expect,
|
||||
it
|
||||
} from 'vitest'
|
||||
|
||||
import {
|
||||
File,
|
||||
FileReader,
|
||||
type FileReaderLoadEvent
|
||||
} from '~/helpers/scanner/file-api'
|
||||
|
||||
describe( 'scanner file api shim', () => {
|
||||
it( 'constructs a file from a buffer payload', () => {
|
||||
const file = new File({
|
||||
buffer: Buffer.from( 'hello world', 'utf8' ),
|
||||
name: 'hello.txt',
|
||||
type: 'text/plain'
|
||||
})
|
||||
|
||||
expect( file.name ).toBe( 'hello.txt' )
|
||||
expect( file.type ).toBe( 'text/plain' )
|
||||
expect( file.size ).toBe( 11 )
|
||||
} )
|
||||
|
||||
it( 'reads text content through the node FileReader shim', async () => {
|
||||
const file = new File({
|
||||
buffer: Buffer.from( 'scanner-text', 'utf8' ),
|
||||
name: 'scanner.txt',
|
||||
type: 'text/plain'
|
||||
})
|
||||
const reader = new FileReader()
|
||||
|
||||
const loadedText = await new Promise<string>( ( resolve, reject ) => {
|
||||
reader.onerror = reject
|
||||
reader.onload = event => {
|
||||
const loadEvent = event as FileReaderLoadEvent
|
||||
|
||||
resolve( String( loadEvent.target.result ) )
|
||||
}
|
||||
|
||||
reader.readAsText( file )
|
||||
} )
|
||||
|
||||
expect( loadedText ).toBe( 'scanner-text' )
|
||||
} )
|
||||
|
||||
it( 'reads binary content through the node FileReader shim', async () => {
|
||||
const file = new File({
|
||||
buffer: Buffer.from( [ 0xde, 0xad, 0xbe, 0xef ] ),
|
||||
name: 'scanner.bin',
|
||||
type: 'application/octet-stream'
|
||||
})
|
||||
const reader = new FileReader()
|
||||
|
||||
const loadedBuffer = await new Promise<Buffer>( ( resolve, reject ) => {
|
||||
reader.onerror = reject
|
||||
reader.onload = event => {
|
||||
const loadEvent = event as FileReaderLoadEvent
|
||||
|
||||
resolve( loadEvent.target.nodeBufferResult )
|
||||
}
|
||||
|
||||
reader.readAsArrayBuffer( file )
|
||||
} )
|
||||
|
||||
expect( Buffer.isBuffer( loadedBuffer ) ).toBe( true )
|
||||
expect( loadedBuffer.toString( 'hex' ) ).toBe( 'deadbeef' )
|
||||
} )
|
||||
} )
|
||||
52
test/scanner/plist.test.ts
Normal file
52
test/scanner/plist.test.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { Buffer } from 'buffer'
|
||||
|
||||
import {
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
vi
|
||||
} from 'vitest'
|
||||
|
||||
import {
|
||||
parseFileSync,
|
||||
parsePlistBuffer
|
||||
} from '~/helpers/scanner/parsers/plist'
|
||||
|
||||
type ParsedPlist = Record<string, string>
|
||||
|
||||
const xmlPlist = Buffer.from( [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
||||
'<plist version="1.0">',
|
||||
'<dict>',
|
||||
' <key>CFBundleExecutable</key>',
|
||||
' <string>Playwright Native App</string>',
|
||||
' <key>CFBundleIdentifier</key>',
|
||||
' <string>com.doesitarm.playwright-native-app</string>',
|
||||
'</dict>',
|
||||
'</plist>'
|
||||
].join( '\n' ), 'utf8' )
|
||||
|
||||
describe( 'plist parser', () => {
|
||||
it( 'parses xml plist buffers asynchronously', async () => {
|
||||
const callback = vi.fn()
|
||||
const plist = await parsePlistBuffer( xmlPlist as any, callback ) as ParsedPlist
|
||||
|
||||
expect( plist.CFBundleExecutable ).toBe( 'Playwright Native App' )
|
||||
expect( plist.CFBundleIdentifier ).toBe( 'com.doesitarm.playwright-native-app' )
|
||||
expect( callback ).toHaveBeenCalledWith( null, plist )
|
||||
} )
|
||||
|
||||
it( 'parses xml plist buffers synchronously', () => {
|
||||
const plist = parseFileSync( xmlPlist as any ) as ParsedPlist
|
||||
|
||||
expect( plist.CFBundleExecutable ).toBe( 'Playwright Native App' )
|
||||
expect( plist.CFBundleIdentifier ).toBe( 'com.doesitarm.playwright-native-app' )
|
||||
} )
|
||||
|
||||
it( 'rejects invalid plist data', async () => {
|
||||
await expect( parsePlistBuffer( Buffer.from( 'not-a-plist', 'utf8' ) as any ) )
|
||||
.rejects
|
||||
.toThrow( /Invalid binary plist/i )
|
||||
} )
|
||||
} )
|
||||
Loading…
Add table
Add a link
Reference in a new issue