Skip to content

Commit

Permalink
jest-test-gen 1.2.0 add outputDir and support for ts and tsx components
Browse files Browse the repository at this point in the history
  • Loading branch information
egm0121 committed Aug 7, 2022
1 parent 5f194a9 commit 2bd37ab
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 23 deletions.
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

Automates creation of initial unit test files taking dependencies into account.

Supported exports:
Parsing and test generation is avaialable for the following exports:

* Typescript typed React class components 🆕
* Typescript typed Functional components 🆕
* React Functional components 🆕
* React Class based components 🆕
* ES6 Classes default export or named exports
Expand Down Expand Up @@ -36,19 +38,14 @@ run `npm i -g jest-test-gen`

run `jest-test-gen <path-to-file>`

## TODO

* Custom test output for React components
* Enhance jest.mock support
* TS unit test output for Typescript sources

## Development

It's probably best to:

* add an input file in `spec/fixtures` folder test.js
* add expected output file, e.g. expected.test.js
* link them in integration.spec.ts
* add a snapshot test for the input spec in `integration.spec.ts`
* verify that the snapshot is actually the wanted test output before commiting the updated snapshot.

Alternavely, you can:

Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
{
"name": "jest-test-gen",
"version": "1.1.1",
"version": "1.2.0",
"description": "Generator of jest unit test with all imports mocked and tests stub for every class and function exported",
"keywords": [
"jest",
"unit test generator",
"test generator",
"mocks",
"testing",
"jest generator",
"es6 classes",
"functions",
"export parsing"
"export parsing",
"typescript",
"tsx"
],
"main": "lib/public-api.js",
"scripts": {
Expand Down
135 changes: 135 additions & 0 deletions spec/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -546,3 +546,138 @@ describe('MyVarClass', () => {
});
});"
`;
exports[`integration typescript support component class based - generic arg parsing should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import React from 'react';
import { Card } from './tsFunctionalTyped';
const renderTree = tree => renderer.create(tree);
describe('<Card>', () => {
it('should render component', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
myOptionalString={/* string */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
exports[`integration typescript support component functional - FunctionComponent<propType> - generic type arg parsing should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import React, { FunctionComponent } from 'react';
import { Card } from './tsFunctionalGeneric';
const renderTree = tree => renderer.create(tree);
describe('<Card>', () => {
it('should render component', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
exports[`integration typescript support component functional - React.FC<propType> - generic type arg parsing should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import * as React from 'react';
import { Card } from './tsFunctionalGeneric_React.FC';
const renderTree = tree => renderer.create(tree);
describe('<Card>', () => {
it('should render component', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* string */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* string */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
exports[`integration typescript support component functional - typed prop argument - array of type syntax should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import React from 'react';
import { CardItems } from './tsFunctionalTypedArray';
const renderTree = tree => renderer.create(tree);
describe('<CardItems>', () => {
it('should render component', () => {
expect(renderTree(<CardItems
title={/* string */}
items={/* string[] */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<CardItems
title={/* string */}
items={/* string[] */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
exports[`integration typescript support component functional - typed prop argument - function declaration parsing should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import React from 'react';
import { Card } from './tsFunctionalTypedDeclaration';
const renderTree = tree => renderer.create(tree);
describe('<Card>', () => {
it('should render component', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
myOptionalString={/* string */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
exports[`integration typescript support component functional - typed prop argument should match snapshot 1`] = `
"import renderer from 'react-test-renderer';
import React from 'react';
import { Card } from './tsFunctionalTyped';
const renderTree = tree => renderer.create(tree);
describe('<Card>', () => {
it('should render component', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
/>).toJSON()).toMatchSnapshot();
});
it('should render component with props', () => {
expect(renderTree(<Card
title={/* string */}
paragraph={/* CardParagraph */}
myOptionalString={/* string */}
/>).toJSON()).toMatchSnapshot();
});
});"
`;
13 changes: 13 additions & 0 deletions spec/fixtures/components/tsClassComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { Component } from 'react'; // let's also import Component

type ClockProps = {
greeting: string,
myTime: Date,
cb?: () => void,
}
export class MyComp extends Component<ClockProps> {

render() {
return <p>The prop is {this.props.greeting}</p>
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';

export const userInfo = {
contactId: PropTypes.string,
isOpen: PropTypes.bool,
};

export type UserInfoProps = PropTypes.InferProps<typeof userInfo>;

const UserInfo: React.FC<UserInfoProps> = ({
contactId,
isOpen = false,
}) => {
return (
<p>User Info: {contactId} {isOpen}</p>
);
};

export default UserInfo;
19 changes: 19 additions & 0 deletions spec/fixtures/components/tsFunctionalGeneric.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { FunctionComponent } from 'react'; // importing FunctionComponent

type CardParagraph = {
content: string
}

type CardProps = {
title: string,
paragraph: CardParagraph
}

export const Card: FunctionComponent<CardProps> = ({ title, paragraph }) => <aside>
<h2>{ title }</h2>
<p>
{ paragraph.content }
</p>
</aside>

const el = <Card title="Welcome!" paragraph={{content:"To this example"}} />
15 changes: 15 additions & 0 deletions spec/fixtures/components/tsFunctionalGeneric_React.FC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react';

type CardProps = {
title: string,
paragraph: string
}

export const Card: React.FC<CardProps> = ({ title, paragraph }) => <aside>
<h2>{ title }</h2>
<p>
{ paragraph }
</p>
</aside>

const el = <Card title="Welcome!" paragraph="To this example" />
20 changes: 20 additions & 0 deletions spec/fixtures/components/tsFunctionalTyped.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'; // we need this to make JSX compile

type CardParagraph = {
content: string
}

type CardProps = {
title: string,
paragraph: CardParagraph
myOptionalString?: string
}

export const Card = ({ title, paragraph }: CardProps) => <aside>
<h2>{ title }</h2>
<p>
{ paragraph }
</p>
</aside>

const el = <Card title="Welcome!" paragraph={{ content: "To this example" }} />
15 changes: 15 additions & 0 deletions spec/fixtures/components/tsFunctionalTypedArray.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'; // we need this to make JSX compile

type CardProps = {
title: string,
items: string[]
}

export const CardItems = ({ title, items }: CardProps) => <aside>
<h2>{ title }</h2>
<p>
{ items.join(',') }
</p>
</aside>

const el = <CardItems title="Welcome!" items={['a','b','c']} />
21 changes: 21 additions & 0 deletions spec/fixtures/components/tsFunctionalTypedDeclaration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'; // we need this to make JSX compile

type CardParagraph = {
content: string
}

type CardProps = {
title: string,
paragraph: CardParagraph
myOptionalString?: string
}

export function Card({ title, paragraph }: CardProps) {
return <aside>
<h2>{ title }</h2>
<p>
{ paragraph }
</p>
</aside>
}
const el = <Card title="Welcome!" paragraph={{ content: "To this example" }} />
32 changes: 32 additions & 0 deletions spec/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,38 @@ describe('integration', () => {
file: 'spec/fixtures/components/multipleComponent.js',
});
});
describe(`typescript support`, () => {
describe('component class based - generic arg parsing', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalTyped.tsx'
})
});
describe('component functional - typed prop argument', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalTyped.tsx'
})
});
describe('component functional - typed prop argument - array of type syntax', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalTypedArray.tsx'
})
});
describe('component functional - typed prop argument - function declaration parsing', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalTypedDeclaration.tsx'
})
});
describe('component functional - FunctionComponent<propType> - generic type arg parsing', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalGeneric.tsx'
})
});
describe('component functional - React.FC<propType> - generic type arg parsing', () => {
createSnapshotTest({
file: 'spec/fixtures/components/tsFunctionalGeneric_React.FC.tsx'
})
});
});
});

function createSnapshotTest(input: {
Expand Down
1 change: 0 additions & 1 deletion src/generate-unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function generateUnitTest(path: string, _sourceCode: string, input: Parse
}
const templateDir = `${__dirname}/../templates`;
const relativePath = './' + basename(path, extname(path));
console.log(relativePath);
const quoteSymbol = determinateUsedQuote(input.imports);

let namedExportsList = [
Expand Down
Loading

0 comments on commit 2bd37ab

Please sign in to comment.