1
0
mirror of https://github.com/lancedikson/bowser synced 2026-09-22 20:14:20 +00:00

fix: keep every published file reachable, and test all four build artifacts (#631)

This commit is contained in:
Naor Peled
2026-08-30 21:40:10 +03:00
committed by GitHub
parent 1d7923497f
commit 28174aca5e
3 changed files with 56 additions and 6 deletions

View File

@@ -2,7 +2,41 @@ import test from 'ava';
import yaml from 'yamljs';
import path from 'path';
import Bowser from '../../src/bowser';
import BowserBuild from '../../es5';
import BowserEs5 from '../../es5';
import BowserBundled from '../../bundled';
import BowserMjs from '../../bowser.mjs';
/**
* Every published JS artifact is built from `src/` through a different
* pipeline — raw ES modules, babel + terser UMD, UMD with core-js baked in,
* and the rolldown ESM build. A regression in any one of them ships silently
* unless each is asserted against the spec independently.
*
* `bowser.mjs` matters most: it is what the `import` condition of the exports
* map resolves to, so it is the file every modern ESM and bundler consumer
* actually runs. Testing only `src/` and `es5.js` leaves it uncovered.
*
* These are build outputs, so `pnpm build` has to run before `pnpm test`.
* Importing `bowser.mjs` from this CommonJS test file relies on Node's
* require(esm) support (Node >= 22.12) — the build toolchain already requires
* a newer Node than that, so anything able to produce these files can load them.
*/
const artifacts = [
['src/bowser.js', Bowser],
['es5.js', BowserEs5],
['bundled.js', BowserBundled],
['bowser.mjs', BowserMjs],
];
// A missing build output fails at import with a plain "Cannot find module".
// This catches the quieter failure: an artifact that loads but is not the
// Bowser class — a broken UMD wrapper or a lost CJS interop unwrap would
// otherwise make every assertion below vacuous instead of failing.
artifacts.forEach(([name, artifact]) => {
if (typeof artifact !== 'function' || typeof artifact.parse !== 'function') {
throw new Error(`${name} did not load as the Bowser class — run \`pnpm build\` first`);
}
});
const listOfUA = yaml.load(path.join(__dirname, 'useragentstrings.yml'));
@@ -11,11 +45,10 @@ const browserNames = Object.keys(listOfUA);
browserNames.forEach((browserName) => {
listOfUA[browserName].forEach((browser, index) => {
test(`Test ${browserName} ${index}`, (t) => {
const parsed = Bowser.parse(browser.ua);
const parsedBuild = BowserBuild.parse(browser.ua);
t.deepEqual(parsed, browser.spec, `${browser.ua}`);
t.deepEqual(parsedBuild, browser.spec, `${browser.ua}`);
t.is(parsed.browser.name, browserName, `${browser.ua}`);
artifacts.forEach(([name, artifact]) => {
t.deepEqual(artifact.parse(browser.ua), browser.spec, `${name}: ${browser.ua}`);
});
t.is(Bowser.parse(browser.ua).browser.name, browserName, `${browser.ua}`);
});
});
});

View File

@@ -93,6 +93,19 @@ check('require.resolve("bowser/package.json") works', function () {
assert.ok(fs.existsSync(require.resolve('bowser/package.json')));
});
// Before the exports map existed, *every* published file was reachable by
// subpath. An exports map is a closed list, so anything published but not
// enumerated silently becomes ERR_PACKAGE_PATH_NOT_EXPORTED. These four are
// not code, but they did resolve on every previous version — license and
// attribution tooling and `/// <reference types="bowser/index.d.ts" />`
// consumers can all depend on them.
['bowser/LICENSE', 'bowser/README.md', 'bowser/index.d.ts', 'bowser/index.d.mts']
.forEach(function (id) {
check('resolves "' + id + '"', function () {
assert.ok(fs.existsSync(require.resolve(id)));
});
});
// --- The published manifest ------------------------------------------------
check('main/browser/module/types fields are unchanged', function () {