Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
51e7ef5
Implement the basic installation helper
dmtrKovalenko Sep 17, 2020
312624f
Remove local link to node
dmtrKovalenko Sep 17, 2020
e3130a0
Improve helpers
dmtrKovalenko Sep 18, 2020
f7845fa
Make separate tsconfig.json for building binary scritps
dmtrKovalenko Sep 18, 2020
75dfe66
Rename build step to `bin`
dmtrKovalenko Sep 18, 2020
d295cb8
Fix transpiling script
dmtrKovalenko Sep 18, 2020
7a4a9f2
Add test with vitual file system
dmtrKovalenko Sep 21, 2020
36df7ab
Implement template payload logic
dmtrKovalenko Sep 21, 2020
acc0ef4
Add more tests
dmtrKovalenko Sep 21, 2020
1f92eaf
Try to fix CI
dmtrKovalenko Sep 21, 2020
5b61015
Show relative path for webpack config
dmtrKovalenko Sep 22, 2020
ddcac9b
Create fake bin file before npm i
dmtrKovalenko Sep 22, 2020
189ca1b
Add more comprehensive test for webpack code gen
dmtrKovalenko Sep 22, 2020
b9cdad5
Try to fix CI v2
dmtrKovalenko Sep 22, 2020
95bc0b3
Add babel template
dmtrKovalenko Sep 22, 2020
2623abc
Create rollup example
dmtrKovalenko Sep 22, 2020
9df7b67
Add rollup test
dmtrKovalenko Sep 22, 2020
5665e9e
Add additional print helper available
dmtrKovalenko Sep 22, 2020
5126200
Avoid bin links on ci
dmtrKovalenko Sep 22, 2020
6fd6977
Add default webpack options template
dmtrKovalenko Sep 23, 2020
08a382b
Merge branch main into feature/smart-installation
dmtrKovalenko Sep 23, 2020
5d6bfc9
Remove not related change from launch.json
dmtrKovalenko Sep 23, 2020
b08b9f6
Revert rollup example and template
dmtrKovalenko Sep 23, 2020
a99eb02
Read package.json right into string
dmtrKovalenko Sep 23, 2020
bb8ee10
Improve error message if cypress is not found
dmtrKovalenko Sep 23, 2020
fd1dfd4
Add greeting line explaining the tool running
dmtrKovalenko Sep 23, 2020
56f3610
Make bin/init.js executable
dmtrKovalenko Sep 23, 2020
7b2d681
Apply grammar suggestions from code review
dmtrKovalenko Sep 28, 2020
37a284a
Fix more grammar
dmtrKovalenko Sep 28, 2020
e8ddbef
Merge branch main into feature/smart-installation
dmtrKovalenko Sep 28, 2020
06e639f
Fix broken suggestion
dmtrKovalenko Sep 28, 2020
169bf55
Fix test
dmtrKovalenko Sep 28, 2020
eba7744
Merge branch 'main' into feature/smart-installation
dmtrKovalenko Sep 29, 2020
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add default webpack options template
  • Loading branch information
dmtrKovalenko committed Sep 23, 2020
commit 6fd69778ab2bc9d77e4e827cd4229b151912e88a
34 changes: 34 additions & 0 deletions docs/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,37 @@ When loading your `.babelrc` settings, `cypress-react-unit-test` sets `BABEL_ENV
```

See [examples/using-babel](examples/using-babel) folder for full example.

### Using rollup config

If you are using rollup for bundling – we can use it as well for the bundling. Check the example:

```js
// // cypress/plugins/index.js
const rollupPreprocessor = require('@bahmutov/cy-rollup')

module.exports = (on, config) => {
on(
'file:preprocessor',
rollupPreprocessor({
// this is the default value
configFile: 'rollup.config.js',
}),
)

require('@cypress/code-coverage/task')(on, config)
}
```

But make sure that several rollup plugins are required in order to bundle the code for cypress.

```js
// bundle node_modules
nodeResolve(),
// process commonjs modules
commonjs(),
// required for react (prop-types) sources
replace({ 'process.env.NODE_ENV': JSON.stringify('development') }),
```

See [examples/rollup](examples/rollup) folder for full example.
Copy link
Contributor

Choose a reason for hiding this comment

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

will come from PR 444

122 changes: 122 additions & 0 deletions init/init.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import chalk from 'chalk'
import highlight from 'cli-highlight'
import { main, guessTemplateForUsedFramework } from './init'
import inquirer from 'inquirer'
import { mockFs, clearMockedFs } from './test/mockFs'

jest.mock('fs')
jest.mock('inquirer')
jest.spyOn(global.console, 'log')

describe('end-to-end tests for init script', () => {
beforeEach(clearMockedFs)

it('automatically suggests to the user which config to use', async () => {
mockFs({
'cypress.json': '{}',
'webpack.config.js': 'module.exports = { }',
})

// @ts-ignore
inquirer.prompt = jest.fn(() =>
Promise.resolve({
chosenTemplateName: 'create-react-app',
componentFolder: 'cypress/component',
}),
)

await main()

const [{ choices, message }] = (inquirer.prompt as any).mock.calls[0][0]

expect(choices[0]).toBe('webpack')
expect(message).toContain(
`Press ${chalk.inverse(' Enter ')} to continue with ${chalk.green(
'webpack',
)} configuration`,
)
})

it('determines more presumable configuration to suggest', async () => {
mockFs({
'cypress.json': '{}',
// For next.js user will have babel config, but we want to suggest to use the closest config for the application code
'babel.config.js': 'module.exports = { }',
'package.json': JSON.stringify({ dependencies: { next: '^9.2.0' } }),
})

// @ts-ignore
inquirer.prompt = jest.fn(() =>
Promise.resolve({
chosenTemplateName: 'next.js',
componentFolder: 'src',
}),
)

await main()

const [{ choices, message }] = (inquirer.prompt as any).mock.calls[0][0]

expect(choices[0]).toBe('next.js')
expect(message).toContain(
`Press ${chalk.inverse(' Enter ')} to continue with ${chalk.green(
'next.js',
)} configuration`,
)
})

it('suggest the right instruction based on user template choice', async () => {
mockFs({
'cypress.json': '{}',
})

// @ts-ignore
inquirer.prompt = jest.fn(() =>
Promise.resolve({
chosenTemplateName: 'create-react-app',
componentFolder: 'src',
}),
)

await main()

expect(global.console.log).toBeCalledWith(
`Working example of component tests with ${chalk.green(
'create-react-app',
)}: ${chalk.bold.underline(
'https://github.com/bahmutov/cypress-react-unit-test/tree/main/examples/react-scripts',
)}\n`,
)
})

it('suggests right docs example and cypress.json config based on the `componentFolder` answer', async () => {
mockFs({
'cypress.json': '{}',
})

// @ts-ignore
inquirer.prompt = jest.fn(() =>
Promise.resolve({
chosenTemplateName: 'create-react-app',
componentFolder: 'cypress/component',
}),
)

await main()

const expectedCode = highlight(
JSON.stringify(
{
experimentalComponentTesting: true,
componentFolder: 'cypress/component',
testFiles: '**/*.spec.{js,ts,jsx,tsx}',
},
null,
2,
),
{ language: 'json' },
)

expect(global.console.log).toBeCalledWith(`\n${expectedCode}\n`)
})
})
22 changes: 15 additions & 7 deletions init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import { WebpackTemplate } from './templates/webpack-file'
import { ReactScriptsTemplate } from './templates/react-scripts'
import { BabelTemplate } from './templates/babel'
import { RollupTemplate } from './templates/rollup'
import { WebpackOptions } from './templates/webpack-options'

const templates: Record<string, Template<any>> = {
'next.js': NextTemplate,
'create-react-app': ReactScriptsTemplate,
webpack: WebpackTemplate,
rollup: RollupTemplate,
babel: BabelTemplate,
'default (webpack options)': WebpackOptions,
}

type TemplateGuess<T> = {
Expand All @@ -26,7 +28,7 @@ type TemplateGuess<T> = {
templatePayload: T | null
}

function guessTemplateForUsedFramework<T>(): TemplateGuess<T> {
export function guessTemplateForUsedFramework<T>(): TemplateGuess<T> {
for (const [name, template] of Object.entries(templates)) {
const typedTemplate = template as Template<T>
const { success, payload } = typedTemplate.test(process.cwd())
Expand Down Expand Up @@ -106,9 +108,7 @@ function printSupportHelper(supportFilePath: string) {
: requireCode

console.log(
`\n${stepNumber} This to the ${chalk.green.underline(
relativeSupportPath,
)}:`,
`\n${stepNumber} This to the ${chalk.green(relativeSupportPath)}:`,
)
console.log(
`\n${highlight(importCodeWithPreferredStyle, { language: 'js' })}\n`,
Expand All @@ -134,7 +134,7 @@ function printPluginHelper(pluginCode: string, pluginsFilePath: string) {
console.log(`\n${highlightedPluginCode}\n`)
}

async function main<T>() {
export async function main<T>() {
const { config, cypressConfigPath } = await getCypressConfig()
const {
defaultTemplate,
Expand Down Expand Up @@ -172,7 +172,7 @@ async function main<T>() {
)} to continue with ${chalk.green(
defaultTemplateName,
)} configuration or select other template from the list:`
: 'We were not able to automatically determine which framework you are using. Please choose from the list which configuration to use:',
: 'We were not able to automatically determine which framework or bundling tool you are using. Please choose from the list which configuration to use:',
},
{
type: 'input',
Expand Down Expand Up @@ -208,10 +208,18 @@ async function main<T>() {
chosenTemplateName,
)}: ${chalk.bold.underline(
chosenTemplate.getExampleUrl({ componentFolder }),
)}\n`,
)

console.log(
`Docs for different recipes of bundling tools: ${chalk.bold.underline(
'https://github.com/bahmutov/cypress-react-unit-test/blob/main/docs/recipes.md',
)}`,
)

console.log(`\nHappy testing with ${chalk.green('cypress.io')} 🔥🔥🔥\n`)
}

main().catch(e => console.error(e))
if (process.env.NODE_ENV !== 'test') {
main().catch(e => console.error(e))
}
55 changes: 55 additions & 0 deletions init/templates/webpack-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import chalk from 'chalk'
import { Template } from '../Template'

export const WebpackOptions: Template = {
// this should never show ideally
message: 'Default template using webpack options',
getExampleUrl: () =>
'https://github.com/bahmutov/cypress-react-unit-test/tree/main/examples/webpack-options',
test: () => ({ success: false }),
recommendedComponentFolder: 'src',
getPluginsCode: () =>
[
`const webpackPreprocessor = require('@cypress/webpack-preprocessor')`,
``,
`// Cypress Webpack preprocessor includes Babel env preset,`,
`// but to transpile JSX code we need to add Babel React preset`,
`module.exports = (on, config) => {`,
` const opts = webpackPreprocessor.defaultOptions`,
` const babelLoader = opts.webpackOptions.module.rules[0].use[0]`,
``,
` // add React preset to be able to transpile JSX`,
` babelLoader.options.presets.push(require.resolve('@babel/preset-react'))`,
``,
` // We can also push Babel istanbul plugin to instrument the code on the fly`,
` // and get code coverage reports from component tests (optional)`,
` if (!babelLoader.options.plugins) {`,
` babelLoader.options.plugins = []`,
` }`,
` babelLoader.options.plugins.push(require.resolve('babel-plugin-istanbul'))`,
``,
` // in order to mock named imports, need to include a plugin`,
` babelLoader.options.plugins.push([`,
` require.resolve('@babel/plugin-transform-modules-commonjs'),`,
` {`,
` loose: true,`,
` },`,
` ])`,
``,
` // add code coverage plugin`,
` require('@cypress/code-coverage/task')(on, config)`,
``,
` on('file:preprocessor', webpackPreprocessor(opts))`,
``,
` // if adding code coverage, important to return updated config`,
` return config`,
`}`,
].join('\n'),
printHelper: () => {
console.log(
`${chalk.inverse('Important:')} this configuration is using ${chalk.blue(
'new webpack configuration ',
)}to bundle components. If you are using some framework (e.g. next) or bundling tool (e.g. rollup/parcel) consider using them to bundle component specs for cypress. \n`,
)
},
}