Skip to content

Commit

Permalink
feat(react): add unit test examples when inSourceTests is passed
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi committed Dec 13, 2022
1 parent f0b581d commit 823e75a
Show file tree
Hide file tree
Showing 21 changed files with 169 additions and 68 deletions.
5 changes: 5 additions & 0 deletions docs/generated/packages/react.json
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,11 @@
"fileName": {
"type": "string",
"description": "Create a component with this file name."
},
"inSourceTests": {
"type": "boolean",
"default": false,
"description": "When using Vitest, separate spec files will not be generated and instead will be included within the source files. Read more on the Vitest docs site: https://vitest.dev/guide/in-source.html"
}
},
"required": ["name", "project"],
Expand Down
66 changes: 66 additions & 0 deletions e2e/react/src/react-package.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
checkFilesDoNotExist,
checkFilesExist,
expectTestsPass,
getSize,
killPorts,
newProject,
Expand Down Expand Up @@ -260,6 +261,71 @@ describe('Build React applications and libraries with Vite', () => {
proj = newProject();
});

it('should test and lint app with bundler=vite', async () => {
const viteApp = uniq('viteapp');

runCLI(
`generate @nrwl/react:app ${viteApp} --bundler=vite --no-interactive`
);

expectTestsPass(await runCLIAsync(`test ${viteApp}`));

const appLintResults = await runCLIAsync(`lint ${viteApp}`);
expect(appLintResults.combinedOutput).toContain('All files pass linting.');

await runCLIAsync(`build ${viteApp}`);
checkFilesExist(`dist/apps/${viteApp}/index.html`);
});

it('should test and lint app with bundler=vite and inSourceTests', async () => {
const viteApp = uniq('viteapp');
const viteLib = uniq('vitelib');

runCLI(
`generate @nrwl/react:app ${viteApp} --bundler=vite --unitTestRunner=vitest --inSourceTests --no-interactive`
);
expect(() => {
checkFilesExist(`src/apps/${viteApp}/src/app.spec.tsx`);
}).toThrow();

expectTestsPass(await runCLIAsync(`test ${viteApp}`));

const appLintResults = await runCLIAsync(`lint ${viteApp}`);
expect(appLintResults.combinedOutput).toContain('All files pass linting.');

await runCLIAsync(`build ${viteApp}`);
checkFilesExist(`dist/apps/${viteApp}/index.html`);

runCLI(
`generate @nrwl/react:lib ${viteLib} --bundler=vite --inSourceTests --no-interactive`
);
expect(() => {
checkFilesExist(`src/libs/${viteLib}/src/${viteLib}.spec.tsx`);
}).toThrow();

runCLI(
`generate @nrwl/react:component comp1 --inSourceTests --export --no-interactive`
);
expect(() => {
checkFilesExist(`src/libs/${viteLib}/src/comp1/comp1.spec.tsx`);
}).toThrow();

runCLI(`generate @nrwl/react:component comp2 --export --no-interactive`);
checkFilesExist(`src/libs/${viteLib}/src/comp2/comp2.spec.tsx`);

expectTestsPass(await runCLIAsync(`test ${viteLib}`));

const libLintResults = await runCLIAsync(`lint ${viteLib}`);
expect(libLintResults.combinedOutput).toContain('All files pass linting.');

await runCLIAsync(`build ${viteLib}`);
checkFilesExist(
`dist/libs/${viteLib}/index.d.ts`,
`dist/libs/${viteLib}/index.js`,
`dist/libs/${viteLib}/index.mjs`
);
});

it('should support bundling with Vite', async () => {
const viteLib = uniq('vitelib');

Expand Down
1 change: 1 addition & 0 deletions packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
project: options.projectName,
newProject: true,
includeVitest: true,
inSourceTests: options.inSourceTests,
});
tasks.push(viteTask);
} else if (options.bundler === 'webpack') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,5 @@ import { BrowserRouter } from 'react-router-dom';
import App from './<%= fileName %>';

describe('App', () => {
it('should render successfully', () => {
<% if (routing) { %>
const { baseElement } = render(<BrowserRouter><App /></BrowserRouter>);
<% } else { %>
const { baseElement } = render(<App />);
<% } %>
expect(baseElement).toBeTruthy();
});

it('should have a greeting as the title', () => {
<% if (routing) { %>
const { getByText } = render(<BrowserRouter><App /></BrowserRouter>);
<% } else { %>
const { getByText } = render(<App />);
<% } %>
expect(getByText(/Welcome <%= projectName %>/gi)).toBeTruthy();
});
<%- appTests %>
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,5 @@ import { BrowserRouter } from 'react-router-dom';
import App from './<%= fileName %>';

describe('App', () => {
it('should render successfully', () => {
<% if (routing) { %>
const { baseElement } = render(<BrowserRouter><App /></BrowserRouter>);
<% } else { %>
const { baseElement } = render(<App />);
<% } %>
expect(baseElement).toBeTruthy();
});

it('should have a greeting as the title', () => {
<% if (routing) { %>
const { getByText } = render(<BrowserRouter><App /></BrowserRouter>);
<% } else { %>
const { getByText } = render(<App />);
<% } %>
expect(getByText(/Welcome <%= projectName %>/gi)).toBeTruthy();
});
<%- appTests %>
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ export function App() {
<% } %>

export default App;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ export function App() {
<% } %>

export default App;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export function App() {
<% } %>

export default App;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ export function App() {
<% } %>

export default App;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ export function App() {
<% } %>

export default App;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import { NormalizedSchema } from '../schema';
import {
names,
offsetFromRoot,
Tree,
toJS,
generateFiles,
joinPathFragments,
updateJson,
} from '@nrwl/devkit';
import { names, offsetFromRoot, Tree, toJS, generateFiles } from '@nrwl/devkit';
import { join } from 'path';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import { createTsConfig } from '../../../utils/create-ts-config';
import { getInSourceVitestTestsTemplate } from '../../../utils/get-in-source-vitest-tests-template';
import { getAppTests } from './get-app-tests';

export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
let styleSolutionSpecificAppFiles: string;
Expand All @@ -30,11 +24,14 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
host,
options.appProjectRoot
);
const appTests = getAppTests(options);
const templateVariables = {
...names(options.name),
...options,
tmpl: '',
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
appTests,
inSourceVitestTests: getInSourceVitestTestsTemplate(appTests),
};

generateFiles(
Expand Down Expand Up @@ -62,18 +59,6 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
templateVariables
);

if (options.unitTestRunner === 'vitest' && options.inSourceTests == true) {
let originalAppContents = host
.read(`${options.appProjectRoot}/src/app/${options.fileName}.tsx`)
.toString();
originalAppContents += `
if (import.meta.vitest) {
// add tests related to your file here
// For more information please visit the Vitest docs site here: https://vitest.dev/guide/in-source.html
}
`;
}

if (options.js) {
toJS(host);
}
Expand Down
23 changes: 23 additions & 0 deletions packages/react/src/generators/application/lib/get-app-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NormalizedSchema } from '../schema';

export function getAppTests(options: NormalizedSchema) {
return `
it('should render successfully', () => {
${
options.routing
? 'const { baseElement } = render(<BrowserRouter><App /></BrowserRouter>);'
: 'const { baseElement } = render(<App />);'
}
expect(baseElement).toBeTruthy();
});
it('should have a greeting as the title', () => {
${
options.routing
? 'const { getByText } = render(<BrowserRouter><App /></BrowserRouter>);'
: 'const { getByText } = render(<App />);'
}
expect(getByText(/Welcome ${options.projectName}/gi)).toBeTruthy();
});
`;
}
19 changes: 10 additions & 9 deletions packages/react/src/generators/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,15 @@ import * as ts from 'typescript';
import { addStyledModuleDependencies } from '../../rules/add-styled-dependencies';
import { assertValidStyle } from '../../utils/assertion';
import { addImport } from '../../utils/ast-utils';
import { getInSourceVitestTestsTemplate } from '../../utils/get-in-source-vitest-tests-template';
import {
reactRouterDomVersion,
typesReactRouterDomVersion,
} from '../../utils/versions';
import { getComponentTests } from './get-component-tests';
import { NormalizedSchema } from './noramlized-schema';
import { Schema } from './schema';

interface NormalizedSchema extends Schema {
projectSourceRoot: string;
fileName: string;
className: string;
styledModule: null | string;
hasStyles: boolean;
}

export async function componentGenerator(host: Tree, schema: Schema) {
const options = await normalizeOptions(host, schema);
createComponentFiles(host, options);
Expand Down Expand Up @@ -62,15 +57,21 @@ function createComponentFiles(host: Tree, options: NormalizedSchema) {
options.directory
);

const componentTests = getComponentTests(options);
generateFiles(host, joinPathFragments(__dirname, './files'), componentDir, {
...options,
componentTests,
inSourceVitestTests: getInSourceVitestTestsTemplate(componentTests),
tmpl: '',
});

for (const c of host.listChanges()) {
let deleteFile = false;

if (options.skipTests && /.*spec.tsx/.test(c.path)) {
if (
(options.skipTests || options.inSourceTests) &&
/.*spec.tsx/.test(c.path)
) {
deleteFile = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,5 @@ import { render } from '@testing-library/react';
import <%= className %> from './<%= fileName %>';

describe('<%= className %>', () => {
it('should render successfully', () => {
const { baseElement } = render(< <%= className %> />);
expect(baseElement).toBeTruthy();
});
<%- componentTests %>
});
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ export function <%= className %>(props: <%= className %>Props) {
<% } %>

export default <%= className %>;

<% if (inSourceTests === true) { %> <%- inSourceVitestTests %> <% } %>
10 changes: 10 additions & 0 deletions packages/react/src/generators/component/get-component-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NormalizedSchema } from './noramlized-schema';

export function getComponentTests(schema: NormalizedSchema) {
return `
it('should render successfully', () => {
const { baseElement } = render(<${schema.className} />);
expect(baseElement).toBeTruthy();
});
`;
}
9 changes: 9 additions & 0 deletions packages/react/src/generators/component/noramlized-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Schema } from './schema';

export interface NormalizedSchema extends Schema {
projectSourceRoot: string;
fileName: string;
className: string;
styledModule: null | string;
hasStyles: boolean;
}
1 change: 1 addition & 0 deletions packages/react/src/generators/component/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export interface Schema {
flat?: boolean;
globalCss?: boolean;
fileName?: string;
inSourceTests?: boolean;
}
5 changes: 5 additions & 0 deletions packages/react/src/generators/component/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
"fileName": {
"type": "string",
"description": "Create a component with this file name."
},
"inSourceTests": {
"type": "boolean",
"default": false,
"description": "When using Vitest, separate spec files will not be generated and instead will be included within the source files. Read more on the Vitest docs site: https://vitest.dev/guide/in-source.html"
}
},
"required": ["name", "project"]
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
routing: options.routing,
js: options.js,
pascalCaseFiles: options.pascalCaseFiles,
inSourceTests: options.inSourceTests,
});
tasks.push(componentTask);
}
Expand Down
17 changes: 17 additions & 0 deletions packages/react/src/utils/get-in-source-vitest-tests-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function getInSourceVitestTestsTemplate(testContent: string) {
return `
if (import.meta.vitest) {
// add tests related to your file here
// For more information please visit the Vitest docs site here: https://vitest.dev/guide/in-source.html
const { it, expect, beforeEach } = import.meta.vitest;
let render: any;
beforeEach(async () => {
render = (await import('@testing-library/react')).render;
});
${testContent}
}
`;
}

0 comments on commit 823e75a

Please sign in to comment.