Skip to content

Commit

Permalink
feat: generate jest tests from templates
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Mar 27, 2021
1 parent 1a20fc2 commit 74d02f8
Show file tree
Hide file tree
Showing 115 changed files with 2,918 additions and 1,160 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
templates
16 changes: 15 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,21 @@
"name": "jest jest-addon",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"cwd": "${workspaceFolder}/plugins/jest-snapshots",
"args": ["stories"],
"args": ["enzyme-esm"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
}
},
{
"type": "node",
"request": "launch",
"name": "jest components",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"cwd": "${workspaceFolder}/ui/components",
"args": [""],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
Expand Down
49 changes: 23 additions & 26 deletions core/config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
defaultRunConfig,
convertConfig,
} from '@component-controls/core';
import { defaultConfigFolder } from '@component-controls/core/node-utils';

export const buildConfigFileNames = [
'buildtime.js',
Expand Down Expand Up @@ -56,21 +55,9 @@ export const getConfigurationArg = (
return argv.config;
};

/**
* given a base project folder and a configuration folder, returns the configuration file
*
* @param baseFolder project folder to start the search with
* @param configFolder folder where the configuration file is located
* @param args optional arguments
*/
export const loadConfiguration = (
baseFolder: string,
configFolder?: string,
args?: string[],
defaultConfigPath?: string,
export const loadConfig = (
configPath: string,
): ConfigurationResult | undefined => {
const folder = configFolder ?? getConfigurationArg(args) ?? defaultConfigPath;
const configPath = folder ? path.resolve(baseFolder, folder) : baseFolder;
const hasConfigFolder = fs.existsSync(configPath);
if (!hasConfigFolder) {
console.warn('configuration folder not found', configPath);
Expand Down Expand Up @@ -102,6 +89,24 @@ export const loadConfiguration = (
return undefined;
};

/**
* given a base project folder and a configuration folder, returns the configuration file
*
* @param baseFolder project folder to start the search with
* @param configFolder folder where the configuration file is located
* @param args optional arguments
*/
export const loadConfiguration = (
baseFolder: string,
configFolder?: string,
args?: string[],
defaultConfigPath?: string,
): ConfigurationResult | undefined => {
const folder = configFolder ?? getConfigurationArg(args) ?? defaultConfigPath;
const configPath = folder ? path.resolve(baseFolder, folder) : baseFolder;
return loadConfig(configPath);
};

//fix for sb5 issue handling glob
const fixGlob = (golbExpr: string): string => golbExpr.replace('.(', '.@(');

Expand Down Expand Up @@ -177,26 +182,18 @@ export const configRequireContext = ({
* @param configFilePath the config folder - relative to the root path
* @returns merged configuration
*/
export const loadConfigurations = (
rootPath: string,
configFilePath?: string,
): RunConfiguration | undefined => {
const config = loadConfiguration(
rootPath,
configFilePath,
undefined,
defaultConfigFolder,
);
export const loadConfigurations = (configPath: string): RunConfiguration => {
const config = loadConfig(configPath);
const buildConfig: BuildConfiguration = config
? mergeConfig(defaultBuildConfig, config.config)
: defaultBuildConfig;

let runtimeConfig = {};
if (config?.optionsFilePath) {
const req = require(config?.optionsFilePath);
runtimeConfig = req.default || req;
}
const runConfig = mergeConfig(defaultRunConfig, runtimeConfig);

return mergeConfig(
defaultRunConfig,
convertConfig(mergeConfig(buildConfig, runConfig)),
Expand Down
5 changes: 4 additions & 1 deletion core/config/test/config.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import path from 'path';
import { loadConfigurations } from '../src';

describe('load both configurations', () => {
test('load', () => {
const config = loadConfigurations(__dirname, 'fixtures/.config');
const config = loadConfigurations(
path.resolve(__dirname, 'fixtures/.config'),
);
expect(config).toMatchObject({
title: 'Component controls',
description:
Expand Down
1 change: 0 additions & 1 deletion core/render/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"@component-controls/core": "^3.4.2"
},
"devDependencies": {
"@component-controls/render": "^3.4.2",
"@component-controls/ts-markdown-docs": "^2.6.0",
"@types/jest": "^26.0.10",
"@types/react": "^16.9.34",
Expand Down
3 changes: 0 additions & 3 deletions core/render/src/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ export const render: FrameworkRenderFn = (story, doc, options: any = {}) => {
if (!story) {
throw new Error(`Invalid story`);
}
if (!doc) {
throw new Error(`Invalid doc`);
}
const controls = story.controls;
const values = getControlValues(controls);
//parameters added to avoid bug in SB6 rc that assumes parameters exist
Expand Down
13 changes: 1 addition & 12 deletions core/test-renderers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,11 @@
"@component-controls/config": "^3.4.2",
"@component-controls/core": "^3.4.2",
"@component-controls/render": "^3.4.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^10.4.9",
"@wojtekmaj/enzyme-adapter-react-17": "^0.3.1",
"enzyme": "^3.11.0",
"enzyme-to-json": "^3.5.0",
"jest": "^26.4.2",
"path": "^0.12.7",
"react-dom": "^16.13.1",
"rc-util": "^5.0.7",
"react-test-renderer": "^16.13.1"
"react-dom": "^16.13.1"
},
"devDependencies": {
"@types/enzyme": "^3.10.5",
"@types/react-dom": "^16.9.8",
"@types/react-test-renderer": "^16.9.3",
"@types/testing-library__jest-dom": "^5.9.2",
"typescript": "^4.0.5"
},
"publishConfig": {
Expand Down
117 changes: 29 additions & 88 deletions core/test-renderers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,72 +9,11 @@ import {
ExampleControls,
mergeControlValues,
getControlValues,
FrameworkRenderFn,
RunConfiguration,
} from '@component-controls/core';
import { loadConfigurations } from '@component-controls/config';
import { render as reactRender } from '@component-controls/render/react';
import { render as reactTestRenderer } from './renderers/react-test-renderer';
import { render as enzymeReact16Renderer } from './renderers/enzyme-react-16';
import { render as rtlRenderer } from './renderers/react-testing-library';
import { RendererFn, RendererFnResult, Json } from './types';
export { RendererFn, RendererFnResult, Json };

export type rendererTypes = 'react' | 'rtr' | 'enzyme';
export const renderers: Record<rendererTypes, RendererFn> = {
react: rtlRenderer,
rtr: reactTestRenderer,
enzyme: enzymeReact16Renderer,
};

export async function renderExample(
props: {
example: Example;
doc: Document;
projectFolder: string;
configFolder?: string;
renderer: 'react';
controls?: ExampleControls;
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
options?: any,
): ReturnType<typeof rtlRenderer>;

export async function renderExample<Props = unknown>(
props: {
example: Example<Props>;
doc: Document;
projectFolder: string;
configFolder?: string;
controls?: ExampleControls;
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
options?: any,
): ReturnType<typeof rtlRenderer>;

export async function renderExample<Props = unknown>(
props: {
example: Example<Props>;
doc: Document;
projectFolder: string;
configFolder?: string;
renderer: 'rtr';
controls?: ExampleControls;
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
options?: any,
): ReturnType<typeof reactTestRenderer>;

export async function renderExample<Props = unknown>(
props: {
example: Example<Props>;
doc: Document;
projectFolder: string;
configFolder?: string;
renderer: 'enzyme';
controls?: ExampleControls;
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
options?: any,
): ReturnType<typeof enzymeReact16Renderer>;

/**
* render an example using a test framework.
Expand All @@ -83,34 +22,37 @@ export async function renderExample<Props = unknown>(
* @param options optional to be passed to the render function of the selected testing framework
* @returns a toJson function to use in snapshots, in addition all the props returned by the selected test frameowrk
*/
export async function renderExample<Props = unknown>(
{
example,
doc,
projectFolder,
configFolder,
renderer = 'react',
controls,
}: {
example: Example<Props>;
doc: Document;
projectFolder: string;
configFolder?: string;
renderer?: rendererTypes;
controls?: ExampleControls;
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
options?: any,
): Promise<RendererFnResult | undefined> {
const config = loadConfigurations(projectFolder, configFolder) || {};
if (!config.renderFn) {
config.renderFn = reactRender;
export function renderExample<Props = unknown>({
example,
doc,
config,
controls,
}: {
example: Example<Props>;
doc: Document;
config: string | RunConfiguration;
controls?: ExampleControls;
}): ReturnType<FrameworkRenderFn> {
let runtimeConfig;
if (typeof config === 'string') {
runtimeConfig = loadConfigurations(config);
if (!runtimeConfig) {
throw new Error(`Could not load configuration ${config}`);
}
} else {
runtimeConfig = config;
}
if (!runtimeConfig.renderFn) {
runtimeConfig.renderFn = reactRender;
}
const story = example as Story;
if (typeof example === 'function') {
story.renderFn = example as StoryRenderFn;
}
Object.assign(story, mergeStoryProps(mergeStoryProps(config, doc), story));
Object.assign(
story,
mergeStoryProps(mergeStoryProps(runtimeConfig, doc), story),
);
story.controls = transformControls(story.controls);
if (controls && story.controls) {
story.controls = mergeControlValues(
Expand All @@ -119,6 +61,5 @@ export async function renderExample<Props = unknown>(
getControlValues(transformControls(controls as ComponentControls)),
);
}
const rendererFn = renderers[renderer];
return await rendererFn({ story, doc, config }, options);
return (runtimeConfig.renderFn as StoryRenderFn)(story, doc);
}
34 changes: 20 additions & 14 deletions core/test-renderers/test/jazmine-story.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import path from 'path';
import { mount, configure } from 'enzyme';
import toJson from 'enzyme-to-json';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';

import { renderExample } from '../src';
import { VariantButtonProps } from './fixtures/VariantButton';

configure({ adapter: new Adapter() });

import doc, {
primary,
disabled,
Expand All @@ -10,35 +16,35 @@ import doc, {

describe('VariantButton', () => {
test('controls', async () => {
const { component } = await renderExample<VariantButtonProps>({
const rendered = renderExample<VariantButtonProps>({
example: overview,
doc,
projectFolder: path.join(__dirname, 'fixtures'),
renderer: 'enzyme',
config: path.join(__dirname, 'fixtures/.config'),
});
const component = mount(rendered);
expect(component.find('div[data-testid="label"]').text()).toBe('Button');
});
test('controls values', async () => {
const { component } = await renderExample<VariantButtonProps>({
const rendered = renderExample<VariantButtonProps>({
example: overview,
doc,
projectFolder: path.join(__dirname, 'fixtures'),
renderer: 'enzyme',
config: path.join(__dirname, 'fixtures/.config'),
controls: {
text: 'New Text',
},
});
const component = mount(rendered);
expect(component.find('div[data-testid="label"]').text()).toBe('New Text');
});
test('primary', async () => {
const { toJson, component } = await renderExample({
const rendered = renderExample({
example: primary,
doc,
projectFolder: path.join(__dirname, 'fixtures'),
renderer: 'enzyme',
config: path.join(__dirname, 'fixtures/.config'),
});
const component = mount(rendered);

expect(toJson()).toMatchSnapshot();
expect(toJson(component, { mode: 'deep' })).toMatchSnapshot();
const label = component.find('div[data-testid="label"]');
expect(label.text()).toBe('Primary');

Expand All @@ -51,13 +57,13 @@ describe('VariantButton', () => {
).toHaveProperty('background', 'lightblue');
});
test('disabled', async () => {
const { toJson, component } = await renderExample({
const rendered = renderExample({
example: disabled,
doc,
projectFolder: path.join(__dirname, 'fixtures'),
renderer: 'enzyme',
config: path.join(__dirname, 'fixtures/.config'),
});
expect(toJson()).toMatchSnapshot();
const component = mount(rendered);
expect(toJson(component, { mode: 'deep' })).toMatchSnapshot();
expect(component.find('button').prop('disabled')).toBe(true);
});
});
Loading

0 comments on commit 74d02f8

Please sign in to comment.