chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:38:36 +08:00
commit 8e2a6eb840
10194 changed files with 1593658 additions and 0 deletions
@@ -0,0 +1,35 @@
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
const cypressJsonConfig = {
fileServerFolder: '.',
fixturesFolder: './src/fixtures',
video: true,
videosFolder: '../../dist/cypress/graph/client-e2e/videos',
screenshotsFolder: '../../dist/cypress/graph/client-e2e/screenshots',
chromeWebSecurity: false,
specPattern: './src/e2e/**/release-static*.cy.{js,jsx,ts,tsx}',
supportFile: 'src/support/e2e.ts',
};
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
webServerCommands: {
default:
'pnpm exec nx run graph-client:serve --configuration=release-static',
},
}),
baseUrl: 'http://localhost:4205',
...cypressJsonConfig,
/**
* TODO(@nx/cypress): In Cypress v12,the testIsolation option is turned on by default.
* This can cause tests to start breaking where not indended.
* You should consider enabling this once you verify tests do not depend on each other
* More Info: https://docs.cypress.io/guides/references/migration-guide#Test-Isolation
**/
testIsolation: false,
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
injectDocumentDomain: true,
},
});
@@ -0,0 +1,34 @@
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
const cypressJsonConfig = {
fileServerFolder: '.',
fixturesFolder: './src/fixtures',
video: true,
videosFolder: '../../dist/cypress/graph/client-e2e/videos',
screenshotsFolder: '../../dist/cypress/graph/client-e2e/screenshots',
chromeWebSecurity: false,
specPattern: './src/e2e/**/release-serve-*.cy.{js,jsx,ts,tsx}',
supportFile: 'src/support/e2e.ts',
};
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
webServerCommands: {
default: 'pnpm exec nx run graph-client:serve --configuration=release',
},
}),
baseUrl: 'http://localhost:4203',
...cypressJsonConfig,
/**
* TODO(@nx/cypress): In Cypress v12,the testIsolation option is turned on by default.
* This can cause tests to start breaking where not indended.
* You should consider enabling this once you verify tests do not depend on each other
* More Info: https://docs.cypress.io/guides/references/migration-guide#Test-Isolation
**/
testIsolation: false,
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
injectDocumentDomain: true,
},
});
@@ -0,0 +1,34 @@
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
const cypressJsonConfig = {
fileServerFolder: '.',
fixturesFolder: './src/fixtures',
video: true,
videosFolder: '../../dist/cypress/graph/client-e2e/videos',
screenshotsFolder: '../../dist/cypress/graph/client-e2e/screenshots',
chromeWebSecurity: false,
specPattern: './src/e2e/**/watch-mode-*.cy.{js,jsx,ts,tsx}',
supportFile: 'src/support/e2e.ts',
};
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
webServerCommands: {
default: 'pnpm exec nx run graph-client:serve --configuration=watch',
},
}),
baseUrl: 'http://localhost:4204',
...cypressJsonConfig,
/**
* TODO(@nx/cypress): In Cypress v12,the testIsolation option is turned on by default.
* This can cause tests to start breaking where not indended.
* You should consider enabling this once you verify tests do not depend on each other
* More Info: https://docs.cypress.io/guides/references/migration-guide#Test-Isolation
**/
testIsolation: false,
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
injectDocumentDomain: true,
},
});
+34
View File
@@ -0,0 +1,34 @@
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
const cypressJsonConfig = {
fileServerFolder: '.',
fixturesFolder: './src/fixtures',
video: true,
videosFolder: '../../dist/cypress/graph/client-e2e/videos',
screenshotsFolder: '../../dist/cypress/graph/client-e2e/screenshots',
chromeWebSecurity: false,
specPattern: 'src/e2e/**/dev-*.cy.{js,jsx,ts,tsx}',
supportFile: 'src/support/e2e.ts',
};
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
webServerCommands: {
default: 'pnpm exec nx run graph-client:serve --configuration=dev-e2e',
},
}),
baseUrl: 'http://localhost:4206',
...cypressJsonConfig,
/**
* TODO(@nx/cypress): In Cypress v12,the testIsolation option is turned on by default.
* This can cause tests to start breaking where not indended.
* You should consider enabling this once you verify tests do not depend on each other
* More Info: https://docs.cypress.io/guides/references/migration-guide#Test-Isolation
**/
testIsolation: false,
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
injectDocumentDomain: true,
},
});
@@ -0,0 +1 @@
Cr24
+14
View File
@@ -0,0 +1,14 @@
import cypress from 'eslint-plugin-cypress';
import { baseConfig } from '../../eslint.config.mjs';
export default [
...baseConfig,
cypress.configs.recommended,
{
files: ['src/plugins/index.js'],
rules: {
'@typescript-eslint/no-var-requires': 'off',
'no-undef': 'off',
},
},
];
+57
View File
@@ -0,0 +1,57 @@
{
"name": "e2e-graph-client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "graph/client-e2e/src",
"projectType": "application",
"targets": {
"e2e-base": {
"executor": "@nx/cypress:cypress",
"options": {
"testingType": "e2e",
"skipServe": true,
"browser": "chrome"
},
"configurations": {
"dev": {
"cypressConfig": "graph/client-e2e/cypress.config.ts"
},
"watch": {
"cypressConfig": "graph/client-e2e/cypress-watch-mode.config.ts"
},
"release": {
"cypressConfig": "graph/client-e2e/cypress-release.config.ts"
},
"release-static": {
"cypressConfig": "graph/client-e2e/cypress-release-static.config.ts"
}
},
"defaultConfiguration": "dev"
},
"e2e-local": {
"executor": "nx:run-commands",
"outputs": [],
"options": {
"commands": [
"npx nx e2e-base e2e-graph-client --configuration dev",
"npx nx e2e-base e2e-graph-client --configuration watch",
"npx nx e2e-base e2e-graph-client --configuration release",
"npx nx e2e-base e2e-graph-client --configuration release-static"
],
"parallel": false
}
},
"DISABLED__e2e": {
"executor": "nx:run-commands",
"outputs": [],
"options": {
"commands": [
"npx nx e2e-base e2e-graph-client --configuration dev",
"npx nx e2e-base e2e-graph-client --configuration release",
"npx nx e2e-base e2e-graph-client --configuration release-static"
],
"parallel": false
}
}
},
"implicitDependencies": ["graph-client"]
}
+102
View File
@@ -0,0 +1,102 @@
describe('dev mode - app', () => {
before(() => {
cy.intercept('/assets/project-graphs/e2e.json', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
cy.visit('/e2e/projects');
// wait for initial graph to finish loading
cy.wait('@getGraph');
});
describe('theme preferences', () => {
let systemTheme: string;
before(() => {
cy.visit('/e2e/projects');
systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
});
it('should initialize localstorage with default theme', () => {
expect(localStorage.getItem('nx-dep-graph-theme')).eq('system');
});
it('has system default theme', () => {
cy.log('system theme is:', systemTheme);
cy.get('html').should('have.class', systemTheme);
});
describe('dark theme is set as prefered', () => {
before(() => {
cy.get('[data-cy="theme-open-modal-button"]').click();
cy.get('[data-cy="dark-theme-button"]').click();
});
it('should set dark theme', () => {
cy.log('Localstorage is: ', localStorage.getItem('nx-dep-graph-theme'));
expect(localStorage.getItem('nx-dep-graph-theme')).eq('dark');
cy.get('html').should('have.class', 'dark');
});
});
describe('light theme is set as preferred', () => {
before(() => {
cy.get('[data-cy="theme-open-modal-button"]').click();
cy.get('[data-cy="light-theme-button"]').click();
});
it('should set light theme', () => {
cy.log('Localstorage is: ', localStorage.getItem('nx-dep-graph-theme'));
expect(localStorage.getItem('nx-dep-graph-theme')).eq('light');
cy.get('html').should('have.class', 'light');
});
});
});
describe('graph layout direction preferences', () => {
let rankDir: string;
before(() => {
cy.visit('/e2e/projects');
rankDir = 'TB';
});
it('should initialize localstorage with default graph layout direction', () => {
expect(localStorage.getItem('nx-dep-graph-rankdir')).eq(rankDir);
});
describe('left-to-right graph layout direction is set as preferred', () => {
before(() => {
cy.get('[data-cy="lr-rankdir-button"]').click();
});
it('should set left-to-right graph layout direction', () => {
cy.log(
'Localstorage is: ',
localStorage.getItem('nx-dep-graph-rankdir')
);
expect(localStorage.getItem('nx-dep-graph-rankdir')).eq('LR');
cy.get('[data-cy="tb-rankdir-button"]').should(
(elem) => expect(elem).to.exist
);
});
});
describe('top-to-bottom graph layout direction is set as preferred', () => {
before(() => {
cy.get('[data-cy="tb-rankdir-button"]').click();
});
it('should set top-to-bottom graph layout direction', () => {
cy.log(
'Localstorage is: ',
localStorage.getItem('nx-dep-graph-rankdir')
);
expect(localStorage.getItem('nx-dep-graph-rankdir')).eq('TB');
cy.get('[data-cy="lr-rankdir-button"]').should(
(elem) => expect(elem).to.exist
);
});
});
});
});
@@ -0,0 +1,398 @@
import {
getCheckedProjectItems,
getDeselectAllButton,
getFocusButtonForProject,
getGroupByFolderCheckbox,
getImageDownloadButton,
getIncludeProjectsInPathButton,
getSearchDepthCheckbox,
getSearchDepthDecrementButton,
getSearchDepthIncrementButton,
getSelectAffectedButton,
getSelectAllButton,
getSelectProjectsMessage,
getTextFilterInput,
getTextFilterReset,
getToggleAllButtonForFolder,
getUncheckedProjectItems,
getUnfocusProjectButton,
} from '../support/app.po';
import * as affectedJson from '../fixtures/affected.json';
import { testProjectsRoutes } from '../support/routing-tests';
import * as nxExamplesJson from '../fixtures/nx-examples-project-graph.json';
describe('dev mode - project graph', () => {
before(() => {
cy.intercept('/assets/project-graphs/e2e.json', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
cy.visit('/e2e/projects');
// wait for initial graph to finish loading
cy.wait('@getGraph');
});
afterEach(() => {
// clean up by hiding all projects and clearing text input
getDeselectAllButton().click();
getTextFilterInput().clear().type('{enter}');
getCheckedProjectItems().should('have.length', 0);
});
describe('select projects message', () => {
it('should display on load', () => {
getSelectProjectsMessage().should('be.visible');
});
it('should hide when a project is selected', () => {
cy.contains('cart').as('cart');
cy.get('@cart').scrollIntoView();
cy.get('@cart').should('be.visible');
cy.get('[data-project="cart"]').should('be.visible');
cy.get('[data-project="cart"]').click({ force: true });
getSelectProjectsMessage().should('not.exist');
});
});
describe('text filter', () => {
it('should hide clear button initially', () => {
getTextFilterReset().should('not.exist');
});
it('should show clear button after typing', () => {
getTextFilterInput().type('cart');
getTextFilterReset().should('exist');
});
it('should clear selection on reset', () => {
getTextFilterInput().type('cart');
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.filter((project) =>
project.name.includes('cart')
).length
);
getTextFilterReset().click();
getCheckedProjectItems().should('have.length', 0);
});
it('should hide clear button after clicking', () => {
getTextFilterInput().type('cart');
getTextFilterReset().click().should('not.exist');
});
it('should filter projects by text when pressing enter', () => {
getTextFilterInput().type('cart{enter}');
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.filter((project) =>
project.name.includes('cart')
).length
);
});
it('should filter projects by text after debounce', () => {
getTextFilterInput().type('cart');
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.filter((project) =>
project.name.includes('cart')
).length
);
});
it('should include projects in path when option is checked', () => {
getTextFilterInput().type('cart');
getIncludeProjectsInPathButton().click();
getCheckedProjectItems().should(
'have.length.gt',
nxExamplesJson.projects.filter((project) =>
project.name.includes('cart')
).length
);
});
});
describe('proximity', () => {
it('should change when increment/decrement button is clicked', () => {
cy.get('[data-cy="depth-value"]').should('contain', '1');
getSearchDepthIncrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '2');
getSearchDepthDecrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '1');
});
it("should reactivate proximity if it's disabled and a button is clicked", () => {
getSearchDepthIncrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '2');
getSearchDepthCheckbox()
.should('be.checked')
.click()
.should('not.be.checked')
.click();
getSearchDepthIncrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '3');
getSearchDepthCheckbox()
.should('be.checked')
.click()
.should('not.be.checked')
.click();
getSearchDepthDecrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '2');
getSearchDepthCheckbox()
.should('be.checked')
.click()
.should('not.be.checked')
.click();
// return to 1 for following tests
getSearchDepthDecrementButton().click();
});
it('should not go below 1', () => {
getSearchDepthIncrementButton().click();
getSearchDepthIncrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '3');
getSearchDepthDecrementButton().click();
getSearchDepthDecrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '1');
getSearchDepthDecrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '1');
});
});
describe('select all button', () => {
it('should check all project items', () => {
getSelectAllButton().scrollIntoView().click({ force: true });
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.length
);
});
});
describe('deselect all button', () => {
it('should uncheck all project items', () => {
getDeselectAllButton().click();
getUncheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.length
);
getSelectProjectsMessage().should('be.visible');
});
});
describe('show affected button', () => {
it('should be hidden initially', () => {
getSelectAffectedButton().should('not.exist');
});
it('should check all affected project items', () => {
cy.intercept('/assets/project-graphs/affected.json', {
fixture: 'affected.json',
}).as('getAffectedGraph');
cy.get('[data-cy=project-select]').select('affected', { force: true });
cy.wait('@getAffectedGraph');
getSelectAffectedButton().click();
getCheckedProjectItems().should(
'have.length',
affectedJson.affected.length
);
// switch back to Nx Examples graph before proceeding
cy.intercept('/assets/project-graphs/e2e.json', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
cy.get('[data-cy=project-select]').select('e2e', { force: true });
cy.wait('@getGraph');
});
});
describe('selecting projects', () => {
it('should select a project by clicking on the project name', () => {
cy.get('[data-project="cart"]').should('have.data', 'active', false);
cy.get('[data-project="cart"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]').should('exist');
});
it('should deselect a project by clicking on the project name again', () => {
cy.get('[data-project="cart"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]')
.should('exist')
.click({
force: true,
});
cy.get('[data-project="cart"][data-active="false"]').should('exist');
});
it('should select a project by clicking on the selected icon', () => {
cy.get('[data-project="cart"][data-active="false"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]')
.should('exist')
.parent()
.siblings()
.first()
.should('exist')
.click({
force: true,
});
cy.get('[data-project="cart"][data-active="false"]').should('exist');
});
});
describe('focusing projects in sidebar', () => {
it('should select appropriate projects', () => {
cy.contains('cart').as('cart');
cy.get('@cart').scrollIntoView();
cy.get('@cart').should('be.visible');
getFocusButtonForProject('cart').click({ force: true });
const dependencies = nxExamplesJson.dependencies.cart;
const dependents = Object.keys(nxExamplesJson.dependencies).filter(
(key) =>
nxExamplesJson.dependencies[key]
.map((dependencies) => dependencies.target)
.includes('cart')
);
getUnfocusProjectButton().should('exist');
getCheckedProjectItems().should(
'have.length',
['cart', ...dependencies, ...dependents].length
);
});
it('should url encode projects with special chars', () => {
getFocusButtonForProject('@scoped/project-a').click({ force: true });
cy.url().should('include', '%40scoped%2Fproject-a');
});
});
describe('unfocus button', () => {
it('should uncheck all project items', () => {
getFocusButtonForProject('cart').click({ force: true });
getUnfocusProjectButton().click();
getUnfocusProjectButton().should('not.exist');
getCheckedProjectItems().should('have.length', 0);
});
});
describe('toggle all projects in folder button', () => {
it('should check all projects in folder if at least one project checked', () => {
cy.contains('shared-product-state').as('shared-product-state');
cy.get('@shared-product-state').scrollIntoView();
cy.get('@shared-product-state').should('be.visible');
cy.get('[data-project="shared-product-state"]').should('be.visible');
cy.get('[data-project="shared-product-state"]').click({ force: true });
getToggleAllButtonForFolder('shared/product').click({ force: true });
getCheckedProjectItems().should('have.length', 4);
});
it('should check all projects in folder if no projects checked yet', () => {
getToggleAllButtonForFolder('shared').click({ force: true });
getCheckedProjectItems().should('have.length', 5);
});
it('should uncheck all projects in folder if all projects checked yet', () => {
getToggleAllButtonForFolder('shared').click({ force: true });
getCheckedProjectItems().should('have.length', 5);
getToggleAllButtonForFolder('shared').click({ force: true });
getCheckedProjectItems().should('have.length', 0);
});
});
describe('image download button', () => {
it('should be hidden initally', () => {
getImageDownloadButton().should('have.class', 'opacity-0');
});
it('should be shown when a project is selected', () => {
cy.get('[data-project="cart"]').click({ force: true });
getImageDownloadButton().should('not.have.class', 'opacity-0');
});
it('should be hidden when no more projects are selected', () => {
cy.get('[data-project="cart"]').click({ force: true });
getDeselectAllButton().click();
getImageDownloadButton().should('have.class', 'opacity-0');
});
});
describe('setting url params', () => {
it('should set focused project', () => {
cy.contains('cart').as('cart');
cy.get('@cart').scrollIntoView();
cy.get('@cart').should('be.visible');
getFocusButtonForProject('cart').click({ force: true });
getUnfocusProjectButton().should('exist');
cy.url().should('contain', '/projects/cart');
cy.reload();
getUnfocusProjectButton().should('exist');
});
it('should set group by folder', () => {
getGroupByFolderCheckbox().click();
getGroupByFolderCheckbox().should('be.checked');
cy.url().should('contain', 'groupByFolder=true');
cy.reload();
getGroupByFolderCheckbox().should('be.checked');
});
it('should set search depth disabled', () => {
// it's on by default, clicking should disable it
getSearchDepthCheckbox().click();
getSearchDepthCheckbox().should('not.be.checked');
cy.url().should('contain', 'searchDepth=0');
cy.reload();
getSearchDepthCheckbox().should('not.be.checked');
// re-enable to clean-up for following tests
getSearchDepthCheckbox().click();
});
it('should set search depth if greater than 1', () => {
// it's on by default and set to 1, clicking should change it to 2
getSearchDepthIncrementButton().click();
cy.get('[data-cy="depth-value"]').should('contain', '2');
cy.url().should('contain', 'searchDepth=2');
cy.reload();
cy.get('[data-cy="depth-value"]').should('contain', '2');
});
it('should set select to all', () => {
getSelectAllButton().click();
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.length
);
cy.url().should('contain', '/projects/all');
cy.reload();
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.length
);
});
});
});
describe('loading graph client with url params', () => {
beforeEach(() => {
cy.intercept('/assets/project-graphs/*', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
});
testProjectsRoutes('browser', ['/e2e/projects']);
});
@@ -0,0 +1,237 @@
import {
getCheckedProjectItems,
getDeselectAllButton,
getFocusButtonForProject,
getGroupByFolderCheckbox,
getGroupByProjectCheckbox,
getImageDownloadButton,
getIncludeProjectsInPathButton,
getSearchDepthCheckbox,
getSearchDepthIncrementButton,
getSelectAffectedButton,
getSelectAllButton,
getSelectProjectsMessage,
getSelectTargetDropdown,
getSelectTasksMessage,
getTextFilterInput,
getTextFilterReset,
getToggleAllButtonForFolder,
getUncheckedProjectItems,
getUnfocusProjectButton,
openTooltipForNode,
} from '../support/app.po';
import * as affectedJson from '../fixtures/affected.json';
import { testProjectsRoutes, testTaskRoutes } from '../support/routing-tests';
import * as nxExamplesTaskInputs from '../fixtures/nx-examples-task-inputs.json';
describe('dev mode - task graph', () => {
before(() => {
cy.intercept('/assets/project-graphs/e2e.json', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
cy.intercept('/assets/task-graphs/e2e.json', {
fixture: 'nx-examples-task-graphs.json',
}).as('getTaskGraph');
cy.visit('/e2e/tasks');
// wait for initial graphs to finish loading
cy.wait('@getGraph');
cy.wait('@getTaskGraph');
});
afterEach(() => {
// clean up by hiding all tasks
getDeselectAllButton().click();
getCheckedProjectItems().should('have.length', 0);
});
describe('select tasks message', () => {
it('should display on load', () => {
getSelectTasksMessage().should('be.visible');
});
it('should hide when a project is selected', () => {
cy.contains('cart').as('cart');
cy.get('@cart').scrollIntoView();
cy.get('@cart').should('be.visible');
cy.get('[data-project="cart"]').should('be.visible');
cy.get('[data-project="cart"]').click({ force: true });
getSelectTasksMessage().should('not.exist');
});
});
describe('select all button', () => {
it('should check all project items', () => {
getSelectAllButton().scrollIntoView().click({ force: true });
getCheckedProjectItems().should('have.length', 2);
});
it('should remove all from the url when no longer selected', () => {
getSelectAllButton().scrollIntoView().click({ force: true });
cy.url().should('contain', '/all');
getDeselectAllButton().click();
cy.url().should('not.contain', '/all');
getSelectAllButton().scrollIntoView().click({ force: true });
cy.url().should('contain', '/all');
cy.get('[data-project="cart"]').click({
force: true,
});
cy.url().should('not.contain', '/all');
});
});
describe('deselect all button', () => {
it('should uncheck all project items', () => {
getDeselectAllButton().click();
getUncheckedProjectItems().should('have.length', 2);
getSelectTasksMessage().should('be.visible');
});
});
describe('selecting projects', () => {
it('should select a project by clicking on the project name', () => {
cy.get('[data-project="cart"]').should('have.data', 'active', false);
cy.get('[data-project="cart"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]').should('exist');
});
it('should deselect a project by clicking on the project name again', () => {
cy.get('[data-project="cart"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]')
.should('exist')
.click({
force: true,
});
cy.get('[data-project="cart"][data-active="false"]').should('exist');
});
it('should select a project by clicking on the selected icon', () => {
cy.get('[data-project="cart"][data-active="false"]').click({
force: true,
});
cy.get('[data-project="cart"][data-active="true"]')
.should('exist')
.parent()
.siblings()
.first()
.should('exist')
.click({
force: true,
});
cy.get('[data-project="cart"][data-active="false"]').should('exist');
});
});
describe('image download button', () => {
it('should be hidden initally', () => {
getImageDownloadButton().should('have.class', 'opacity-0');
});
it('should be shown when a project is selected', () => {
cy.get('[data-project="cart"]').click({ force: true });
getImageDownloadButton().should('not.have.class', 'opacity-0');
});
it('should be hidden when no more projects are selected', () => {
cy.get('[data-project="cart"]').click({ force: true });
getDeselectAllButton().click();
getImageDownloadButton().should('have.class', 'opacity-0');
});
});
describe('setting route params', () => {
it('should set selected target', () => {
getSelectTargetDropdown().select('e2e', { force: true });
cy.url().should('contain', 'tasks/e2e');
});
it('should set group by project', () => {
getGroupByProjectCheckbox().click();
cy.url().should('contain', 'groupByProject=true');
});
});
describe('loading graph client with url params', () => {
beforeEach(() => {
cy.intercept('/assets/project-graphs/*', {
fixture: 'nx-examples-project-graph.json',
}).as('getGraph');
cy.intercept('/assets/task-graphs/e2e.json', {
fixture: 'nx-examples-task-graphs.json',
}).as('getTaskGraphs');
});
// check that params work from old base url of /
// and also new /projects route
testTaskRoutes('browser', ['/e2e/tasks']);
});
describe('file inputs', () => {
beforeEach(() => {
cy.intercept(
{
method: 'GET',
url: '/task-inputs.json*',
},
async (req) => {
// Extract the desired query parameter
const taskId = req.url.split('taskId=')[1];
// Load the fixture data and find the property based on the query parameter
const expandedInputs = nxExamplesTaskInputs[taskId];
// Reply with the selected property
req.reply({
body: expandedInputs,
});
}
).as('getTaskInputs');
});
it('should display input files', () => {
getSelectTargetDropdown().select('build', { force: true });
cy.get('[data-project="cart"]').click({
force: true,
});
openTooltipForNode('cart:build');
cy.get('[data-cy="inputs-accordion"]').click();
cy.get('[data-cy="input-list-entry"]').should('have.length', 18);
const expectedSections = [
'cart-cart-page',
'shared-assets',
'shared-header',
'shared-styles',
'External Inputs',
];
cy.get('[data-cy="input-section-entry"]').each((el, idx) => {
expect(el.text()).to.equal(expectedSections[idx]);
});
const sharedHeaderSelector =
'[data-cy="input-section-entry"]:contains(shared-header)';
cy.get(sharedHeaderSelector).click();
cy.get(sharedHeaderSelector)
.nextAll('[data-cy="input-list-entry"]')
.should('have.length', 9);
});
});
});
@@ -0,0 +1,18 @@
describe('release serve-mode app', () => {
beforeEach(() => {
cy.intercept('/assets/project-graphs/*').as('getGraph');
cy.visit('/');
// wait for first graph to finish loading
cy.wait('@getGraph');
});
it('should not display experimental features', () => {
cy.get('experimental-features').should('not.exist');
});
it('should not display the debugger', () => {
cy.get('debugger-panel').should('not.exist');
});
});
@@ -0,0 +1,97 @@
import { testProjectsRoutes, testTaskRoutes } from '../support/routing-tests';
import {
getCheckedProjectItems,
getDeselectAllButton,
getFocusButtonForProject,
getTextFilterInput,
getUnfocusProjectButton,
} from '../support/app.po';
import * as nxExamplesJson from '../fixtures/nx-examples-project-graph.json';
describe('release static-mode app', () => {
describe('smoke tests', () => {
beforeEach(() => {
cy.visit('/');
});
it('should not display experimental features', () => {
cy.get('experimental-features').should('not.exist');
});
it('should not display the debugger', () => {
cy.get('debugger-panel').should('not.exist');
});
it('should use hash router', () => {
cy.url().should('contain', '/#/projects');
});
});
describe('routing', () => {
testProjectsRoutes('hash', ['/projects']);
});
describe('api tests', () => {
before(() => {
cy.visit('/#/projects/');
});
afterEach(() => {
// clean up by hiding all projects and clearing text input
getDeselectAllButton().click();
getTextFilterInput().clear();
getCheckedProjectItems().should('have.length', 0);
});
describe('externalApi public api', () => {
it('should focus project', () => {
cy.window().then((window) => {
// Cast the cypress AUTWindow to the augmented global Window (tsgo
// doesn't surface the Window augmentation through AUTWindow).
(window as Window).externalApi.focusProject('cart');
checkFocusedProject(nxExamplesJson, 'cart');
});
});
it('should select all projects', () => {
cy.window().then((window) => {
(window as Window).externalApi.selectAllProjects();
checkSelectAll(nxExamplesJson);
});
});
});
});
});
function checkFocusedProject(projectGraphJson: any, projectName: string) {
const dependencies = projectGraphJson.dependencies.cart;
const dependents = Object.keys(nxExamplesJson.dependencies).filter((key) =>
nxExamplesJson.dependencies[key]
.map((dependencies) => dependencies.target)
.includes(projectName)
);
getUnfocusProjectButton().should('exist');
getCheckedProjectItems().should(
'have.length',
[projectName, ...dependencies, ...dependents].length
);
cy.url().should('contain', `/projects/${projectName}`);
}
function checkSelectAll(projectGraphJson: any) {
getCheckedProjectItems().should(
'have.length',
projectGraphJson.projects.length
);
cy.url().should('contain', `/projects/all`);
}
function checkSelectedProject(projectName: string) {
cy.get(`[data-project="${projectName}"][data-active="true"]`).should('exist');
}
function checkDeselectedProject(projectName: string) {
cy.get(`[data-project="${projectName}"][data-active="true"]`).should(
'not.exist'
);
}
@@ -0,0 +1,53 @@
import { getProjectItems } from '../support/app.po';
describe('watch mode - app', () => {
beforeEach(() => {
cy.visit('/projects');
});
it('should auto-select new libs as they are created', () => {
const excludedValues = ['existing-app-1', 'existing-lib-1'];
checkSelectedProjects(2, excludedValues);
checkSelectedProjects(3, excludedValues);
checkSelectedProjects(4, excludedValues);
});
it('should retain selected projects as new libs are created', () => {
cy.get('[data-project="existing-app-1"]').click();
cy.get('[data-project="existing-lib-1"]').click();
checkSelectedProjects(3, []);
checkSelectedProjects(4, []);
checkSelectedProjects(5, []);
});
it('should not re-add new libs if they were un-selected', () => {
cy.get('[data-project*="3"][data-active="true"]', { timeout: 6000 })
.should('exist')
.click({ force: true });
cy.get('[data-project*="3"][data-active="false"]', {
timeout: 6000,
}).should('exist');
cy.get('[data-project*="3"]', { timeout: 6000 })
.first()
.should((project) => {
expect(project.data('active')).to.be.false;
});
});
});
function checkSelectedProjects(
expectedNumberOfProjects: number,
excludedProjects: string[]
) {
getProjectItems().should((projects) => {
expect(projects.length).to.equal(expectedNumberOfProjects);
projects.each(function () {
if (!excludedProjects.includes(this.dataset.project)) {
expect(this.dataset.active).to.eq('true');
}
});
});
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,450 @@
{
"taskGraph": {
"tasks": {
"products-product-detail-page:lint": {
"id": "products-product-detail-page:lint",
"target": {
"project": "products-product-detail-page",
"target": "lint"
},
"projectRoot": "libs/products/product-detail-page",
"overrides": {}
},
"products-product-detail-page:test": {
"id": "products-product-detail-page:test",
"target": {
"project": "products-product-detail-page",
"target": "test"
},
"projectRoot": "libs/products/product-detail-page",
"overrides": {}
},
"shared-product-state:lint": {
"id": "shared-product-state:lint",
"target": {
"project": "shared-product-state",
"target": "lint"
},
"projectRoot": "libs/shared/product/state",
"overrides": {}
},
"shared-product-state:test": {
"id": "shared-product-state:test",
"target": {
"project": "shared-product-state",
"target": "test"
},
"projectRoot": "libs/shared/product/state",
"overrides": {}
},
"shared-product-types:lint": {
"id": "shared-product-types:lint",
"target": {
"project": "shared-product-types",
"target": "lint"
},
"projectRoot": "libs/shared/product/types",
"overrides": {}
},
"shared-product-data:lint": {
"id": "shared-product-data:lint",
"target": {
"project": "shared-product-data",
"target": "lint"
},
"projectRoot": "libs/shared/product/data",
"overrides": {}
},
"products-home-page:lint": {
"id": "products-home-page:lint",
"target": {
"project": "products-home-page",
"target": "lint"
},
"projectRoot": "libs/products/home-page",
"overrides": {}
},
"products-home-page:test": {
"id": "products-home-page:test",
"target": {
"project": "products-home-page",
"target": "test"
},
"projectRoot": "libs/products/home-page",
"overrides": {}
},
"shared-cart-state:lint": {
"id": "shared-cart-state:lint",
"target": {
"project": "shared-cart-state",
"target": "lint"
},
"projectRoot": "libs/shared/cart/state",
"overrides": {}
},
"shared-cart-state:test": {
"id": "shared-cart-state:test",
"target": {
"project": "shared-cart-state",
"target": "test"
},
"projectRoot": "libs/shared/cart/state",
"overrides": {}
},
"shared-product-ui:lint": {
"id": "shared-product-ui:lint",
"target": {
"project": "shared-product-ui",
"target": "lint"
},
"projectRoot": "libs/shared/product/ui",
"overrides": {}
},
"shared-product-ui:test": {
"id": "shared-product-ui:test",
"target": {
"project": "shared-product-ui",
"target": "test"
},
"projectRoot": "libs/shared/product/ui",
"overrides": {}
},
"shared-e2e-utils:lint": {
"id": "shared-e2e-utils:lint",
"target": {
"project": "shared-e2e-utils",
"target": "lint"
},
"projectRoot": "libs/shared/e2e-utils",
"overrides": {}
},
"cart-cart-page:lint": {
"id": "cart-cart-page:lint",
"target": {
"project": "cart-cart-page",
"target": "lint"
},
"projectRoot": "libs/cart/cart-page",
"overrides": {}
},
"cart-cart-page:test": {
"id": "cart-cart-page:test",
"target": {
"project": "cart-cart-page",
"target": "test"
},
"projectRoot": "libs/cart/cart-page",
"overrides": {}
},
"shared-header:lint": {
"id": "shared-header:lint",
"target": {
"project": "shared-header",
"target": "lint"
},
"projectRoot": "libs/shared/header",
"overrides": {}
},
"shared-header:test": {
"id": "shared-header:test",
"target": {
"project": "shared-header",
"target": "test"
},
"projectRoot": "libs/shared/header",
"overrides": {}
},
"shared-jsxify:lint": {
"id": "shared-jsxify:lint",
"target": {
"project": "shared-jsxify",
"target": "lint"
},
"projectRoot": "libs/shared/jsxify",
"overrides": {}
},
"products-e2e:e2e": {
"id": "products-e2e:e2e",
"target": {
"project": "products-e2e",
"target": "e2e"
},
"projectRoot": "apps/products-e2e",
"overrides": {}
},
"products-e2e:e2e:production": {
"id": "products-e2e:e2e:production",
"target": {
"project": "products-e2e",
"target": "e2e",
"configuration": "production"
},
"projectRoot": "apps/products-e2e",
"overrides": {}
},
"products-e2e:lint": {
"id": "products-e2e:lint",
"target": {
"project": "products-e2e",
"target": "lint"
},
"projectRoot": "apps/products-e2e",
"overrides": {}
},
"cart-e2e:e2e": {
"id": "cart-e2e:e2e",
"target": {
"project": "cart-e2e",
"target": "e2e"
},
"projectRoot": "apps/cart-e2e",
"overrides": {}
},
"cart-e2e:e2e:production": {
"id": "cart-e2e:e2e:production",
"target": {
"project": "cart-e2e",
"target": "e2e",
"configuration": "production"
},
"projectRoot": "apps/cart-e2e",
"overrides": {}
},
"cart-e2e:lint": {
"id": "cart-e2e:lint",
"target": {
"project": "cart-e2e",
"target": "lint"
},
"projectRoot": "apps/cart-e2e",
"overrides": {}
},
"products:build": {
"id": "products:build",
"target": {
"project": "products",
"target": "build"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:build:production": {
"id": "products:build:production",
"target": {
"project": "products",
"target": "build",
"configuration": "production"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:serve": {
"id": "products:serve",
"target": {
"project": "products",
"target": "serve"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:serve:production": {
"id": "products:serve:production",
"target": {
"project": "products",
"target": "serve",
"configuration": "production"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:extract-i18n": {
"id": "products:extract-i18n",
"target": {
"project": "products",
"target": "extract-i18n"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:lint": {
"id": "products:lint",
"target": {
"project": "products",
"target": "lint"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:test": {
"id": "products:test",
"target": {
"project": "products",
"target": "test"
},
"projectRoot": "apps/products",
"overrides": {}
},
"products:deploy": {
"id": "products:deploy",
"target": {
"project": "products",
"target": "deploy"
},
"projectRoot": "apps/products",
"overrides": {}
},
"cart:build:production": {
"id": "cart:build:production",
"target": {
"project": "cart",
"target": "build",
"configuration": "production"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:build:development": {
"id": "cart:build:development",
"target": {
"project": "cart",
"target": "build",
"configuration": "development"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:serve:development": {
"id": "cart:serve:development",
"target": {
"project": "cart",
"target": "serve",
"configuration": "development"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:serve:production": {
"id": "cart:serve:production",
"target": {
"project": "cart",
"target": "serve",
"configuration": "production"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:lint": {
"id": "cart:lint",
"target": {
"project": "cart",
"target": "lint"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:test": {
"id": "cart:test",
"target": {
"project": "cart",
"target": "test"
},
"projectRoot": "apps/cart",
"overrides": {}
},
"cart:deploy": {
"id": "cart:deploy",
"target": {
"project": "cart",
"target": "deploy"
},
"projectRoot": "apps/cart",
"overrides": {}
}
},
"dependencies": {
"products-product-detail-page:lint": [],
"products-product-detail-page:test": [],
"shared-product-state:lint": [],
"shared-product-state:test": [],
"shared-product-types:lint": [],
"shared-product-data:lint": [],
"products-home-page:lint": [],
"products-home-page:test": [],
"shared-cart-state:lint": [],
"shared-cart-state:test": [],
"shared-product-ui:lint": [],
"shared-product-ui:test": [],
"shared-e2e-utils:lint": [],
"cart-cart-page:lint": [],
"cart-cart-page:test": [],
"shared-header:lint": [],
"shared-header:test": [],
"shared-jsxify:lint": [],
"products-e2e:e2e": [],
"products-e2e:e2e:production": [],
"products-e2e:lint": [],
"cart-e2e:e2e": [],
"cart-e2e:e2e:production": [],
"cart-e2e:lint": [],
"products:build": [],
"products:build:production": [],
"products:serve": [],
"products:serve:production": [],
"products:extract-i18n": [],
"products:lint": [],
"products:test": [],
"products:deploy": [],
"cart:build:production": [],
"cart:build:development": [],
"cart:serve:development": [],
"cart:serve:production": [],
"cart:lint": [],
"cart:test": [],
"cart:deploy": []
},
"continuousDependencies": {},
"roots": [
"products-product-detail-page:lint",
"products-product-detail-page:test",
"shared-product-state:lint",
"shared-product-state:test",
"shared-product-types:lint",
"shared-product-data:lint",
"products-home-page:lint",
"products-home-page:test",
"shared-cart-state:lint",
"shared-cart-state:test",
"shared-product-ui:lint",
"shared-product-ui:test",
"shared-e2e-utils:lint",
"cart-cart-page:lint",
"cart-cart-page:test",
"shared-header:lint",
"shared-header:test",
"shared-jsxify:lint",
"products-e2e:e2e",
"products-e2e:e2e:production",
"products-e2e:lint",
"cart-e2e:e2e",
"cart-e2e:e2e:production",
"cart-e2e:lint",
"products:build",
"products:build:production",
"products:serve",
"products:serve:production",
"products:extract-i18n",
"products:lint",
"products:test",
"products:deploy",
"cart:build:production",
"cart:build:development",
"cart:serve:development",
"cart:serve:production",
"cart:lint",
"cart:test",
"cart:deploy"
]
},
"plans": {},
"error": null
}
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
// ensure we have the types for the externalApi on window
// eslint-disable-next-line @nx/enforce-module-boundaries
import type { ExternalApi } from '@nx/graph/shared';
declare global {
interface Window {
externalApi: ExternalApi;
}
}
+18
View File
@@ -0,0 +1,18 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// Preprocess Typescript file using Nx helper
};
+56
View File
@@ -0,0 +1,56 @@
export const getSelectProjectsMessage = () =>
cy.contains('Please select a project in the sidebar');
export const getSelectTasksMessage = () =>
cy.contains('Please select a task in the sidebar');
export const getGraph = () => cy.get('#graph-container');
export const getSelectAllButton = () => cy.get('[data-cy=selectAllButton]');
export const getDeselectAllButton = () => cy.get('[data-cy=deselectAllButton]');
export const getSelectAffectedButton = () => cy.get('[data-cy=affectedButton]');
export const getUnfocusProjectButton = () => cy.get('[data-cy=unfocusButton]');
export const getProjectItems = () =>
cy.get('[data-project]', { timeout: 6000 });
export const getCheckedProjectItems = () => cy.get('[data-active="true"]');
export const getUncheckedProjectItems = () => cy.get('[data-active="false"]');
export const getGroupByFolderCheckbox = () =>
cy.get('input[name=groupByFolder]');
export const getGroupByProjectCheckbox = () =>
cy.get('input[name=groupByProject]');
export const getSearchDepthCheckbox = () =>
cy.get('input[name=depthFilter][value=depthFilterActivated]');
export const getTextFilterInput = () => cy.get('[data-cy=textFilterInput]');
export const getTextFilterReset = () => cy.get('[data-cy=textFilterReset]');
export const getSearchDepthDecrementButton = () =>
cy.get('[data-cy=decrement-depth-filter]');
export const getSearchDepthIncrementButton = () =>
cy.get('[data-cy=increment-depth-filter]');
export const getIncludeProjectsInPathButton = () =>
cy.get('input[name=textFilterCheckbox]');
export const getImageDownloadButton = () =>
cy.get('[data-cy=downloadImageButton]');
export const getFocusButtonForProject = (projectName: string) =>
cy.get(`[data-cy="focus-button-${projectName}"]`);
export const getToggleAllButtonForFolder = (folderName: string) =>
cy.get(`[data-cy="toggle-folder-visibility-button-${folderName}"]`);
export const getSelectTargetDropdown = () =>
cy.get('[data-cy=selected-target-dropdown]');
export const openTooltipForNode = (nodeId: string) =>
cy.window().then((window) => {
// @ts-ignore - we will access private methods only in this e2e test
const pos = window.externalApi._graphService.renderGraph.cy
.$(nodeId)
.renderedPosition();
cy.get('#cytoscape-graph').click(pos.x, pos.y);
});
+35
View File
@@ -0,0 +1,35 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
declare global {
namespace Cypress {
interface Chainable<Subject> {
login(email: string, password: string): void;
}
}
}
//
// -- This is a parent command --
Cypress.Commands.add('login', (email: string, password: string) => {
console.log('Custom command example: Login', email, password);
});
export {};
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
+17
View File
@@ -0,0 +1,17 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
@@ -0,0 +1,177 @@
import * as nxExamplesJson from '../fixtures/nx-examples-project-graph.json';
import {
getCheckedProjectItems,
getGroupByFolderCheckbox,
getGroupByProjectCheckbox,
getSearchDepthCheckbox,
getSelectTargetDropdown,
} from './app.po';
function waitForProjectGraph(router: 'hash' | 'browser') {
if (router === 'browser') {
cy.wait('@getGraph');
}
}
function waitForTaskGraphs(router: 'hash' | 'browser') {
if (router === 'browser') {
cy.wait('@getTaskGraphs');
}
}
function resolveProjectsRoute(
router: 'hash' | 'browser',
route: string,
paramString: string
) {
if (router === 'hash') {
return `/#${route}?${paramString}`;
} else {
return `${route}?${paramString}`;
}
}
function resolveTasksRoute(
router: 'hash' | 'browser',
route: string,
paramString: string
) {
if (router === 'hash') {
return `/#${route}?${paramString}`;
} else {
return `${route}?${paramString}`;
}
}
export function testProjectsRoutes(
router: 'hash' | 'browser',
routes: string[]
) {
routes.forEach((route) => {
describe(`for route ${route}`, () => {
it('should focus projects', () => {
cy.visit(resolveProjectsRoute(router, `${route}/cart`, ''));
// wait for first graph to finish loading
waitForProjectGraph(router);
const dependencies = nxExamplesJson.dependencies.cart;
const dependents = Object.keys(nxExamplesJson.dependencies).filter(
(key) =>
nxExamplesJson.dependencies[key]
.map((dependencies) => dependencies.target)
.includes('cart')
);
getCheckedProjectItems().should(
'have.length',
['cart', ...dependencies, ...dependents].length
);
});
it('should focus projects with special characters', () => {
cy.visit(
resolveProjectsRoute(router, `${route}/%40scoped%2Fproject-a`, '')
);
// wait for first graph to finish loading
waitForProjectGraph(router);
const dependencies = nxExamplesJson.dependencies['@scoped/project-a'];
const dependents = Object.keys(nxExamplesJson.dependencies).filter(
(key) =>
nxExamplesJson.dependencies[key]
.map((dependencies) => dependencies.target)
.includes('@scoped/project-a')
);
getCheckedProjectItems().should(
'have.length',
['@scoped/project-a', ...dependencies, ...dependents].length
);
});
it('should focus projects with search depth', () => {
cy.visit(
resolveProjectsRoute(router, `${route}/cart`, `searchDepth=2`)
);
// wait for first graph to finish loading
waitForProjectGraph(router);
getCheckedProjectItems().should('have.length', 10);
getSearchDepthCheckbox().should('exist');
});
it('should focus projects with search depth disabled', () => {
cy.visit(
resolveProjectsRoute(router, `${route}/cart`, `searchDepth=0`)
);
// wait for first graph to finish loading
waitForProjectGraph(router);
getCheckedProjectItems().should('have.length', 12);
getSearchDepthCheckbox().should('exist');
});
it('should set group by folder', () => {
cy.visit(
resolveProjectsRoute(router, `${route}/cart`, `groupByFolder=true`)
);
// wait for first graph to finish loading
waitForProjectGraph(router);
getGroupByFolderCheckbox().should('be.checked');
});
it('should select all projects', () => {
cy.visit(resolveProjectsRoute(router, `${route}/all`, ``));
// wait for first graph to finish loading
waitForProjectGraph(router);
getCheckedProjectItems().should(
'have.length',
nxExamplesJson.projects.length
);
});
});
});
}
export function testTaskRoutes(router: 'hash' | 'browser', routes: string[]) {
routes.forEach((route) => {
describe(`for route ${route}`, () => {
it('should set group by project', () => {
cy.visit(resolveTasksRoute(router, route, `groupByProject=true`));
// wait for first graph to finish loading
waitForProjectGraph(router);
waitForTaskGraphs(router);
getGroupByProjectCheckbox().should('be.checked');
});
it('should set selected target', () => {
cy.visit(resolveTasksRoute(router, `${route}/e2e`, ''));
// wait for first graph to finish loading
waitForProjectGraph(router);
waitForTaskGraphs(router);
getSelectTargetDropdown().should('have.value', 'e2e');
});
it('should select all', () => {
cy.visit(resolveTasksRoute(router, `${route}/e2e/all`, ''));
// wait for first graph to finish loading
waitForProjectGraph(router);
waitForTaskGraphs(router);
getSelectTargetDropdown().should('have.value', 'e2e');
getCheckedProjectItems().should('have.length', 2);
});
});
});
}
+26
View File
@@ -0,0 +1,26 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"sourceMap": false,
"outDir": "out-tsc",
"allowJs": true,
"types": ["cypress", "node"],
"typeRoots": [
"../../node_modules/@types",
"../../node_modules/.pnpm/cypress@14.3.0/node_modules/cypress/types"
],
"lib": ["DOM"]
},
"files": [],
"include": [
"cypress.config.ts",
"cypress-watch-mode.config.ts",
"cypress-release.config.ts",
"cypress-release-static.config.ts",
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json"
],
"references": [],
"exclude": ["out-tsc"]
}