@nx/angular
Version:
223 lines (219 loc) • 9.64 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.addVitestAngular = addVitestAngular;
exports.addVitestAnalog = addVitestAnalog;
const devkit_1 = require("@nx/devkit");
const devkit_internals_1 = require("nx/src/devkit-internals");
const semver_1 = require("semver");
const versions_1 = require("../../utils/versions");
const version_utils_1 = require("./version-utils");
async function addVitestAngular(tree, options) {
validateVitestVersion(tree);
const executor = options.useNxUnitTestRunnerExecutor
? '@nx/angular:unit-test'
: '@angular/build:unit-test';
const project = (0, devkit_1.readProjectConfiguration)(tree, options.name);
project.targets ??= {};
project.targets.test = { executor, options: {} };
(0, devkit_1.updateProjectConfiguration)(tree, options.name, project);
const nxJson = (0, devkit_1.readNxJson)(tree);
nxJson.targetDefaults ??= {};
nxJson.targetDefaults[executor] ??= {
cache: true,
inputs: nxJson.namedInputs && 'production' in nxJson.namedInputs
? ['default', '^production']
: ['default', '^default'],
};
(0, devkit_1.updateNxJson)(tree, nxJson);
configureTypeScriptForVitest(tree, options.projectRoot);
addVitestScreenshotsToGitIgnore(tree);
if (!options.skipPackageJson) {
const pkgVersions = (0, version_utils_1.versions)(tree, { minAngularMajorVersion: 21 });
const angularDevkitVersion = (0, version_utils_1.getInstalledAngularDevkitVersion)(tree) ??
pkgVersions.angularDevkitVersion;
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
'@angular/build': angularDevkitVersion,
jsdom: pkgVersions.jsdomVersion,
vitest: pkgVersions.vitestVersion,
}, undefined, true);
}
}
async function addVitestAnalog(tree, options) {
const { major: angularMajorVersion } = (0, version_utils_1.getInstalledAngularVersionInfo)(tree);
if (!options.skipPackageJson) {
const angularDevkitVersion = (0, version_utils_1.getInstalledAngularDevkitVersion)(tree) ??
(0, version_utils_1.versions)(tree).angularDevkitVersion;
const devDependencies = {
'@angular/build': angularDevkitVersion,
};
// Add compatible vitest/jsdom versions BEFORE calling configurationGenerator
// so that @nx/vitest respects existing versions
if (angularMajorVersion < 21) {
const pkgVersions = (0, version_utils_1.versions)(tree);
devDependencies['vitest'] = pkgVersions.vitestVersion;
devDependencies['jsdom'] = pkgVersions.jsdomVersion;
}
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, true);
}
(0, devkit_1.ensurePackage)('@nx/vitest', versions_1.nxVersion);
const { configurationGenerator } = await Promise.resolve().then(() => __importStar(require('@nx/vitest/generators')));
await configurationGenerator(tree, {
project: options.name,
uiFramework: 'angular',
testEnvironment: 'jsdom',
coverageProvider: 'v8',
addPlugin: options.addPlugin ?? false,
skipFormat: options.skipFormat,
skipPackageJson: options.skipPackageJson,
});
createAnalogSetupFile(tree, options, angularMajorVersion);
}
function validateVitestVersion(tree) {
let installedVitestVersion = null;
// Try to get the actual installed version from node_modules
try {
const { packageJson } = (0, devkit_internals_1.readModulePackageJson)('vitest');
installedVitestVersion = packageJson.version;
}
catch { }
const pkgVersions = (0, version_utils_1.versions)(tree, { minAngularMajorVersion: 21 });
const requiredRange = pkgVersions.vitestVersion;
if (installedVitestVersion) {
if (!(0, semver_1.satisfies)(installedVitestVersion, requiredRange, {
includePrerelease: true,
})) {
throw new Error(`The installed vitest version "${installedVitestVersion}" is not compatible with the version range Angular requires: "${requiredRange}".`);
}
return;
}
// not installed, get it from package.json
installedVitestVersion = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'vitest');
if (!installedVitestVersion) {
// not declared anywhere, it'll be installed with the correct version
return;
}
if ((0, semver_1.valid)(installedVitestVersion)) {
if (!(0, semver_1.satisfies)(installedVitestVersion, requiredRange, {
includePrerelease: true,
})) {
throw new Error(`The installed vitest version "${installedVitestVersion}" is not compatible with the version range Angular requires: "${requiredRange}".`);
}
}
else if ((0, semver_1.validRange)(installedVitestVersion)) {
// it's a range from package.json, check if it intersects with the required range
if (!(0, semver_1.intersects)(installedVitestVersion, requiredRange, {
includePrerelease: true,
})) {
throw new Error(`The declared vitest version range "${installedVitestVersion}" does not overlap with the version range Angular requires: "${requiredRange}". When installed, this may cause compatibility issues.`);
}
}
else {
// it can be anything, we don't have a way to validate it
// log a warning and continue
devkit_1.logger.warn(`The declared vitest version "${installedVitestVersion}" is not a valid semver range, ` +
`so we can't validate if it's compatible with the version range Angular requires: "${requiredRange}". ` +
`The generation will continue, but you may encounter issues if the version is not compatible.`);
}
}
function configureTypeScriptForVitest(tree, projectRoot) {
(0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.spec.json'), {
extends: './tsconfig.json',
compilerOptions: {
outDir: `${(0, devkit_1.offsetFromRoot)(projectRoot)}dist/out-tsc`,
types: ['vitest/globals'],
},
include: ['src/**/*.ts', 'src/**/*.d.ts'],
});
const projectTsconfigPath = (0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.json');
(0, devkit_1.updateJson)(tree, projectTsconfigPath, (json) => {
json.references ??= [];
if (!json.references.some((ref) => ref.path === './tsconfig.spec.json')) {
json.references.push({ path: './tsconfig.spec.json' });
}
return json;
});
}
function addVitestScreenshotsToGitIgnore(tree) {
if (tree.exists('.gitignore')) {
let content = tree.read('.gitignore', 'utf-8');
if (/^__screenshots__\/$/gm.test(content)) {
return;
}
content = `${content}\n__screenshots__/\n`;
tree.write('.gitignore', content);
}
else {
devkit_1.logger.warn(`Couldn't find .gitignore file to update`);
}
}
function createAnalogSetupFile(tree, options, angularMajorVersion) {
let setupFile;
if (angularMajorVersion >= 21) {
setupFile = `import '@angular/compiler';
import '@analogjs/vitest-angular/setup-snapshots';
import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed';
setupTestBed(${options.zoneless ? '' : '{ zoneless: false }'});
`;
}
else if (angularMajorVersion === 20) {
setupFile = `import '@angular/compiler';
import '@analogjs/vitest-angular/setup-zone';
import {
BrowserTestingModule,
platformBrowserTesting,
} from '@angular/platform-browser/testing';
import { getTestBed } from '@angular/core/testing';
getTestBed().initTestEnvironment(
BrowserTestingModule,
platformBrowserTesting(),
);
`;
}
else {
setupFile = `import '@analogjs/vitest-angular/setup-zone';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { getTestBed } from '@angular/core/testing';
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
`;
}
tree.write((0, devkit_1.joinPathFragments)(options.projectRoot, 'src/test-setup.ts'), setupFile);
}