// Integration tests for injectNavigatorStealth / 隐身导航注入集成测试 import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { chromium } from 'playwright-extra'; import StealthPlugin from 'puppeteer-extra-plugin-stealth'; import type { Browser, BrowserContext } from 'playwright'; import type { FingerprintProfile } from '@visionl/core'; import { injectNavigatorStealth } from '../stealth/navigator.js'; chromium.use(StealthPlugin()); const integration = process.env.VISIONL_INTEGRATION === '1' ? describe : describe.skip; const testProfile: FingerprintProfile = { id: 'fp_stealth_nav', name: 'Stealth Navigator Test', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', platform: 'Win32', languages: ['en-US', 'en'], acceptLanguage: 'en-US,en;q=0.9', screen: { width: 1920, height: 1080, colorDepth: 24, pixelRatio: 1 }, viewport: { width: 1280, height: 720 }, webgl: { vendor: 'Google Inc.', renderer: 'ANGLE (NVIDIA GeForce RTX 3060)' }, timezone: 'America/New_York', permissions: { notifications: 'denied', geolocation: 'granted', camera: 'denied', microphone: 'denied', }, behavior: { mouseMoveDelay: { min: 50, max: 150 }, keyPressDelay: { min: 80, max: 200 }, scrollStepDelay: { min: 30, max: 100 }, }, canvasNoise: { enabled: true, strength: 0.5 }, }; integration('injectNavigatorStealth', () => { let browser: Browser; let context: BrowserContext; beforeAll(async () => { browser = await chromium.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], }); }); afterAll(async () => { if (context) await context.close(); if (browser) await browser.close(); }); it('should set navigator.webdriver to false', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const webdriver = await page.evaluate(() => navigator.webdriver); expect(webdriver).toBe(false); }); it('should override navigator.languages from profile', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const langs = await page.evaluate(() => navigator.languages); expect(langs).toEqual(testProfile.languages); }); it('should override navigator.platform from profile', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const platform = await page.evaluate(() => navigator.platform); expect(platform).toBe(testProfile.platform); }); it('should set navigator.vendor to "Google Inc."', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const vendor = await page.evaluate(() => navigator.vendor); expect(vendor).toBe('Google Inc.'); }); it('should set navigator.productSub to "20030107"', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const productSub = await page.evaluate(() => navigator.productSub); expect(productSub).toBe('20030107'); }); it('should inject navigator.connection if missing', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const connection = await page.evaluate(() => { const c = (navigator as any).connection; if (!c) return null; return { downlink: c.downlink, effectiveType: c.effectiveType, rtt: c.rtt, saveData: c.saveData }; }); expect(connection).not.toBeNull(); expect(connection!.downlink).toBe(10); expect(connection!.effectiveType).toBe('4g'); expect(connection!.rtt).toBe(50); expect(connection!.saveData).toBe(false); }); it('should keep navigator.plugins accessible', async () => { context = await browser.newContext(); await injectNavigatorStealth(context, testProfile); const page = await context.newPage(); await page.goto('about:blank'); const plugins = await page.evaluate(() => { const p = navigator.plugins; return { length: p.length, hasItem: typeof p.item === 'function', hasNamedItem: typeof p.namedItem === 'function' }; }); expect(typeof plugins.length).toBe('number'); expect(plugins.hasItem).toBe(true); expect(plugins.hasNamedItem).toBe(true); }); });