UNPKG

chrome-devtools-frontend

Version:
128 lines (113 loc) 3.78 kB
// Copyright 2025 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import {readFileSync} from 'fs'; import glob from 'glob'; import * as ts from 'typescript'; import yargs from 'yargs'; import {hideBin} from 'yargs/helpers'; const argv = yargs(hideBin(process.argv)) .option('format', { alias: 'f', describe: 'Output format', choices: ['list', 'b'], default: 'list', }) .option('sources', { type: 'array', alias: 's', describe: 'Sources', choices: ['devtools', 'chromium'], default: ['devtools', 'chromium'], }) .parseSync(); /** * Usage: node --no-warnings --experimental-strip-types * scripts/extract_bugs.ts * * Finds all skipped tests and returns associated bug IDs and the test * files (tab-separated). */ const bugs = new Set<string>(); const bugToFile = new Map<string, string>(); function extract(sourceFile: ts.SourceFile) { extractBugs(sourceFile); function isSkipCall(node: ts.Node) { if (node.getChildAt(0).kind === ts.SyntaxKind.PropertyAccessExpression) { const propAccess = node.getChildAt(0); const skipCalls = new Set(['it.skip', 'describe.skip', 'itScreenshot.skip']); if (skipCalls.has(propAccess.getText())) { return true; } } return false; } function isSkipOnPlatformsCall(node: ts.Node) { if (node.getChildAt(0).kind === ts.SyntaxKind.PropertyAccessExpression) { const propAccess = node.getChildAt(0); const skipOnPlatformCalls = new Set(['it.skipOnPlatforms', 'describe.skipOnPlatforms', 'itScreenshot.skipOnPlatforms']); if (skipOnPlatformCalls.has(propAccess.getText())) { return true; } } return false; } function extractBugs(node: ts.Node) { switch (node.kind) { case ts.SyntaxKind.CallExpression: { let description; if (isSkipCall(node)) { description = node.getChildAt(2).getChildAt(0).getText(); } else if (isSkipOnPlatformsCall(node)) { description = node.getChildAt(2).getChildAt(2).getText(); } if (!description) { break; } const match = description.match(/crbug.com\/(\d+)/); if (!match) { break; } bugs.add(match[1]); bugToFile.set(match[1], sourceFile.fileName); break; } } ts.forEachChild(node, extractBugs); } } if (argv.sources.includes('devtools')) { const files = [ ...glob.sync('front_end/**/*.test.ts'), ...glob.sync('test/**/*test.ts'), ]; for (const file of files) { extract(ts.createSourceFile( file, readFileSync(file).toString(), ts.ScriptTarget.ESNext, /* setParentNodes */ true)); } } if (argv.sources.includes('chromium')) { const expectations = readFileSync('../../chromium/src/third_party/blink/web_tests/TestExpectations', 'utf-8'); const lines = expectations.split('\n'); for (const line of lines) { if (line.includes('/tests/devtools/')) { const parts = line.split(' '); const crbug = parts.shift() ?? ''; const match = crbug.match(/crbug.com\/(\d+)/); if (!match) { continue; } bugs.add(match[1]); bugToFile.set(match[1], parts.find(part => part.includes('/tests/devtools/')) ?? ''); } } } if (argv.format === 'b') { console.log(`id: (${Array.from(bugs).join('|')})`); } else { for (const bug of bugs) { console.log(`crbug.com/${bug}\t${bugToFile.get(bug)}`); } }