feat: add JavaScript/TypeScript wrapper with Playwright + Puppeteer support

Adds js/ package mirroring the Python wrapper architecture:
- Dual API: import from 'cloakbrowser' (Playwright) or 'cloakbrowser/puppeteer'
- TypeScript with full type definitions
- Same binary download/cache logic, same stealth args, same env vars
- Optional peer deps: users install only the runtime they need
- Full 6-site stealth test suite (sannysoft, incolumitas, BrowserScan, deviceandbrowserinfo, FingerprintJS, reCAPTCHA v3)
- Published to npm as cloakbrowser@0.1.2
This commit is contained in:
CloakHQ
2026-02-24 07:33:18 +01:00
parent 23ae521832
commit 4e809b9678
17 changed files with 4260 additions and 9 deletions
+59
View File
@@ -0,0 +1,59 @@
import { describe, it, expect } from "vitest";
import {
CHROMIUM_VERSION,
getDefaultStealthArgs,
getCacheDir,
getBinaryDir,
getDownloadUrl,
} from "../src/config.js";
describe("config", () => {
it("CHROMIUM_VERSION matches expected format", () => {
expect(CHROMIUM_VERSION).toMatch(/^\d+\.\d+\.\d+\.\d+$/);
});
it("getDefaultStealthArgs returns expected flags", () => {
const args = getDefaultStealthArgs();
expect(args).toContain("--no-sandbox");
expect(args).toContain("--disable-blink-features=AutomationControlled");
expect(args).toContain("--fingerprint-platform=windows");
expect(args).toContain("--fingerprint-hardware-concurrency=8");
// Should have a random fingerprint seed
const fingerprintArg = args.find((a) => a.startsWith("--fingerprint="));
expect(fingerprintArg).toBeDefined();
const seed = Number(fingerprintArg!.split("=")[1]);
expect(seed).toBeGreaterThanOrEqual(10000);
expect(seed).toBeLessThanOrEqual(99999);
});
it("getDefaultStealthArgs generates different seeds", () => {
const seeds = new Set<string>();
for (let i = 0; i < 10; i++) {
const args = getDefaultStealthArgs();
const fp = args.find((a) => a.startsWith("--fingerprint="))!;
seeds.add(fp);
}
// With 90k possible seeds, 10 calls should produce at least 2 unique
expect(seeds.size).toBeGreaterThan(1);
});
it("getCacheDir returns ~/.cloakbrowser by default", () => {
const dir = getCacheDir();
expect(dir).toContain(".cloakbrowser");
});
it("getBinaryDir includes version", () => {
const dir = getBinaryDir();
expect(dir).toContain(`chromium-${CHROMIUM_VERSION}`);
});
it("getDownloadUrl contains version and platform tag", () => {
const url = getDownloadUrl();
expect(url).toContain(CHROMIUM_VERSION);
expect(url).toContain("cloakbrowser-");
expect(url).toContain(".tar.gz");
expect(url).toContain("github.com/CloakHQ/");
});
});
+39
View File
@@ -0,0 +1,39 @@
import { describe, it, expect } from "vitest";
import { binaryInfo } from "../src/download.js";
import { CHROMIUM_VERSION } from "../src/config.js";
describe("binaryInfo", () => {
it("returns correct structure", () => {
const info = binaryInfo();
expect(info.version).toBe(CHROMIUM_VERSION);
expect(info.platform).toMatch(/^(linux|darwin)-(x64|arm64)$/);
expect(info.binaryPath).toBeTruthy();
expect(typeof info.installed).toBe("boolean");
expect(info.cacheDir).toContain("cloakbrowser");
expect(info.downloadUrl).toContain(".tar.gz");
});
});
// Integration tests require the binary — run with:
// CLOAKBROWSER_BINARY_PATH=/path/to/chrome npm test
describe.skipIf(!process.env.CLOAKBROWSER_BINARY_PATH)(
"launch (integration)",
() => {
it("launches browser and checks stealth", async () => {
const { launch } = await import("../src/playwright.js");
const browser = await launch({ headless: true });
const page = await browser.newPage();
await page.goto("about:blank");
const webdriver = await page.evaluate(() => navigator.webdriver);
expect(webdriver).toBeFalsy();
const plugins = await page.evaluate(() => navigator.plugins.length);
expect(plugins).toBeGreaterThan(0);
await browser.close();
}, 30_000);
}
);