Currently, we provide `targetDefaults` for atomized targets (e.g.
`e2e-ci`) with a glob pattern that may not match nested paths.
i.e.
```
"e2e-ci--**/*": {
"dependsOn": [
"^build",
],
},
```
The `e2e-ci--**/*` pattern should be `e2e-ci--**/**`.
<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->
## Current Behavior
The generated `e2e-ci` pattern in `nx.json` does not match nested paths
for split tasks.
## Expected Behavior
The generated `e2e-ci` pattern should apply to all split tasks.
## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->
Fixes #28842
378 lines
9.9 KiB
TypeScript
378 lines
9.9 KiB
TypeScript
import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports';
|
|
import { readNxJson, updateNxJson, type Tree } from 'nx/src/devkit-exports';
|
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
|
import { addE2eCiTargetDefaults } from './target-defaults-utils';
|
|
describe('target-defaults-utils', () => {
|
|
describe('addE2eCiTargetDefaults', () => {
|
|
let tree: Tree;
|
|
let tempFs: TempFs;
|
|
beforeEach(() => {
|
|
tempFs = new TempFs('target-defaults-utils');
|
|
tree = createTreeWithEmptyWorkspace();
|
|
tree.root = tempFs.tempDir;
|
|
});
|
|
|
|
afterEach(() => {
|
|
tempFs.cleanup();
|
|
jest.resetModules();
|
|
});
|
|
|
|
it('should add e2e-ci--**/** target default for e2e plugin for specified build target when it does not exist', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
});
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['e2e-ci--**/**']).toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should update existing e2e-ci--**/** target default for e2e plugin for specified build target when it does not exist in dependsOn', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
});
|
|
nxJson.targetDefaults ??= {};
|
|
nxJson.targetDefaults['e2e-ci--**/**'] = {
|
|
dependsOn: ['^build'],
|
|
};
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build-base',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['e2e-ci--**/**']).toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
"^build-base",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should read the ciTargetName and add a new entry when it does not exist', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'cypress:e2e-ci',
|
|
},
|
|
});
|
|
nxJson.targetDefaults ??= {};
|
|
nxJson.targetDefaults['e2e-ci--**/**'] = {
|
|
dependsOn: ['^build'],
|
|
};
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build-base',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['e2e-ci--**/**']).toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
}
|
|
`);
|
|
expect(newNxJson.targetDefaults['cypress:e2e-ci--**/**'])
|
|
.toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build-base",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should not add additional e2e-ci--**/** target default for e2e plugin when it already exists with build target', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
});
|
|
nxJson.targetDefaults ??= {};
|
|
nxJson.targetDefaults['e2e-ci--**/**'] = {
|
|
dependsOn: ['^build'],
|
|
};
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults).toMatchInlineSnapshot(`
|
|
{
|
|
"build": {
|
|
"cache": true,
|
|
},
|
|
"e2e-ci--**/**": {
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
},
|
|
"lint": {
|
|
"cache": true,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should do nothing when there are no nxJson.plugins does not exist', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins = undefined;
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults).toMatchInlineSnapshot(`
|
|
{
|
|
"build": {
|
|
"cache": true,
|
|
},
|
|
"lint": {
|
|
"cache": true,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should do nothing when there are nxJson.plugins but e2e plugin is not registered', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/playwright/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
});
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults).toMatchInlineSnapshot(`
|
|
{
|
|
"build": {
|
|
"cache": true,
|
|
},
|
|
"lint": {
|
|
"cache": true,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should choose the correct plugin when there are includes', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
include: ['libs/**'],
|
|
});
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'cypress:e2e-ci',
|
|
},
|
|
include: ['apps/**'],
|
|
});
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['cypress:e2e-ci--**/**'])
|
|
.toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should choose the correct plugin when there are excludes', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'e2e-ci',
|
|
},
|
|
exclude: ['apps/**'],
|
|
});
|
|
nxJson.plugins.push({
|
|
plugin: '@nx/cypress/plugin',
|
|
options: {
|
|
targetName: 'e2e',
|
|
ciTargetName: 'cypress:e2e-ci',
|
|
},
|
|
exclude: ['libs/**'],
|
|
});
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['cypress:e2e-ci--**/**'])
|
|
.toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it('should use the default name when the plugin registration is a string', async () => {
|
|
// ARRANGE
|
|
const nxJson = readNxJson(tree);
|
|
nxJson.plugins ??= [];
|
|
nxJson.plugins.push('@nx/cypress/plugin');
|
|
updateNxJson(tree, nxJson);
|
|
|
|
tree.write('apps/myapp-e2e/cypress.config.ts', '');
|
|
await tempFs.createFile('apps/myapp-e2e/cypress.config.ts', '');
|
|
|
|
// ACT
|
|
await addE2eCiTargetDefaults(
|
|
tree,
|
|
'@nx/cypress/plugin',
|
|
'^build',
|
|
'apps/myapp-e2e/cypress.config.ts'
|
|
);
|
|
|
|
// ASSERT
|
|
const newNxJson = readNxJson(tree);
|
|
expect(newNxJson.targetDefaults['e2e-ci--**/**']).toMatchInlineSnapshot(`
|
|
{
|
|
"dependsOn": [
|
|
"^build",
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
});
|
|
});
|