mirror of
https://github.com/bitwarden/browser
synced 2026-02-04 10:43:47 +00:00
* Add missing libs to jest.config.js Added 15 missing libraries to the jest projects array: - libs/assets - libs/client-type - libs/core-test-utils - libs/dirt/card - libs/guid - libs/logging - libs/messaging-internal - libs/messaging - libs/serialization - libs/state-test-utils - libs/state - libs/storage-core - libs/storage-test-utils - libs/tools/export/vault-export/vault-export-ui - libs/user-core This ensures all existing libraries with jest.config.js files are included in CI test runs. * Update basic-lib generator to add new libs to jest.config.js - Added updateJestConfig function that automatically adds new libraries to jest.config.js - Function finds the appropriate alphabetical position for the new library - Added comprehensive tests for the new functionality - Ensures new libraries are included in CI test runs from creation This prevents the issue where new libraries are created but their tests are not run in CI because they are missing from the jest configuration. * Fix import statements in state-definitions and deserialization-helpers tests - Fixed ClientLocations import in state-definitions.spec.ts to use @bitwarden/storage-core instead of relative import - Simplified deserialization-helpers.spec.ts import to use library root @bitwarden/serialization
193 lines
6.3 KiB
TypeScript
193 lines
6.3 KiB
TypeScript
import { execSync } from "child_process";
|
|
import * as path from "path";
|
|
|
|
import {
|
|
formatFiles,
|
|
generateFiles,
|
|
Tree,
|
|
offsetFromRoot,
|
|
updateJson,
|
|
runTasksInSerial,
|
|
GeneratorCallback,
|
|
} from "@nx/devkit";
|
|
|
|
import { BasicLibGeneratorSchema } from "./schema";
|
|
|
|
/**
|
|
* An Nx generator for creating basic libraries.
|
|
* Generators help automate repetitive tasks like creating new components, libraries, or apps.
|
|
*
|
|
* @param {Tree} tree - The virtual file system tree that Nx uses to make changes
|
|
* @param {BasicLibGeneratorSchema} options - Configuration options for the generator
|
|
* @returns {Promise<void>} - Returns a promise that resolves when generation is complete
|
|
*/
|
|
export async function basicLibGenerator(
|
|
tree: Tree,
|
|
options: BasicLibGeneratorSchema,
|
|
): Promise<GeneratorCallback> {
|
|
const projectRoot = `${options.directory}/${options.name}`;
|
|
const srcRoot = `${projectRoot}/src`;
|
|
|
|
/**
|
|
* Generate files from templates in the 'files/' directory.
|
|
* This copies all template files to the new library location.
|
|
*/
|
|
generateFiles(tree, path.join(__dirname, "files"), projectRoot, {
|
|
...options,
|
|
// `tmpl` is used in file names for template files. Setting it to an
|
|
// empty string here lets use be explicit with the naming of template
|
|
// files, and lets Nx handle stripping out "__tmpl__" from file names.
|
|
tmpl: "",
|
|
// `name` is a variable passed to template files for interpolation into
|
|
// their contents. It is set to the name of the library being generated.
|
|
name: options.name,
|
|
root: projectRoot,
|
|
// `offsetFromRoot` is helper to calculate relative path from the new
|
|
// library to project root.
|
|
offsetFromRoot: offsetFromRoot(projectRoot),
|
|
});
|
|
|
|
// Add TypeScript path to the base tsconfig
|
|
updateTsConfigPath(tree, options.name, srcRoot);
|
|
|
|
// Update CODEOWNERS with the new lib
|
|
updateCodeowners(tree, options.directory, options.name, options.team);
|
|
|
|
// Update jest.config.js with the new lib
|
|
updateJestConfig(tree, options.directory, options.name);
|
|
|
|
// Format all new files with prettier
|
|
await formatFiles(tree);
|
|
|
|
const tasks: GeneratorCallback[] = [];
|
|
// Run npm i after generation. Nx ships a helper function for this called
|
|
// installPackagesTask. When used here it was leaving package-lock in a
|
|
// broken state, so a manual approach was used instead.
|
|
tasks.push(() => {
|
|
execSync("npm install", { stdio: "inherit" });
|
|
return Promise.resolve();
|
|
});
|
|
return runTasksInSerial(...tasks);
|
|
}
|
|
|
|
/**
|
|
* Updates the base tsconfig.json file to include the new library.
|
|
* This allows importing the library using its alias path.
|
|
*
|
|
* @param {Tree} tree - The virtual file system tree
|
|
* @param {string} name - The library name
|
|
* @param {string} srcRoot - Path to the library's source files
|
|
*/
|
|
function updateTsConfigPath(tree: Tree, name: string, srcRoot: string) {
|
|
updateJson(tree, "tsconfig.base.json", (json) => {
|
|
const paths = json.compilerOptions.paths || {};
|
|
|
|
paths[`@bitwarden/${name}`] = [`${srcRoot}/index.ts`];
|
|
|
|
json.compilerOptions.paths = paths;
|
|
return json;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Updates the CODEOWNERS file to add ownership for the new library
|
|
*
|
|
* @param {Tree} tree - The virtual file system tree
|
|
* @param {string} directory - Directory where the library is created
|
|
* @param {string} name - The library name
|
|
* @param {string} team - The team responsible for the library
|
|
*/
|
|
function updateCodeowners(tree: Tree, directory: string, name: string, team: string) {
|
|
const codeownersPath = ".github/CODEOWNERS";
|
|
|
|
if (!tree.exists(codeownersPath)) {
|
|
console.warn("CODEOWNERS file not found at .github/CODEOWNERS");
|
|
return;
|
|
}
|
|
|
|
const teamHandleMap: Record<string, string> = {
|
|
"admin-console": "@bitwarden/team-admin-console-dev",
|
|
auth: "@bitwarden/team-auth-dev",
|
|
autofill: "@bitwarden/team-autofill-dev",
|
|
billing: "@bitwarden/team-billing-dev",
|
|
"data-insights-and-reporting": "@bitwarden/team-data-insights-and-reporting-dev",
|
|
"key-management": "@bitwarden/team-key-management-dev",
|
|
platform: "@bitwarden/team-platform-dev",
|
|
tools: "@bitwarden/team-tools-dev",
|
|
"ui-foundation": "@bitwarden/team-ui-foundation",
|
|
vault: "@bitwarden/team-vault-dev",
|
|
};
|
|
|
|
const teamHandle = teamHandleMap[team] || `@bitwarden/team-${team}-dev`;
|
|
const libPath = `${directory}/${name}`;
|
|
|
|
const newLine = `${libPath} ${teamHandle}\n`;
|
|
|
|
const content = tree.read(codeownersPath)?.toString() || "";
|
|
tree.write(codeownersPath, content + newLine);
|
|
}
|
|
|
|
/**
|
|
* Updates the jest.config.js file to include the new library
|
|
* This ensures the library's tests are included in CI runs
|
|
*
|
|
* @param {Tree} tree - The virtual file system tree
|
|
* @param {string} directory - Directory where the library is created
|
|
* @param {string} name - The library name
|
|
*/
|
|
function updateJestConfig(tree: Tree, directory: string, name: string) {
|
|
const jestConfigPath = "jest.config.js";
|
|
|
|
if (!tree.exists(jestConfigPath)) {
|
|
console.warn("jest.config.js file not found at root");
|
|
return;
|
|
}
|
|
|
|
const content = tree.read(jestConfigPath)?.toString() || "";
|
|
const libJestPath = `"<rootDir>/${directory}/${name}/jest.config.js",`;
|
|
|
|
// Find the libs section and insert the new library in alphabetical order
|
|
const lines = content.split("\n");
|
|
let insertIndex = -1;
|
|
let foundLibsSection = false;
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
|
|
// Check if we're in the libs section
|
|
if (line.includes('"<rootDir>/libs/')) {
|
|
foundLibsSection = true;
|
|
|
|
// Extract the lib name for comparison
|
|
const match = line.match(/"<rootDir>libs([^"]+)/);
|
|
if (match) {
|
|
const existingLibName = match[1];
|
|
|
|
// If the new lib should come before this existing lib alphabetically
|
|
if (name < existingLibName) {
|
|
insertIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// If we were in libs section but hit a non-libs line, insert at end of libs
|
|
else if (foundLibsSection && !line.includes('"<rootDir>/libs/')) {
|
|
insertIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (insertIndex === -1) {
|
|
console.warn(`Could not find appropriate location to insert ${name} in jest.config.js`);
|
|
return;
|
|
}
|
|
|
|
// Insert the new library line
|
|
lines.splice(insertIndex, 0, ` ${libJestPath}`);
|
|
|
|
// Write back the updated content
|
|
tree.write(jestConfigPath, lines.join("\n"));
|
|
}
|
|
|
|
export default basicLibGenerator;
|