Files
js-sha256/tests/browser/worker.spec.mjs
Yi-Cyuan Chen a6d0f636aa ### Added
- Add dedicated ESM, CommonJS, Node.js, and browser distribution entry points.
- Add streaming support to the native Node.js SHA-256, SHA-224, and HMAC implementations.
- Add distribution contract tests and real browser Web Worker tests with Playwright.
- Add Node.js 16, 18, 20, 22, and 24 runtime tests against the packed npm artifact.

### Changed
- Refactor the implementation into environment-independent core and Node.js modules.
- Use the native Node.js `crypto` implementation for hashing and HMAC.
- Load the package version automatically when generating distribution banners.
- Export unminified ESM source directly and build only CommonJS and browser/minified distributions.
- Replace `expect.js`, NYC, Tiny Worker, and UglifyJS with Node.js assert, c8, Playwright, and Rollup/Terser.
- Build automatically before `npm pack` and `npm publish`.
- Throw error if update after finalize

### Removed
- Remove runtime CommonJS, AMD, Node.js, Web Worker, and ArrayBuffer environment switches from the core implementation.
- Remove legacy environment flags and obsolete compatibility polyfills.
- Remove the old generated `sha256.mjs` and `sha256.node.mjs` entry points.
2026-07-27 14:30:34 +08:00

96 lines
2.7 KiB
JavaScript

import { test, expect } from '@playwright/test';
import { createReadStream } from 'node:fs';
import { stat } from 'node:fs/promises';
import { createServer } from 'node:http';
import { extname, join, normalize } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = fileURLToPath(new URL('../..', import.meta.url));
const contentTypes = {
'.js': 'text/javascript',
'.mjs': 'text/javascript'
};
let server;
let origin;
test.beforeAll(async () => {
server = createServer(async (request, response) => {
if (request.url === '/') {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('<!doctype html><title>js-sha256 worker test</title>');
return;
}
const path = normalize(join(root, decodeURIComponent(request.url)));
if (!path.startsWith(root)) {
response.writeHead(403);
response.end();
return;
}
try {
await stat(path);
response.writeHead(200, {
'Content-Type': contentTypes[extname(path)] || 'application/octet-stream'
});
createReadStream(path).pipe(response);
} catch {
response.writeHead(404);
response.end();
}
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const address = server.address();
origin = `http://127.0.0.1:${address.port}`;
});
test.afterAll(async () => {
await new Promise((resolve, reject) => {
server.close(error => error ? reject(error) : resolve());
});
});
async function hashInWorker(page, workerPath, options) {
return page.evaluate(({ workerPath, options }) => new Promise((resolve, reject) => {
const worker = new Worker(workerPath, options);
const timeout = setTimeout(() => {
worker.terminate();
reject(new Error('Worker timed out'));
}, 5000);
worker.onmessage = event => {
clearTimeout(timeout);
worker.terminate();
resolve(event.data);
};
worker.onerror = event => {
clearTimeout(timeout);
worker.terminate();
reject(new Error(event.message));
};
worker.postMessage('abc');
}), { workerPath, options });
}
test('classic Worker loads the minified UMD build', async ({ page }) => {
await page.goto(origin);
const hash = await hashInWorker(page, '/tests/browser/classic-worker.js');
expect(hash).toBe(
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
);
});
test('module Worker imports the ESM source entry', async ({ page }) => {
await page.goto(origin);
const hash = await hashInWorker(
page,
'/tests/browser/module-worker.mjs',
{ type: 'module' }
);
expect(hash).toBe(
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
);
});