// A stale build-output copy of the app's PrivacyInfo.xcprivacy (seen live: .native-build/apps/native/ios/App/App/) // must not be read as the app's own manifest by check / scan / privacy-manifest. Placeholder data only. import { afterAll, expect, test } from 'bun:test'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { isBuildCopyPath } from '../cli/lib/privacy-manifest'; import { detectProject } from '../cli/lib/scan/project'; const tmp = mkdtempSync(join(tmpdir(), 'sb-pm-copy-')); afterAll(() => rmSync(tmp, { recursive: true, force: true })); const manifest = (collected: boolean) => ` NSPrivacyTrackingNSPrivacyCollectedDataTypes${collected ? 'NSPrivacyCollectedDataTypeNSPrivacyCollectedDataTypeCrashDataNSPrivacyCollectedDataTypeLinkedNSPrivacyCollectedDataTypeTrackingNSPrivacyCollectedDataTypePurposesNSPrivacyCollectedDataTypePurposeAppFunctionality' : ''}NSPrivacyAccessedAPITypes`; test('isBuildCopyPath: hidden, build and copy folders are skipped, the real ios tree is not', () => { for (const p of ['.native-build/apps/native/ios/App/App/PrivacyInfo.xcprivacy', 'ios/build/App.app/PrivacyInfo.xcprivacy', 'DerivedData/x/PrivacyInfo.xcprivacy', 'dist/ios/PrivacyInfo.xcprivacy', '.output/PrivacyInfo.xcprivacy', 'node_modules/a/PrivacyInfo.xcprivacy']) expect(isBuildCopyPath(p)).toBe(true); for (const p of ['apps/native/ios/App/App/PrivacyInfo.xcprivacy', 'ios/App/App/PrivacyInfo.xcprivacy', 'PrivacyInfo.xcprivacy']) expect(isBuildCopyPath(p)).toBe(false); }); test('scan facts: the real manifest is found, the stale .native-build copy is not', () => { const real = join(tmp, 'apps/native/ios/App/App'); const copy = join(tmp, '.native-build/apps/native/ios/App/App'); mkdirSync(real, { recursive: true }); mkdirSync(copy, { recursive: true }); writeFileSync(join(real, 'PrivacyInfo.xcprivacy'), manifest(true)); writeFileSync(join(copy, 'PrivacyInfo.xcprivacy'), manifest(false)); expect(detectProject(tmp).privacyManifests.map(m => m.path)).toEqual(['apps/native/ios/App/App/PrivacyInfo.xcprivacy']); });