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
+3
View File
@@ -0,0 +1,3 @@
import { baseConfig, e2eTestOnlyIgnores } from '../../eslint.config.mjs';
export default [...baseConfig, e2eTestOnlyIgnores];
+13
View File
@@ -0,0 +1,13 @@
/* eslint-disable */
module.exports = {
transform: {
'^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
maxWorkers: 1,
globals: {},
globalSetup: '../utils/global-setup.ts',
globalTeardown: '../utils/global-teardown.ts',
displayName: 'e2e-workspace-create',
preset: '../jest.preset.e2e.js',
};
+8
View File
@@ -0,0 +1,8 @@
{
"name": "@nx/e2e-workspace-create",
"version": "0.0.1",
"private": true,
"dependencies": {
"@nx/e2e-utils": "workspace:*"
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"name": "e2e-workspace-create",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "e2e/workspace-create",
"projectType": "application",
"implicitDependencies": ["create-nx-workspace"],
"// targets": "to see all targets run: nx show project e2e-workspace-create --web",
"targets": {}
}
@@ -0,0 +1,75 @@
import {
checkFilesExist,
cleanupProject,
getSelectedPackageManager,
packageManagerLockFile,
runCLI,
runCreatePlugin,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-plugin', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should be able to create a plugin repo build a plugin', () => {
const pluginName = uniq('plugin');
const generatorName = uniq('generator');
const executorName = uniq('executor');
runCreatePlugin(pluginName, {
packageManager,
extraArgs: `--createPackageName=false`,
});
checkFilesExist(
'package.json',
packageManagerLockFile[packageManager],
`project.json`
);
runCLI(`build ${pluginName}`);
checkFilesExist(
`dist/${pluginName}/package.json`,
`dist/${pluginName}/src/index.js`
);
runCLI(
`generate @nx/plugin:generator ${pluginName}/src/generators/${generatorName} --name ${generatorName}`
);
runCLI(
`generate @nx/plugin:executor ${pluginName}/src/executors/${executorName} --name ${executorName}`
);
runCLI(`build ${pluginName}`);
checkFilesExist(
`dist/${pluginName}/package.json`,
`dist/${pluginName}/generators.json`,
`dist/${pluginName}/executors.json`
);
});
it('should be able to create a repo with create workspace cli', () => {
const pluginName = uniq('plugin');
runCreatePlugin(pluginName, {
packageManager,
extraArgs: `--createPackageName=create-${pluginName}-package`,
});
runCLI(`build ${pluginName}`);
checkFilesExist(
`dist/packages/${pluginName}/package.json`,
`dist/packages/${pluginName}/generators.json`,
`packages/${pluginName}-e2e/src/${pluginName}.spec.ts`
);
runCLI(`build create-${pluginName}-package`);
checkFilesExist(`dist/packages/create-${pluginName}-package/bin/index.js`);
expect(() => runCLI(`e2e ${pluginName}-e2e`)).not.toThrow();
});
});
@@ -0,0 +1,104 @@
import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
expectCodeIsFormatted,
getSelectedPackageManager,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=angular', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should create a workspace with a single angular app at the root without routing', () => {
const wsName = uniq('angular');
runCreateWorkspace(wsName, {
preset: 'angular-standalone',
appName: wsName,
style: 'css',
packageManager,
standaloneApi: false,
routing: false,
unitTestRunner: 'jest',
e2eTestRunner: 'none',
bundler: 'webpack',
ssr: false,
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('src/app/app-module.ts');
checkFilesDoNotExist('src/app/app.routes.ts');
expectCodeIsFormatted();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should create a workspace with a single angular app at the root using standalone APIs', () => {
const wsName = uniq('angular');
runCreateWorkspace(wsName, {
preset: 'angular-standalone',
appName: wsName,
style: 'css',
packageManager,
standaloneApi: true,
routing: true,
unitTestRunner: 'jest',
e2eTestRunner: 'none',
bundler: 'webpack',
ssr: false,
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('src/app/app.routes.ts');
checkFilesDoNotExist('src/app/app-module.ts');
expectCodeIsFormatted();
});
it('should be able to create an angular workspace', () => {
const wsName = uniq('angular');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'angular-monorepo',
style: 'css',
appName,
packageManager,
standaloneApi: false,
routing: true,
unitTestRunner: 'jest',
e2eTestRunner: 'none',
bundler: 'webpack',
ssr: false,
});
expectCodeIsFormatted();
});
it('should fail correctly when preset errors', () => {
// Using Angular Preset as the example here to test
// It will error when prefix is not valid
const wsName = uniq('angular-1-test');
const appName = uniq('app');
expect(() =>
runCreateWorkspace(wsName, {
preset: 'angular-monorepo',
style: 'css',
appName,
packageManager,
standaloneApi: false,
routing: false,
e2eTestRunner: 'none',
bundler: 'webpack',
ssr: false,
prefix: '1-one',
})
).toThrow();
});
});
@@ -0,0 +1,36 @@
import {
cleanupProject,
readJson,
runCLI,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --template', () => {
afterEach(() => cleanupProject());
const templates = [
'nrwl/empty-template',
'nrwl/typescript-template',
] as const;
describe.each(['npm', 'pnpm'] as const)('with %s', (packageManager) => {
it.each(templates)(
'should clone %s and run lint,test,build',
(template) => {
const wsName = uniq('template');
runCreateWorkspace(wsName, {
template,
packageManager,
});
expect(() => runCLI('run-many -t lint,test,build')).not.toThrow();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
},
600_000
);
});
});
@@ -0,0 +1,86 @@
import {
e2eCwd,
getPackageManagerCommand,
getSelectedPackageManager,
getStrippedEnvironmentVariables,
uniq,
} from '@nx/e2e-utils';
import { execSync } from 'child_process';
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs-extra';
describe('create-nx-workspace current directory', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
// create-nx-workspace . scaffolds into the current directory in place rather
// than into a new subfolder. Run non-interactively (CI), like an AI agent.
function createInCurrentDir(dir: string): string {
const pmc = getPackageManagerCommand({ packageManager });
return execSync(
`${pmc.createWorkspace} . --template=empty --no-interactive --package-manager=${packageManager}`,
{
cwd: dir,
stdio: 'pipe',
env: { CI: 'true', ...getStrippedEnvironmentVariables() },
encoding: 'utf-8',
}
);
}
it('scaffolds in place when the current directory is empty', () => {
const dir = `${e2eCwd}/${uniq('cwd-empty')}`;
mkdirSync(dir, { recursive: true });
try {
createInCurrentDir(dir);
expect(existsSync(`${dir}/nx.json`)).toBeTruthy();
expect(existsSync(`${dir}/package.json`)).toBeTruthy();
} finally {
rmSync(dir, { recursive: true, force: true });
}
}, 120000);
it('scaffolds in place in an existing git repo and preserves it', () => {
// Mirror a freshly created GitHub repo: a real git repo with a remote +
// README + LICENSE.
const dir = `${e2eCwd}/${uniq('cwd-gitrepo')}`;
mkdirSync(dir, { recursive: true });
execSync('git init', { cwd: dir, stdio: 'pipe' });
execSync('git remote add origin https://example.com/my-repo.git', {
cwd: dir,
stdio: 'pipe',
});
writeFileSync(`${dir}/.gitignore`, 'node_modules\n');
writeFileSync(`${dir}/README.md`, '# preexisting\n');
writeFileSync(`${dir}/LICENSE`, 'MIT\n');
try {
createInCurrentDir(dir);
expect(existsSync(`${dir}/nx.json`)).toBeTruthy();
expect(existsSync(`${dir}/package.json`)).toBeTruthy();
// The user's existing git repo (and its remote) must survive - CNW
// detects the repo and skips git initialization.
const remote = execSync('git remote get-url origin', {
cwd: dir,
encoding: 'utf-8',
}).trim();
expect(remote).toBe('https://example.com/my-repo.git');
} finally {
rmSync(dir, { recursive: true, force: true });
}
}, 120000);
it('scaffolds in place without deleting unrelated pre-existing files', () => {
const dir = `${e2eCwd}/${uniq('cwd-nonempty')}`;
mkdirSync(dir, { recursive: true });
writeFileSync(`${dir}/keep-me.txt`, 'keep\n');
try {
createInCurrentDir(dir);
expect(existsSync(`${dir}/nx.json`)).toBeTruthy();
// Files not part of the template are left untouched.
expect(existsSync(`${dir}/keep-me.txt`)).toBeTruthy();
} finally {
rmSync(dir, { recursive: true, force: true });
}
}, 120000);
});
@@ -0,0 +1,76 @@
import {
checkFilesExist,
cleanupProject,
expectCodeIsFormatted,
expectNoAngularDevkit,
getSelectedPackageManager,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=next', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should be able to create an next workspace', () => {
const wsName = uniq('next');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'next',
style: 'css',
appName,
nextAppDir: false,
nextSrcDir: true,
packageManager,
e2eTestRunner: 'none',
});
checkFilesExist(`apps/${appName}/src/pages/index.tsx`);
expectNoAngularDevkit();
expectCodeIsFormatted();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should be able to create a nextjs standalone workspace using app router', () => {
const wsName = uniq('next');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'nextjs-standalone',
style: 'css',
nextAppDir: true,
nextSrcDir: true,
appName,
packageManager,
e2eTestRunner: 'none',
});
checkFilesExist('src/app/page.tsx');
expectNoAngularDevkit();
expectCodeIsFormatted();
});
it('should be able to create a nextjs standalone workspace using pages router', () => {
const wsName = uniq('next');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'nextjs-standalone',
style: 'css',
nextAppDir: false,
nextSrcDir: true,
appName,
packageManager,
e2eTestRunner: 'none',
});
checkFilesExist('src/pages/index.tsx');
expectNoAngularDevkit();
expectCodeIsFormatted();
});
});
@@ -0,0 +1,50 @@
import {
checkFilesExist,
cleanupProject,
expectCodeIsFormatted,
getSelectedPackageManager,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=nuxt', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should create a workspace with a single nuxt app at the root', () => {
const wsName = uniq('nuxt');
runCreateWorkspace(wsName, {
preset: 'nuxt-standalone',
appName: wsName,
style: 'css',
packageManager,
e2eTestRunner: 'none',
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('nuxt.config.ts');
checkFilesExist('app/app.vue');
checkFilesExist('app/pages/index.vue');
expectCodeIsFormatted();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should be able to create a nuxt monorepo', () => {
const wsName = uniq('nuxt');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'nuxt',
appName,
style: 'css',
packageManager,
e2eTestRunner: 'none',
});
expectCodeIsFormatted();
});
});
@@ -0,0 +1,50 @@
import {
checkFilesExist,
cleanupProject,
expectCodeIsFormatted,
getSelectedPackageManager,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=vue', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should create a workspace with a single vue app at the root', () => {
const wsName = uniq('vue');
runCreateWorkspace(wsName, {
preset: 'vue-standalone',
appName: wsName,
style: 'css',
packageManager,
e2eTestRunner: 'none',
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('index.html');
checkFilesExist('src/main.ts');
checkFilesExist('src/app/App.vue');
expectCodeIsFormatted();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should be able to create a vue monorepo', () => {
const wsName = uniq('vue');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'vue-monorepo',
appName,
style: 'css',
packageManager,
e2eTestRunner: 'none',
});
expectCodeIsFormatted();
});
});
@@ -0,0 +1,266 @@
import {
checkFilesExist,
cleanupProject,
getSelectedPackageManager,
packageInstall,
readJson,
runCLI,
runCommand,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=npm', () => {
const wsName = uniq('npm');
let orginalGlobCache;
beforeAll(() => {
orginalGlobCache = process.env.NX_PROJECT_GLOB_CACHE;
// glob cache is causing previous projects to show in Workspace for maxWorkers overrides
// which fails due to files no longer being available
process.env.NX_PROJECT_GLOB_CACHE = 'false';
runCreateWorkspace(wsName, {
preset: 'npm',
packageManager: getSelectedPackageManager(),
});
});
afterEach(() => {
// cleanup previous projects
runCommand(`rm -rf packages/** tsconfig.base.json tsconfig.json`);
});
afterAll(() => {
process.env.NX_PROJECT_GLOB_CACHE = orginalGlobCache;
cleanupProject({ skipReset: true });
});
it('should setup package-based workspace', () => {
const packageJson = readJson('package.json');
expect(packageJson.dependencies).toEqual({});
if (getSelectedPackageManager() === 'pnpm') {
checkFilesExist('pnpm-workspace.yaml');
} else {
expect(packageJson.workspaces).toEqual(['packages/*']);
}
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should add angular application', () => {
packageInstall('@nx/angular', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/angular:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
}, 1_000_000);
it('should add angular library', () => {
packageInstall('@nx/angular', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(`generate @nx/angular:lib packages/${libName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
const tsconfig = readJson(`tsconfig.base.json`);
expect(tsconfig.compilerOptions.paths).toEqual({
[`@${wsName}/${libName}`]: [`./packages/${libName}/src/index.ts`],
});
}, 1_000_000);
it('should add js library', () => {
packageInstall('@nx/js', wsName);
const libName = uniq('lib');
expect(() =>
runCLI(`generate @nx/js:library packages/${libName} --no-interactive`)
).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add web application', () => {
packageInstall('@nx/web', wsName);
const appName = uniq('my-app');
expect(() =>
runCLI(`generate @nx/web:app packages/${appName} --no-interactive`)
).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add react application', () => {
packageInstall('@nx/react', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/react:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add react library', () => {
packageInstall('@nx/react', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(`generate @nx/react:lib packages/${libName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add next application', () => {
packageInstall('@nx/next', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/next:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add next library', () => {
packageInstall('@nx/next', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(`generate @nx/next:lib packages/${libName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add react-native application', () => {
packageInstall('@nx/react-native', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(
`generate @nx/react-native:app packages/${appName} --install=false --no-interactive`
);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add react-native library', () => {
packageInstall('@nx/react-native', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(
`generate @nx/react-native:lib packages/${libName} --no-interactive`
);
}).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add node application', () => {
packageInstall('@nx/node', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/node:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add node library', () => {
packageInstall('@nx/node', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(`generate @nx/node:lib packages/${libName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add nest application', () => {
packageInstall('@nx/nest', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/nest:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
it('should add nest library', () => {
packageInstall('@nx/nest', wsName);
const libName = uniq('lib');
expect(() => {
runCLI(`generate @nx/nest:lib packages/${libName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json', 'tsconfig.json');
const tsconfigBase = readJson(`tsconfig.base.json`);
expect(tsconfigBase.compilerOptions.paths).toBeUndefined();
const tsconfig = readJson(`tsconfig.json`);
expect(tsconfig.extends).toBe('./tsconfig.base.json');
expect(tsconfig.references).toStrictEqual([
{ path: `./packages/${libName}` },
]);
});
it('should add express application', () => {
packageInstall('@nx/express', wsName);
const appName = uniq('my-app');
expect(() => {
runCLI(`generate @nx/express:app packages/${appName} --no-interactive`);
}).not.toThrow();
checkFilesExist('tsconfig.base.json');
});
});
@@ -0,0 +1,60 @@
import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
expectNoAngularDevkit,
expectCodeIsFormatted,
getSelectedPackageManager,
packageManagerLockFile,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=other - Basic Presets', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should reject workspace names starting with numbers', () => {
expect(() => {
runCreateWorkspace('4invalidname', {
preset: 'apps',
packageManager,
});
}).toThrow();
});
it('should be able to create an empty workspace built for apps', () => {
const wsName = uniq('apps');
runCreateWorkspace(wsName, {
preset: 'apps',
packageManager,
});
checkFilesExist('package.json', packageManagerLockFile[packageManager]);
expectNoAngularDevkit();
});
it('should be able to create an empty workspace with npm capabilities', () => {
const wsName = uniq('npm');
runCreateWorkspace(wsName, {
preset: 'npm',
packageManager,
});
expectNoAngularDevkit();
checkFilesDoNotExist('tsconfig.base.json');
});
it('should be able to create an empty workspace with ts/js capabilities', () => {
const wsName = uniq('ts');
runCreateWorkspace(wsName, {
preset: 'ts',
packageManager,
});
expectNoAngularDevkit();
expectCodeIsFormatted();
});
});
@@ -0,0 +1,82 @@
import {
cleanupProject,
expectNoAngularDevkit,
expectCodeIsFormatted,
getSelectedPackageManager,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=other - Framework Presets', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should be able to create an web-components workspace', () => {
const wsName = uniq('web-components');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'web-components',
style: 'css',
appName,
packageManager,
});
expectNoAngularDevkit();
expectCodeIsFormatted();
});
it('should be able to create an express workspace', () => {
const wsName = uniq('express');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'express',
docker: false,
appName,
packageManager,
});
expectNoAngularDevkit();
expectCodeIsFormatted();
});
it('should be able to create react-native workspace', () => {
const wsName = uniq('react-native');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'react-native',
appName,
packageManager: 'npm',
e2eTestRunner: 'none',
});
expectNoAngularDevkit();
expectCodeIsFormatted();
});
it('should be able to create an expo workspace', () => {
const wsName = uniq('expo');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'expo',
appName,
packageManager: 'npm',
e2eTestRunner: 'none',
});
expectNoAngularDevkit();
expectCodeIsFormatted();
});
it('should be able to create a nest workspace', () => {
const wsName = uniq('nest');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'nest',
docker: false,
appName,
packageManager,
});
expectCodeIsFormatted();
});
});
@@ -0,0 +1,31 @@
import {
cleanupProject,
getSelectedPackageManager,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=other - Git Configuration', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should be able to create a workspace with a custom base branch and HEAD', () => {
const wsName = uniq('branch');
runCreateWorkspace(wsName, {
preset: 'apps',
base: 'main',
packageManager,
});
});
it('should be able to create a workspace with custom commit information', () => {
const wsName = uniq('branch');
runCreateWorkspace(wsName, {
preset: 'apps',
extraArgs:
'--commit.name="John Doe" --commit.email="myemail@test.com" --commit.message="Custom commit message!"',
packageManager,
});
});
});
@@ -0,0 +1,178 @@
import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
e2eCwd,
getSelectedPackageManager,
packageManagerLockFile,
readJson,
runCommand,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
import { readFileSync } from 'fs';
import { existsSync, mkdirSync, rmSync } from 'fs-extra';
describe('create-nx-workspace package managers', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should respect package manager preference', () => {
const wsName = uniq('pm');
process.env.YARN_REGISTRY = `http://localhost:4872`;
process.env.SELECTED_PM = 'npm';
runCreateWorkspace(wsName, {
preset: 'apps',
packageManager: 'npm',
});
checkFilesDoNotExist('yarn.lock');
checkFilesExist('package-lock.json');
process.env.SELECTED_PM = packageManager;
});
describe('Use detected package manager', () => {
function setupProject(envPm: 'npm' | 'yarn' | 'pnpm' | 'bun') {
process.env.SELECTED_PM = envPm;
runCreateWorkspace(uniq('pm'), {
preset: 'apps',
packageManager: envPm,
useDetectedPm: true,
});
}
if (packageManager === 'npm') {
it('should use npm when invoked with npx', () => {
setupProject('npm');
checkFilesExist(packageManagerLockFile['npm']);
checkFilesDoNotExist(
packageManagerLockFile['yarn'],
packageManagerLockFile['pnpm'],
packageManagerLockFile['bun']
);
process.env.SELECTED_PM = packageManager;
}, 90000);
}
if (packageManager === 'pnpm') {
it('should use pnpm when invoked with pnpx', () => {
setupProject('pnpm');
checkFilesExist(packageManagerLockFile['pnpm']);
checkFilesDoNotExist(
packageManagerLockFile['yarn'],
packageManagerLockFile['npm'],
packageManagerLockFile['bun']
);
process.env.SELECTED_PM = packageManager;
}, 90000);
}
if (packageManager === 'bun') {
it('should use bun when invoked with bunx', () => {
setupProject('bun');
checkFilesExist(packageManagerLockFile['bun']);
checkFilesDoNotExist(
packageManagerLockFile['yarn'],
packageManagerLockFile['npm'],
packageManagerLockFile['pnpm']
);
process.env.SELECTED_PM = packageManager;
}, 90000);
}
// skipping due to packageManagerCommand for createWorkspace not using yarn create nx-workspace
if (packageManager === 'yarn') {
xit('should use yarn when invoked with yarn create', () => {
setupProject('yarn');
checkFilesExist(packageManagerLockFile['yarn']);
checkFilesDoNotExist(
packageManagerLockFile['pnpm'],
packageManagerLockFile['npm'],
packageManagerLockFile['bun']
);
process.env.SELECTED_PM = packageManager;
}, 90000);
}
});
});
describe('create-nx-workspace parent folder', () => {
const tmpDir = `${e2eCwd}/${uniq('with space')}`;
const wsName = uniq('parent');
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` }));
it('should handle spaces in workspace path', () => {
mkdirSync(tmpDir, { recursive: true });
runCreateWorkspace(wsName, {
preset: 'apps',
packageManager,
cwd: tmpDir,
});
expect(existsSync(`${tmpDir}/${wsName}/package.json`)).toBeTruthy();
});
});
describe('create-nx-workspace yarn berry', () => {
const tmpDir = `${e2eCwd}/${uniq('yarn-berry')}`;
let wsName: string;
let yarnVersion: string;
beforeAll(() => {
mkdirSync(tmpDir, { recursive: true });
runCommand('corepack prepare yarn@3.6.1 --activate', { cwd: tmpDir });
runCommand('yarn set version 3.6.1', { cwd: tmpDir });
yarnVersion = runCommand('yarn --version', { cwd: tmpDir }).trim();
// previous command creates a package.json file which we don't want
rmSync(`${tmpDir}/package.json`);
process.env.YARN_ENABLE_IMMUTABLE_INSTALLS = 'false';
});
afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` }));
it('should create a workspace with yarn berry', () => {
wsName = uniq('apps');
runCreateWorkspace(wsName, {
preset: 'apps',
packageManager: 'yarn',
cwd: tmpDir,
});
expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy();
expect(
readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' })
).toMatchInlineSnapshot(`
"nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-${yarnVersion}.cjs
"
`);
});
it('should create a js workspace with yarn berry', () => {
wsName = uniq('ts');
runCreateWorkspace(wsName, {
preset: 'ts',
packageManager: 'yarn',
cwd: tmpDir,
});
expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy();
expect(
readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' })
).toMatchInlineSnapshot(`
"nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-${yarnVersion}.cjs
"
`);
});
});
@@ -0,0 +1,33 @@
import {
cleanupProject,
runCLI,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --template', () => {
afterEach(() => cleanupProject());
const templates = ['nrwl/react-template'] as const;
describe.each(['npm', 'pnpm'] as const)('with %s', (packageManager) => {
it.each(templates)(
'should clone %s and run lint,test,build',
(template) => {
const wsName = uniq('template');
runCreateWorkspace(wsName, {
template,
packageManager,
});
expect(() => runCLI('run-many -t lint,test,build')).not.toThrow();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
},
600_000
);
});
});
@@ -0,0 +1,114 @@
import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
expectCodeIsFormatted,
expectNoAngularDevkit,
expectNoTsJestInJestConfig,
getSelectedPackageManager,
readJson,
runCreateWorkspace,
uniq,
} from '@nx/e2e-utils';
describe('create-nx-workspace --preset=react', () => {
const packageManager = getSelectedPackageManager() || 'pnpm';
afterEach(() => cleanupProject());
it('should create a workspace with a single react app with vite at the root', () => {
const wsName = uniq('react');
runCreateWorkspace(wsName, {
preset: 'react-standalone',
appName: wsName,
style: 'css',
packageManager,
bundler: 'vite',
e2eTestRunner: 'none',
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('vite.config.mts');
checkFilesDoNotExist('tsconfig.base.json');
expectCodeIsFormatted();
const nxJson = readJson(`nx.json`);
expect(nxJson.nxCloudId).toBeUndefined();
});
it('should create a workspace with a single react app with webpack and playwright at the root', () => {
const wsName = uniq('react');
runCreateWorkspace(wsName, {
preset: 'react-standalone',
appName: wsName,
style: 'css',
packageManager,
bundler: 'webpack',
e2eTestRunner: 'playwright',
});
checkFilesExist('package.json');
checkFilesExist('project.json');
checkFilesExist('webpack.config.js');
checkFilesDoNotExist('tsconfig.base.json');
expectCodeIsFormatted();
});
it('should be able to create a react workspace with webpack', () => {
const wsName = uniq('react');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'react-monorepo',
style: 'css',
appName,
packageManager,
bundler: 'webpack',
e2eTestRunner: 'none',
});
expectNoAngularDevkit();
expectNoTsJestInJestConfig(appName);
const packageJson = readJson('package.json');
expect(packageJson.devDependencies['@nx/webpack']).toBeDefined();
expectCodeIsFormatted();
});
it('should be able to create a react workspace with vite', () => {
const wsName = uniq('react');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'react-monorepo',
style: 'css',
appName,
packageManager,
bundler: 'vite',
e2eTestRunner: 'none',
});
expectNoAngularDevkit();
const packageJson = readJson('package.json');
expect(packageJson.devDependencies['@nx/webpack']).not.toBeDefined();
expect(packageJson.devDependencies['@nx/vite']).toBeDefined();
expectCodeIsFormatted();
});
it('should be able to create a react workspace without options and --no-interactive', () => {
const wsName = uniq('react');
runCreateWorkspace(wsName, {
preset: 'react-monorepo',
});
expectNoAngularDevkit();
checkFilesExist('vitest.workspace.ts');
checkFilesDoNotExist('jest.config.cts');
const packageJson = readJson('package.json');
expect(packageJson.devDependencies['@nx/vite']).toBeDefined(); // vite should be default bundler
expectCodeIsFormatted();
});
});
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": [],
"files": [],
"references": [
{
"path": "../utils"
},
{
"path": "./tsconfig.spec.json"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "out-tsc/spec",
"types": ["jest", "node"]
},
"exclude": ["out-tsc"],
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"**/*.d.ts",
"jest.config.ts"
]
}