Skip to content

Commit

Permalink
feat(testing): add create-nodes plugin for playwright e2e targets (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder authored Dec 20, 2023
1 parent 3981c90 commit 2374d8e
Show file tree
Hide file tree
Showing 26 changed files with 957 additions and 22 deletions.
1 change: 1 addition & 0 deletions docs/generated/devkit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ It only uses language primitives and immutable objects
- [StringChange](../../devkit/documents/StringChange)
- [TargetDefaults](../../devkit/documents/TargetDefaults)
- [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor)
- [ToJSOptions](../../devkit/documents/ToJSOptions)
- [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration)

### Variables
Expand Down
11 changes: 11 additions & 0 deletions docs/generated/devkit/ToJSOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Type alias: ToJSOptions

Ƭ **ToJSOptions**: `Object`

#### Type declaration

| Name | Type |
| :---------- | :------------------------------ |
| `extension` | `".js"` \| `".mjs"` \| `".cjs"` |
| `module?` | `ModuleKind` |
| `target?` | `ScriptTarget` |
9 changes: 5 additions & 4 deletions docs/generated/devkit/toJS.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Function: toJS

**toJS**(`tree`): `void`
**toJS**(`tree`, `options?`): `void`

Rename and transpile any new typescript files created to javascript files

#### Parameters

| Name | Type |
| :----- | :------------------------------------ |
| `tree` | [`Tree`](../../devkit/documents/Tree) |
| Name | Type |
| :--------- | :-------------------------------------------------- |
| `tree` | [`Tree`](../../devkit/documents/Tree) |
| `options?` | [`ToJSOptions`](../../devkit/documents/ToJSOptions) |

#### Returns

Expand Down
1 change: 1 addition & 0 deletions docs/generated/packages/devkit/documents/nx_devkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ It only uses language primitives and immutable objects
- [StringChange](../../devkit/documents/StringChange)
- [TargetDefaults](../../devkit/documents/TargetDefaults)
- [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor)
- [ToJSOptions](../../devkit/documents/ToJSOptions)
- [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration)

### Variables
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "playwright",
"implementation": "/packages/playwright/src/executors/playwright/playwright.ts",
"implementation": "/packages/playwright/src/executors/playwright/playwright.impl.ts",
"schema": {
"$schema": "http://json-schema.org/schema",
"version": 2,
Expand Down
95 changes: 95 additions & 0 deletions e2e/playwright/src/playwright.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ensurePlaywrightBrowsersInstallation,
getPackageManagerCommand,
getSelectedPackageManager,
readJson,
} from '@nx/e2e/utils';

const TEN_MINS_MS = 600_000;
Expand Down Expand Up @@ -67,3 +68,97 @@ describe('Playwright E2E Test runner', () => {
TEN_MINS_MS
);
});

describe('Playwright E2E Test Runner - PCV3', () => {
let env: string | undefined;

beforeAll(() => {
env = process.env.NX_PCV3;
newProject({
name: uniq('playwright'),
unsetProjectNameAndRootFormat: false,
});
process.env.NX_PCV3 = 'true';
});

afterAll(() => {
if (env) {
process.env.NX_PCV3 = env;
} else {
delete process.env.NX_PCV3;
}
});

it(
'should test and lint example app',

() => {
ensurePlaywrightBrowsersInstallation();

const pmc = getPackageManagerCommand();

runCLI(
`g @nx/web:app demo-e2e --directory apps/demo-e2e --unitTestRunner=none --bundler=vite --e2eTestRunner=none --style=css --no-interactive --projectNameAndRootFormat=as-provided`
);
runCLI(
`g @nx/playwright:configuration --project demo-e2e --webServerCommand="${pmc.runNx} serve demo-e2e" --webServerAddress="http://localhost:4200"`
);

const e2eResults = runCLI(`e2e demo-e2e`);
expect(e2eResults).toContain('Successfully ran target e2e for project');

const { targets } = readJson('apps/demo-e2e/project.json');
expect(targets?.e2e).not.toBeDefined();

const { plugins } = readJson('nx.json');
const playwrightPlugin = plugins?.find(
(p) => p.plugin === '@nx/playwright/plugin'
);
expect(playwrightPlugin).toMatchInlineSnapshot(`
{
"options": {
"targetName": "e2e",
},
"plugin": "@nx/playwright/plugin",
}
`);
},
TEN_MINS_MS
);

it(
'should test and lint example app with js',
() => {
ensurePlaywrightBrowsersInstallation();

const pmc = getPackageManagerCommand();

runCLI(
`g @nx/web:app demo-js-e2e --directory apps/demo-js-e2e --unitTestRunner=none --bundler=vite --e2eTestRunner=none --style=css --no-interactive --projectNameAndRootFormat=as-provided`
);
runCLI(
`g @nx/playwright:configuration --project demo-js-e2e --js --webServerCommand="${pmc.runNx} serve demo-e2e" --webServerAddress="http://localhost:4200"`
);

const e2eResults = runCLI(`e2e demo-js-e2e`);
expect(e2eResults).toContain('Successfully ran target e2e for project');

const { targets } = readJson('apps/demo-js-e2e/project.json');
expect(targets?.e2e).not.toBeDefined();

const { plugins } = readJson('nx.json');
const playwrightPlugin = plugins?.find(
(p) => p.plugin === '@nx/playwright/plugin'
);
expect(playwrightPlugin).toMatchInlineSnapshot(`
{
"options": {
"targetName": "e2e",
},
"plugin": "@nx/playwright/plugin",
}
`);
},
TEN_MINS_MS
);
});
4 changes: 3 additions & 1 deletion e2e/utils/get-env-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ export function getStrippedEnvironmentVariables() {
return true;
}

if (key.startsWith('NX_')) {
const allowedKeys = ['NX_PCV3'];

if (key.startsWith('NX_') && !allowedKeys.includes(key)) {
return false;
}

Expand Down
10 changes: 9 additions & 1 deletion packages/cypress/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,19 @@ function getInputs(
/**
* Load the module after ensuring that the require cache is cleared.
*/
const packageInstallationDirectories = ['node_modules', '.yarn'];

function load(path: string): any {
// Clear cache if the path is in the cache
if (require.cache[path]) {
for (const k of Object.keys(require.cache)) {
delete require.cache[k];
// We don't want to clear the require cache of installed packages.
// Clearing them can cause some issues when running Nx without the daemon
// and may cause issues for other packages that use the module state
// in some to store cached information.
if (!packageInstallationDirectories.some((dir) => k.includes(dir))) {
delete require.cache[k];
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export { generateFiles } from './src/generators/generate-files';
/**
* @category Generators
*/
export { toJS } from './src/generators/to-js';
export { toJS, ToJSOptions } from './src/generators/to-js';

/**
* @category Generators
Expand Down
21 changes: 16 additions & 5 deletions packages/devkit/src/generators/to-js.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import type { Tree } from 'nx/src/generators/tree';
import type { ScriptTarget, ModuleKind } from 'typescript';
import { typescriptVersion } from '../utils/versions';
import { ensurePackage } from '../utils/package-json';

export type ToJSOptions = {
target?: ScriptTarget;
module?: ModuleKind;
extension: '.js' | '.mjs' | '.cjs';
};

/**
* Rename and transpile any new typescript files created to javascript files
*/
export function toJS(tree: Tree): void {
const { JsxEmit, ScriptTarget, transpile } = ensurePackage(
export function toJS(tree: Tree, options?: ToJSOptions): void {
const { JsxEmit, ScriptTarget, transpile, ModuleKind } = ensurePackage(
'typescript',
typescriptVersion
);
) as typeof import('typescript');

for (const c of tree.listChanges()) {
if (
Expand All @@ -21,10 +28,14 @@ export function toJS(tree: Tree): void {
transpile(c.content.toString('utf-8'), {
allowJs: true,
jsx: JsxEmit.Preserve,
target: ScriptTarget.ESNext,
target: options?.target ?? ScriptTarget.ESNext,
module: options?.module ?? ModuleKind.ESNext,
})
);
tree.rename(c.path, c.path.replace(/\.tsx?$/, '.js'));
tree.rename(
c.path,
c.path.replace(/\.tsx?$/, options?.extension ?? '.js')
);
}
}
}
1 change: 1 addition & 0 deletions packages/nx/src/native/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,5 @@ export class WorkspaceContext {
incrementalUpdate(updatedFiles: Array<string>, deletedFiles: Array<string>): Record<string, string>
updateProjectFiles(projectRootMappings: ProjectRootMappings, projectFiles: ExternalObject<ProjectFiles>, globalFiles: ExternalObject<Array<FileData>>, updatedFiles: Record<string, string>, deletedFiles: Array<string>): UpdatedWorkspaceFiles
allFileData(): Array<FileData>
getFilesInDirectory(directory: string): Array<string>
}
49 changes: 48 additions & 1 deletion packages/nx/src/native/utils/path.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::native::utils::normalize_trait::Normalize;
use crate::native::{utils::normalize_trait::Normalize, types::FileData};
use std::path::{Path, PathBuf};

impl Normalize for Path {
Expand Down Expand Up @@ -28,3 +28,50 @@ where
path.as_ref().display().to_string()
}
}

pub fn get_child_files<P: AsRef<Path>>(directory: P, files: Vec<FileData>) -> Vec<String> {
files
.into_iter()
.filter(|file_data| Path::new(&file_data.file).starts_with(directory.as_ref()))
.map(|file_data| file_data.file)
.collect()
}

#[cfg(test)]
mod test {
use super::*;
use std::path::PathBuf;

#[test]
fn should_get_child_files() {
let directory = PathBuf::from("foo");
let files = vec![
FileData {
file: "foo/bar".into(),
hash: "123".into(),
},
FileData {
file: "foo/baz".into(),
hash: "123".into(),
},
FileData {
file: "foo/child/bar".into(),
hash: "123".into(),
},
FileData {
file: "bar/baz".into(),
hash: "123".into(),
},
FileData {
file: "foo-other/not-child".into(),
hash: "123".into(),
}
];
let child_files = get_child_files(&directory, files);
assert_eq!(child_files, [
"foo/bar",
"foo/baz",
"foo/child/bar",
]);
}
}
8 changes: 7 additions & 1 deletion packages/nx/src/native/workspace/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use napi::bindgen_prelude::External;
use std::collections::HashMap;

use crate::native::hasher::hash;
use crate::native::utils::Normalize;
use crate::native::utils::{Normalize, path::get_child_files};
use rayon::prelude::*;
use std::ops::Deref;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -299,4 +299,10 @@ impl WorkspaceContext {
pub fn all_file_data(&self) -> Vec<FileData> {
self.files_worker.get_files()
}

#[napi]
pub fn get_files_in_directory(&self, directory: String) -> Vec<String> {
get_child_files(&directory, self.files_worker
.get_files())
}
}
8 changes: 8 additions & 0 deletions packages/nx/src/utils/workspace-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ export function getAllFileDataInContext(workspaceRoot: string) {
return workspaceContext.allFileData();
}

export function getFilesInDirectoryUsingContext(
workspaceRoot: string,
dir: string
) {
ensureContextAvailable(workspaceRoot);
return workspaceContext.getFilesInDirectory(dir);
}

export function updateProjectFiles(
projectRootMappings: Record<string, string>,
rustReferences: NxWorkspaceFilesExternals,
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright/executors.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"executors": {
"playwright": {
"implementation": "./src/executors/playwright/playwright",
"implementation": "./src/executors/playwright/playwright.impl",
"schema": "./src/executors/playwright/schema.json",
"description": "Run Playwright tests."
}
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export {
playwrightExecutor,
PlaywrightExecutorSchema,
} from './src/executors/playwright/playwright';
} from './src/executors/playwright/playwright.impl';
export { initGenerator } from './src/generators/init/init';
export { configurationGenerator } from './src/generators/configuration/configuration';
3 changes: 3 additions & 0 deletions packages/playwright/migrations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"generators": {}
}
8 changes: 7 additions & 1 deletion packages/playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"dependencies": {
"@nx/devkit": "file:../devkit",
"@nx/eslint": "file:../eslint",
"tslib": "^2.3.0"
"@nx/js": "file:../js",
"tslib": "^2.3.0",
"minimatch": "3.0.5"
},
"peerDependencies": {
"@playwright/test": "^1.36.0"
Expand All @@ -54,6 +56,10 @@
"./generators/*/schema.json": "./src/generators/*/schema.json",
"./executors.json": "./executors.json",
"./executors/*/schema.json": "./src/executors/*/schema.json",
"./plugin": "./plugin.js",
"./preset": "./src/utils/preset.js"
},
"nx-migrations": {
"migrations": "./migrations.json"
}
}
1 change: 1 addition & 0 deletions packages/playwright/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { createNodes, PlaywrightPluginOptions } from './src/plugins/plugin';
Loading

1 comment on commit 2374d8e

@vercel
Copy link

@vercel vercel bot commented on 2374d8e Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-nrwl.vercel.app
nx.dev
nx-dev-git-master-nrwl.vercel.app

Please sign in to comment.