blob: 488e54f815e2a69ddb50643fe2d1cc4c6141b906 [file]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Run these tests with:
//
// npx mocha scripts/devtools_build.test.mjs
import {assert} from 'chai';
import {BuildError, BuildStep, FeatureSet} from './devtools_build.mjs';
describe('FeatureSet', () => {
it('yields an empty set of arguments by default', () => {
const featureSet = new FeatureSet();
assert.isEmpty([...featureSet]);
});
it('can enable features', () => {
const featureSet = new FeatureSet();
featureSet.enable('DevToolsFreestyler');
featureSet.enable('DevToolsWellKnown');
assert.deepEqual(
[...featureSet],
['--enable-features=DevToolsFreestyler,DevToolsWellKnown'],
);
});
it('can enable features with parameters', () => {
const featureSet = new FeatureSet();
featureSet.enable('DevToolsFreestyler', {patching: true});
featureSet.enable('DevToolsFreestyler', {
user_tier: 'TESTERS',
multimodal: true,
});
featureSet.enable('DevToolsAiAssistancePerformanceAgent', {
insights_enabled: true,
});
assert.deepEqual(
[...featureSet],
[
'--enable-features=DevToolsAiAssistancePerformanceAgent:insights_enabled/true,DevToolsFreestyler:multimodal/true/patching/true/user_tier/TESTERS',
],
);
});
it('can disable features', () => {
const featureSet = new FeatureSet();
featureSet.disable('MediaRouter');
featureSet.disable('DevToolsAiGeneratedTimelineLabels');
assert.deepEqual(
[...featureSet],
['--disable-features=DevToolsAiGeneratedTimelineLabels,MediaRouter'],
);
});
it('can disable and enable unrelated features', () => {
const featureSet = new FeatureSet();
featureSet.disable('MediaRouter');
featureSet.enable('DevToolsWellKnown');
assert.deepEqual(
[...featureSet],
[
'--disable-features=MediaRouter',
'--enable-features=DevToolsWellKnown',
],
);
});
it('can disable previously enabled features', () => {
const featureSet = new FeatureSet();
featureSet.enable('DevToolsFreestyler', {patching: true});
featureSet.enable('DevToolsWellKnown');
featureSet.disable('DevToolsFreestyler');
assert.deepEqual(
[...featureSet],
[
'--disable-features=DevToolsFreestyler',
'--enable-features=DevToolsWellKnown',
],
);
});
it('can merge feature sets', () => {
const fs1 = new FeatureSet();
fs1.enable('DevToolsFreestyler', {patching: true});
fs1.enable('DevToolsWellKnown');
fs1.disable('MediaRouter');
const fs2 = new FeatureSet();
fs2.disable('DevToolsWellKnown');
fs2.enable('DevToolsFreestyler', {multimodal: true});
fs1.merge(fs2);
assert.deepEqual(
[...fs1],
[
'--disable-features=DevToolsWellKnown,MediaRouter',
'--enable-features=DevToolsFreestyler:multimodal/true/patching/true',
],
);
assert.deepEqual(
[...fs2],
[
'--disable-features=DevToolsWellKnown',
'--enable-features=DevToolsFreestyler:multimodal/true',
],
);
});
it('can parse --enable-features/--disable-features declarations', () => {
assert.deepEqual(FeatureSet.parse('MediaRouter'), [
{feature: 'MediaRouter', parameters: {}},
]);
assert.deepEqual(
FeatureSet.parse('DevToolsFreestyler:multimodal/true/patching/true'),
[
{
feature: 'DevToolsFreestyler',
parameters: {multimodal: 'true', patching: 'true'},
},
],
);
assert.deepEqual(
FeatureSet.parse('DevToolsFreestyler:multimodal/true,DevToolsWellKnown'),
[
{feature: 'DevToolsFreestyler', parameters: {multimodal: 'true'}},
{feature: 'DevToolsWellKnown', parameters: {}},
],
);
});
it('can parse empty values', () => {
assert.deepEqual(FeatureSet.parse(''), []);
assert.deepEqual(FeatureSet.parse(null), []);
assert.deepEqual(FeatureSet.parse(undefined), []);
});
});
describe('BuildError', () => {
describe('message', () => {
const target = 'Default';
const outDir = '/path/to/out/' + target;
it('correctly extracts a single tsc error', () => {
const cause = new Error();
cause.stdout = `ninja: Entering directory \`out/Default'
[ 1% | 3/1/267] ACTION //front_end/panels/timeline/components/insights:insights(//build/toolchain/linux:x64)
FAILED: gen/front_end/panels/timeline/components/insights/Table.js gen/front_end/panels/timeline/components/insights/Table.d.ts
python3 ../../scripts/build/run_with_restat.py gen/front_end/panels/timeline/components/insights/Table.js -- ../../third_party/node/linux/node-linux-x64/bin/node ../../third_party/typescript/tsc -p gen/front_end/panels/timeline/components/insights/insights-tsconfig.json
front_end/panels/timeline/components/insights/Table.ts(17,8): error TS1005: ';' expected.
ninja: build stopped: subcommand failed.`;
const {message} = new BuildError(BuildStep.AUTONINJA, {cause, target, outDir});
assert.strictEqual(message, `TypeScript compilation failed for \`Default'
front_end/panels/timeline/components/insights/Table.ts(17,8): error TS1005: ';' expected.
`);
});
it('correctly extracts multiple tsc errors from the same module', () => {
const cause = new Error();
cause.stdout = `ninja: Entering directory \`out/Default'
[ 1% | 3/1/267] ACTION //front_end/panels/timeline/components/insights:insights(//build/toolchain/linux:x64)
FAILED: gen/front_end/panels/timeline/components/insights/insights.js gen/front_end/panels/timeline/components/insights/insights.d.ts
python3 ../../scripts/build/run_with_restat.py gen/front_end/panels/timeline/components/insights/insights.js -- ../../third_party/node/linux/node-linux-x64/bin/node ../../third_party/typescript/tsc -p gen/front_end/panels/timeline/components/insights/insights-tsconfig.json
front_end/panels/timeline/components/insights/Checklist.ts(21,7): error TS7005: Variable 'b' implicitly has an 'any' type.
front_end/panels/timeline/components/insights/Checklist.ts(21,9): error TS1005: ',' expected.
front_end/panels/timeline/components/insights/Table.ts(17,7): error TS7005: Variable 'a' implicitly has an 'any' type.
front_end/panels/timeline/components/insights/Table.ts(17,9): error TS1005: ',' expected.
ninja: build stopped: subcommand failed.`;
const {message} = new BuildError(BuildStep.AUTONINJA, {cause, target, outDir});
assert.strictEqual(message, `TypeScript compilation failed for \`Default'
front_end/panels/timeline/components/insights/Checklist.ts(21,7): error TS7005: Variable 'b' implicitly has an 'any' type.
front_end/panels/timeline/components/insights/Checklist.ts(21,9): error TS1005: ',' expected.
front_end/panels/timeline/components/insights/Table.ts(17,7): error TS7005: Variable 'a' implicitly has an 'any' type.
front_end/panels/timeline/components/insights/Table.ts(17,9): error TS1005: ',' expected.
`);
});
});
});