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
+10
View File
@@ -0,0 +1,10 @@
import playwright from 'eslint-plugin-playwright';
import { baseConfig } from '../../eslint.config.mjs';
export default [
...baseConfig,
{
...playwright.configs['flat/recommended'],
files: ['src/**/*.{ts,js,tsx,jsx}'],
},
];
+67
View File
@@ -0,0 +1,67 @@
import { defineConfig, devices } from '@playwright/test';
/*
* NOTE: We're not using the `nxE2EPreset` from `@nx/playwright` because there is an issue with `nx-ignore` + nx repo + crystal.
*
* The problem is specific to Nx repo, because of the following incompatible combination:
* 1. `nx-ignore` only installs nx + necessary plugins (as defined in nx.json).
* 2. `@nx/playwright/plugin` registers tsconfig-paths, thus `@nx/devkit` and `nx` packages are read from source
* e.g. packages/devkit rather than node_modules/@nx/devkit
* 3. When `@nx/playwright/plugin` reads this config file (playwright.config.ts), it eventually loads `packages/devkit` instead of `node_modules/@nx/devkit`.
*
* Then, you will see an error like this:
* Unable to create nodes for nx-dev/nx-dev-e2e/playwright.config.ts using plugin @nx/playwright/plugin.
* Inner Error: Error: Cannot find module 'fs-extra'
* Require stack:
* - /vercel/path0/packages/nx/src/project-graph/nx-deps-cache.ts
* - /vercel/path0/packages/nx/src/project-graph/project-graph.ts
* - /vercel/path0/packages/nx/src/config/workspaces.ts
* - /vercel/path0/packages/nx/src/devkit-exports.ts
* - /vercel/path0/packages/devkit/index.ts
*
* Again, this is specific to Nx repo only, because we both install nx + plugins to node_modules, but they are also mapped to source in tsconfig paths.
*/
// For CI, you may want to set BASE_URL to the deployed application.
const baseURL = process.env['BASE_URL'] || 'http://localhost:4200';
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './src',
outputDir: '../../dist/.playwright/nx-dev-e2e/test-output',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'list',
// how long the entire suite can run, prevent CI from timing out
globalTimeout: process.env.CI ? 1_800_000 : undefined,
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL,
// how long each page.goto can take before timing out
navigationTimeout: process.env.CI ? 30_000 : undefined,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm exec nx run nx-dev:start',
url: 'http://localhost:4200',
reuseExistingServer: !process.env.CI,
timeout: 180_000,
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
+18
View File
@@ -0,0 +1,18 @@
{
"name": "nx-dev-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "nx-dev/nx-dev-e2e/src",
"projectType": "application",
"targets": {
"pw-e2e": {
"command": "echo 'pw-e2e disabled'",
"cache": true
},
"e2e-ci": {
"command": "echo 'e2e-ci disabled'",
"cache": true
}
},
"tags": ["scope:nx-dev", "type:e2e"],
"implicitDependencies": ["nx-dev"]
}
@@ -0,0 +1,43 @@
import { assertTextOnPage } from './helpers';
import { Page, test, expect } from '@playwright/test';
const pages: Array<{ title: string; path: string }> = [
{ title: 'create-nx-workspace', path: '/cli/create-nx-workspace' },
{ title: 'generate', path: '/cli/generate' },
{ title: 'run', path: '/cli/run' },
{ title: 'daemon', path: '/cli/daemon' },
{ title: 'graph', path: '/cli/dep-graph' },
{ title: 'run-many', path: '/cli/run-many' },
{ title: 'affected', path: '/cli/affected' },
{ title: 'affected:graph', path: '/cli/affected-dep-graph' },
{ title: 'print-affected', path: '/cli/print-affected' },
{ title: 'format:check', path: '/cli/format-check' },
{ title: 'format:write', path: '/cli/format-write' },
{ title: 'migrate', path: '/cli/migrate' },
{ title: 'report', path: '/cli/report' },
{ title: 'list', path: '/cli/list' },
{ title: 'connect', path: '/cli/connect-to-nx-cloud' },
{ title: 'reset', path: '/cli/reset' },
{ title: 'Storybook', path: '/storybook/overview-react' },
{ title: 'Storybook', path: '/storybook/overview-angular' },
{
title: 'Setting up Storybook Composition with Nx',
path: '/storybook/storybook-composition-setup',
},
{
title: '@nx/devkit',
path: '/devkit/index',
},
{
title: '@nx/devkit',
path: '/devkit/ngcli_adapter',
},
];
/**
* Asserting all the additional API references pages are accounted for and accessible.
* Generation of the pages is manual since we want to make sure the change is intended.
*/
test.describe('nx-dev: Additional API references section', () => {
pages.forEach((page) => assertTextOnPage(page.path, page.title));
});
+7
View File
@@ -0,0 +1,7 @@
import { test, expect } from '@playwright/test';
test('should display the primary heading', async ({ page }) => {
await page.goto('/');
const heading = page.locator('[data-cy="primary-heading"]');
await expect(heading).toContainText('Smart MonoreposFast Builds');
});
+21
View File
@@ -0,0 +1,21 @@
import { expect, test } from '@playwright/test';
/**
* Assert a text is present on the visited page.
* @param page
* @param path
* @param title
* @param selector
*/
export function assertTextOnPage(
path: string,
title: string,
selector: string = 'h1'
): void {
test.describe(path, () => {
test(`should display "${title}"`, async ({ page }) => {
await page.goto(path);
const locator = page.locator(selector);
await expect(locator).toContainText(title);
});
});
}
@@ -0,0 +1,57 @@
import { assertTextOnPage } from './helpers';
import { test, expect } from '@playwright/test';
const pages: Array<{ title: string; path: string }> = [
{
title: 'Continuous Integration with Nx',
path: '/ci/intro/ci-with-nx',
},
{
title: 'Recording Non-Nx Commands',
path: '/ci/recipes/other/record-commands',
},
{
title: 'Enable GitHub PR Integration',
path: '/ci/recipes/source-control-integration/github',
},
{
title: 'Connecting Nx Cloud to your existing Google identity provider',
path: '/ci/recipes/security/google-auth',
},
{
title: 'Access Tokens',
path: '/ci/recipes/security/access-tokens',
},
{
title: 'Cache Security',
path: '/ci/concepts/cache-security',
},
{
title: 'Heartbeat and main job completion handling',
path: '/ci/concepts/heartbeat',
},
{
title: 'Enable End to End Encryption',
path: '/ci/recipes/security/encryption',
},
{
title: 'Configuring the Cloud Runner / Nx CLI',
path: '/ci/reference/config',
},
{
title: 'Environment Variables',
path: '/ci/reference/env-vars',
},
{
title: 'Enterprise Release Notes',
path: '/ci/reference/release-notes',
},
];
/**
* Asserting all the additional API references pages are accounted for and accessible.
* Generation of the pages is manual since we want to make sure the change is intended.
*/
test.describe('nx-dev: Nx Cloud section', () => {
pages.forEach((page) => assertTextOnPage(page.path, page.title));
});
+452
View File
@@ -0,0 +1,452 @@
import { assertTextOnPage } from './helpers';
import { test } from '@playwright/test';
const pages: Array<{ title: string; path: string }> = [
{ title: '@nx/angular', path: '/packages/angular' },
{
title: '@nx/angular:add-linting',
path: '/packages/angular/generators/add-linting',
},
{
title: '@nx/angular:application',
path: '/packages/angular/generators/application',
},
{
title: '@nx/angular:component',
path: '/packages/angular/generators/component',
},
{
title: '@nx/angular:component-story',
path: '/packages/angular/generators/component-story',
},
{ title: '@nx/angular:init', path: '/packages/angular/generators/init' },
{
title: '@nx/angular:library',
path: '/packages/angular/generators/library',
},
{
title: '@nx/angular:library-secondary-entry-point',
path: '/packages/angular/generators/library-secondary-entry-point',
},
{
title: '@nx/angular:remote',
path: '/packages/angular/generators/remote',
},
{ title: '@nx/angular:move', path: '/packages/angular/generators/move' },
{
title: '@nx/angular:convert-to-with-mf',
path: '/packages/angular/generators/convert-to-with-mf',
},
{ title: '@nx/angular:host', path: '/packages/angular/generators/host' },
{
title: '@nx/angular:ng-add',
path: '/packages/angular/generators/ng-add',
},
{
title: '@nx/angular:ngrx-root-store',
path: '/packages/angular/generators/ngrx-root-store',
},
{
title: '@nx/angular:ngrx-feature-store',
path: '/packages/angular/generators/ngrx-feature-store',
},
{ title: '@nx/angular:scam', path: '/packages/angular/generators/scam' },
{
title: '@nx/angular:scam-directive',
path: '/packages/angular/generators/scam-directive',
},
{
title: '@nx/angular:scam-pipe',
path: '/packages/angular/generators/scam-pipe',
},
{
title: '@nx/angular:setup-mf',
path: '/packages/angular/generators/setup-mf',
},
{
title: '@nx/angular:stories',
path: '/packages/angular/generators/stories',
},
{
title: '@nx/',
path: '/packages/angular/generators/storybook-configuration',
},
{
title: '@nx/angular:web-worker',
path: '/packages/angular/generators/web-worker',
},
{
title: '@nx/angular:delegate-build',
path: '/packages/angular/executors/delegate-build',
},
{
title: '@nx/angular:ng-packagr-lite',
path: '/packages/angular/executors/ng-packagr-lite',
},
{
title: '@nx/angular:package',
path: '/packages/angular/executors/package',
},
{ title: 'create-nx-plugin', path: '/packages/create-nx-plugin' },
{
title: 'create-nx-workspace',
path: '/packages/create-nx-workspace',
},
{ title: '@nx/cypress', path: '/packages/cypress' },
{ title: '@nx/cypress:init', path: '/packages/cypress/generators/init' },
{
title: '@nx/cypress:cypress',
path: '/packages/cypress/executors/cypress',
},
{ title: '@nx/detox', path: '/packages/detox' },
{ title: '@nx/detox:init', path: '/packages/detox/generators/init' },
{
title: '@nx/detox:application',
path: '/packages/detox/generators/application',
},
{ title: '@nx/detox:build', path: '/packages/detox/executors/build' },
{ title: '@nx/detox:test', path: '/packages/detox/executors/test' },
{ title: '@nx/devkit', path: '/packages/devkit' },
{ title: '@nx/esbuild', path: '/packages/esbuild' },
{
title: '@nx/esbuild:esbuild',
path: '/packages/esbuild/executors/esbuild',
},
{ title: '@nx/eslint-plugin', path: '/packages/eslint-plugin' },
{ title: '@nx/expo', path: '/packages/expo' },
{
title: '@nx/expo:init',
path: '/packages/expo/generators/init',
},
{
title: '@nx/expo:application',
path: '/packages/expo/generators/application',
},
{
title: '@nx/expo:library',
path: '/packages/expo/generators/library',
},
{
title: '@nx/expo:component',
path: '/packages/expo/generators/component',
},
{
title: '@nx/expo:start',
path: '/packages/expo/executors/start',
},
{
title: '@nx/expo:sync-deps',
path: '/packages/expo/executors/sync-deps',
},
{
title: '@nx/expo:ensure-symlink',
path: '/packages/expo/executors/ensure-symlink',
},
{ title: '@nx/express', path: '/packages/express' },
{ title: '@nx/express:init', path: '/packages/express/generators/init' },
{
title: '@nx/express:application',
path: '/packages/express/generators/application',
},
{ title: '@nx/jest', path: '/packages/jest' },
{ title: '@nx/jest:init', path: '/packages/jest/generators/init' },
{
title: '@nx/jest:configuration',
path: '/packages/jest/generators/configuration',
},
{ title: '@nx/jest', path: '/packages/jest/executors/jest' },
{ title: '@nx/js', path: '/packages/js' },
{ title: '@nx/js:library', path: '/packages/js/generators/library' },
{ title: '@nx/js:init', path: '/packages/js/generators/init' },
{
title: '@nx/js:convert-to-swc',
path: '/packages/js/generators/convert-to-swc',
},
{ title: '@nx/js:tsc', path: '/packages/js/executors/tsc' },
{ title: '@nx/js:swc', path: '/packages/js/executors/swc' },
{ title: '@nx/eslint', path: '/packages/eslint' },
{
title: '@nx/eslint:workspace-rules-project',
path: '/packages/eslint/generators/workspace-rules-project',
},
{
title: '@nx/eslint',
path: '/packages/eslint/generators/workspace-rule',
},
{ title: '@nx/eslint', path: '/packages/eslint/executors/lint' },
{ title: '@nx/nest', path: '/packages/nest' },
{
title: '@nx/nest:application',
path: '/packages/nest/generators/application',
},
{ title: '@nx/nest:init', path: '/packages/nest/generators/init' },
{ title: '@nx/nest:library', path: '/packages/nest/generators/library' },
{ title: '@nx/nest:class', path: '/packages/nest/generators/class' },
{
title: '@nx/nest:controller',
path: '/packages/nest/generators/controller',
},
{
title: '@nx/nest:decorator',
path: '/packages/nest/generators/decorator',
},
{ title: '@nx/nest:filter', path: '/packages/nest/generators/filter' },
{ title: '@nx/nest:gateway', path: '/packages/nest/generators/gateway' },
{ title: '@nx/nest:guard', path: '/packages/nest/generators/guard' },
{
title: '@nx/nest:interceptor',
path: '/packages/nest/generators/interceptor',
},
{
title: '@nx/nest:interface',
path: '/packages/nest/generators/interface',
},
{
title: '@nx/nest:middleware',
path: '/packages/nest/generators/middleware',
},
{ title: '@nx/nest:module', path: '/packages/nest/generators/module' },
{ title: '@nx/nest:pipe', path: '/packages/nest/generators/pipe' },
{
title: '@nx/nest:provider',
path: '/packages/nest/generators/provider',
},
{
title: '@nx/nest:resolver',
path: '/packages/nest/generators/resolver',
},
{
title: '@nx/nest:resource',
path: '/packages/nest/generators/resource',
},
{ title: '@nx/nest:service', path: '/packages/nest/generators/service' },
{ title: '@nx/next', path: '/packages/next' },
{ title: '@nx/next:init', path: '/packages/next/generators/init' },
{
title: '@nx/next:application',
path: '/packages/next/generators/application',
},
{ title: '@nx/next:page', path: '/packages/next/generators/page' },
{
title: '@nx/next:component',
path: '/packages/next/generators/component',
},
{ title: '@nx/next:library', path: '/packages/next/generators/library' },
{ title: '@nx/next:build', path: '/packages/next/executors/build' },
{ title: '@nx/next:server', path: '/packages/next/executors/server' },
{ title: '@nx/node', path: '/packages/node' },
{ title: '@nx/node:init', path: '/packages/node/generators/init' },
{
title: '@nx/node:application',
path: '/packages/node/generators/application',
},
{ title: '@nx/node:library', path: '/packages/node/generators/library' },
{ title: 'nx', path: '/packages/nx' },
{ title: 'nx:noop', path: '/packages/nx/executors/noop' },
{
title: 'nx:run-commands',
path: '/packages/nx/executors/run-commands',
},
{ title: 'nx:run-script', path: '/packages/nx/executors/run-script' },
{ title: 'plugin', path: '/packages/plugin' },
{
title: '@nx/plugin:plugin',
path: '/packages/plugin/generators/plugin',
},
{
title: '@nx/plugin:e2e-project',
path: '/packages/plugin/generators/e2e-project',
},
{
title: '@nx/plugin:migration',
path: '/packages/plugin/generators/migration',
},
{
title: '@nx/plugin:generator',
path: '/packages/plugin/generators/generator',
},
{
title: '@nx/plugin:executor',
path: '/packages/plugin/generators/executor',
},
{ title: '@nx/react', path: '/packages/react' },
{ title: '@nx/react:init', path: '/packages/react/generators/init' },
{
title: '@nx/react:application',
path: '/packages/react/generators/application',
},
{
title: '@nx/react:library',
path: '/packages/react/generators/library',
},
{
title: '@nx/react:component',
path: '/packages/react/generators/component',
},
{ title: '@nx/react:redux', path: '/packages/react/generators/redux' },
{
title: '@nx/react:storybook-configuration',
path: '/packages/react/generators/storybook-configuration',
},
{
title: '@nx/react:component-story',
path: '/packages/react/generators/component-story',
},
{
title: '@nx/react:stories',
path: '/packages/react/generators/stories',
},
{ title: '@nx/react:hook', path: '/packages/react/generators/hook' },
{ title: '@nx/react:host', path: '/packages/react/generators/host' },
{ title: '@nx/react:remote', path: '/packages/react/generators/remote' },
{
title: '@nx/react:module-federation-dev-server',
path: '/packages/react/executors/module-federation-dev-server',
},
{ title: '@nx/react-native', path: '/packages/react-native' },
{
title: '@nx/react-native:init',
path: '/packages/react-native/generators/init',
},
{
title: '@nx/react-native:application',
path: '/packages/react-native/generators/application',
},
{
title: '@nx/react-native:library',
path: '/packages/react-native/generators/library',
},
{
title: '@nx/react-native:component',
path: '/packages/react-native/generators/component',
},
{
title: '@nx/',
path: '/packages/react-native/generators/storybook-configuration',
},
{
title: '@nx/react-native:component-story',
path: '/packages/react-native/generators/component-story',
},
{
title: '@nx/react-native:stories',
path: '/packages/react-native/generators/stories',
},
{
title: '@nx/react-native:run-android',
path: '/packages/react-native/executors/run-android',
},
{
title: '@nx/react-native:run-ios',
path: '/packages/react-native/executors/run-ios',
},
{
title: '@nx/react-native:bundle',
path: '/packages/react-native/executors/bundle',
},
{
title: '@nx/react-native:build-android',
path: '/packages/react-native/executors/build-android',
},
{
title: '@nx/react-native:start',
path: '/packages/react-native/executors/start',
},
{
title: '@nx/react-native:sync-deps',
path: '/packages/react-native/executors/sync-deps',
},
{
title: '@nx/react-native:ensure-symlink',
path: '/packages/react-native/executors/ensure-symlink',
},
{
title: '@nx/react-native:storybook',
path: '/packages/react-native/executors/storybook',
},
{ title: '@nx/storybook', path: '/packages/storybook' },
{
title: '@nx/storybook:init',
path: '/packages/storybook/generators/init',
},
{
title: '@nx/storybook:configuration',
path: '/packages/storybook/generators/configuration',
},
{
title: '@nx/storybook:cypress-project',
path: '/packages/storybook/generators/cypress-project',
},
{
title: '@nx/storybook:storybook',
path: '/packages/storybook/executors/storybook',
},
{
title: '@nx/storybook:build',
path: '/packages/storybook/executors/build',
},
{ title: '@nx/web', path: '/packages/web' },
{ title: '@nx/web:init', path: '/packages/web/generators/init' },
{
title: '@nx/web:application',
path: '/packages/web/generators/application',
},
{
title: '@nx/webpack:webpack',
path: '/packages/webpack/executors/webpack',
},
{ title: '@nx/rollup:rollup', path: '/packages/rollup/executors/rollup' },
{
title: '@nx/webpack:dev-server',
path: '/packages/webpack/executors/dev-server',
},
{
title: '@nx/web:file-server',
path: '/packages/web/executors/file-server',
},
{
title: '@nx/workspace:preset',
path: '/packages/workspace/generators/preset',
},
{
title: '@nx/workspace:move',
path: '/packages/workspace/generators/move',
},
{
title: '@nx/workspace:remove',
path: '/packages/workspace/generators/remove',
},
{
title: '@nx/workspace:new',
path: '/packages/workspace/generators/new',
},
{
title: '@nx/workspace:run-command',
path: '/packages/workspace/generators/run-commands',
},
{
title: '@nx/workspace:fix-configuration',
path: '/packages/workspace/generators/fix-configuration',
},
{
title: '@nx/workspace:npm-package',
path: '/packages/workspace/generators/npm-package',
},
{
title: '@nx/workspace:ci-workflow',
path: '/packages/workspace/generators/ci-workflow',
},
{
title: '@nx/workspace:counter',
path: '/packages/workspace/executors/counter',
},
];
/**
* Asserting all the packages pages are accounted for and accessible.
* Generation of the pages is manual since we want to make sure the change is intended.
*/
test.describe('nx-dev: Packages Section', () => {
pages.forEach((page) => assertTextOnPage(page.path, page.title));
});
+16
View File
@@ -0,0 +1,16 @@
import { test, expect } from '@playwright/test';
test.describe('nx-dev: Recipes pages', () => {
test('should list related recipes based on tags', async ({ page }) => {
await page.goto('/recipes/storybook/overview-react');
const relatedDocs = page.locator('[data-document="related"] li');
const relatedDocsText = await relatedDocs.allInnerTexts();
expect(relatedDocsText.length, 'has related docs').toBeGreaterThan(0);
// All text content has to be different
const distinct = new Set(relatedDocsText);
expect(distinct.size, 'all strings are different').toBe(
relatedDocsText.length
);
});
});
+3
View File
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.base.json"
}