blob: 8fe762738e24b104bc3e27d10a7489947d638115 [file] [edit]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {existsSync, readFileSync} from 'node:fs';
import * as path from 'node:path';
import {fileURLToPath} from 'node:url';
import * as ts from 'typescript';
import {generateExactTestId} from '../front_end/testing/TestIdGeneration.ts';
const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
const REPO_ROOT = path.resolve(dirname, '..');
const [filePath, lineStr, colStr] = process.argv.slice(2);
if (!filePath || !lineStr || !colStr) {
console.error('Usage: node scripts/get_test_id.ts <file> <line> <column>');
process.exit(1);
}
const line = parseInt(lineStr, 10);
const column = parseInt(colStr, 10);
const absFilePath = path.resolve(process.cwd(), filePath);
if (!existsSync(absFilePath)) {
console.error(`Error: File not found at '${absFilePath}'`);
process.exit(1);
}
const fileContent = readFileSync(absFilePath, 'utf-8');
const sourceFile = ts.createSourceFile(
absFilePath,
fileContent,
ts.ScriptTarget.ESNext,
/* setParentNodes */ true,
);
const lineIndex = Math.max(0, line - 1);
const colIndex = Math.max(0, column - 1);
const targetOffset = sourceFile.getPositionOfLineAndCharacter(lineIndex, colIndex);
function findTestTitlePath(sf: ts.SourceFile, offset: number): string[] {
const titlePath: string[] = [];
function isTestOrSuiteCall(node: ts.Node): node is ts.CallExpression {
if (!ts.isCallExpression(node)) {
return false;
}
const exprText = node.expression.getText(sf);
return /^(describe|it)($|\.|\w+)/.test(exprText);
}
function getStringArgument(callNode: ts.CallExpression): string|null {
if (callNode.arguments.length === 0) {
return null;
}
const firstArg = callNode.arguments[0];
if (ts.isStringLiteral(firstArg) || ts.isNoSubstitutionTemplateLiteral(firstArg)) {
return firstArg.text;
}
if (ts.isTemplateExpression(firstArg)) {
return firstArg.getText(sf).replace(/^`|`$/g, '');
}
return null;
}
function visit(node: ts.Node) {
if (node.getStart(sf) <= offset && offset <= node.getEnd()) {
if (isTestOrSuiteCall(node)) {
const title = getStringArgument(node);
if (title !== null) {
titlePath.push(title);
}
}
ts.forEachChild(node, visit);
}
}
visit(sourceFile);
return titlePath;
}
const titlePath = findTestTitlePath(sourceFile, targetOffset);
const relativeSourceFile = path.relative(REPO_ROOT, absFilePath).replace(/\\/g, '/');
const {exactTestId} = generateExactTestId(REPO_ROOT, relativeSourceFile, titlePath);
console.log(exactTestId);