feat: Use plugins on config files (#18798)

Co-authored-by: Tim Griesser <tgriesser10@gmail.com>
This commit is contained in:
Alejandro Estrada
2021-11-16 14:45:26 -05:00
committed by GitHub
parent 8a2acdcdfa
commit bb8251b752
259 changed files with 2657 additions and 2636 deletions

View File

@@ -1032,6 +1032,8 @@ jobs:
runner-integration-tests-chrome,
runner-ct-integration-tests-chrome,
reporter-integration-tests,
run-app-integration-tests-chrome,
run-launchpad-integration-tests-chrome
- run: yarn percy build:finalize
cli-visual-tests:
@@ -1914,7 +1916,21 @@ jobs:
CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1"
command: |
rm -rf cypress.json
echo 'export default {}' > cypress.config.ts
echo "export default {
e2e: {
setupNodeEvents (on, config) {
on('task', {
log (x) {
console.log(x)
return null
},
})
return config
},
},
}" > cypress.config.ts
- run:
name: Run project tests 🗳
working_directory: <<parameters.wd>>

View File

@@ -6,6 +6,7 @@ const mockfs = require('mock-fs')
const Promise = require('bluebird')
const util = require('../lib/util')
const { MockChildProcess } = require('spawn-mock')
const _kill = MockChildProcess.prototype.kill
const patchMockSpawn = () => {

View File

@@ -2813,6 +2813,11 @@ declare namespace Cypress {
* An array of objects defining the certificates
*/
clientCertificates: ClientCertificate[]
/**
* Handle Cypress plugins
*/
setupNodeEvents: (on: PluginEvents, config: PluginConfigOptions) => Promise<PluginConfigOptions> | PluginConfigOptions
}
/**

View File

@@ -9,5 +9,6 @@ export default defineConfig({
'component': {
'componentFolder': 'src/app',
'testFiles': '**/*cy-spec.ts',
'setupNodeEvents': require('./cypress/plugins'),
},
})

View File

@@ -13,4 +13,13 @@ module.exports = {
],
componentFolder: 'src',
fixturesFolder: false,
component: {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/vite-dev-server')
on('dev-server:start', (options) => startDevServer({ options }))
return config
},
},
}

View File

@@ -1,11 +0,0 @@
// @ts-check
const { startDevServer } = require('@cypress/vite-dev-server')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
on('dev-server:start', (options) => startDevServer({ options }))
return config
}

View File

@@ -1,3 +1,5 @@
// @ts-check
module.exports = {
'viewportWidth': 400,
'viewportHeight': 400,
@@ -12,4 +14,70 @@ module.exports = {
'**/__image_snapshots__/*',
],
'experimentalFetchPolyfill': true,
'component': {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const path = require('path')
const babelConfig = require('./babel.config.js')
const webpackConfig = {
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
mode: 'development',
devtool: false,
output: {
publicPath: '/',
chunkFilename: '[name].bundle.js',
},
module: {
rules: [
{
test: /\.(js|jsx|mjs|ts|tsx)$/,
loader: 'babel-loader',
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '..', '..', '.babel-cache') },
},
{
test: /\.modules\.css$/i,
exclude: [/node_modules/],
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
{
test: /\.css$/,
exclude: [/node_modules/, /\.modules\.css$/i],
use: ['style-loader', 'css-loader'],
},
{
// some of our examples import SVG
test: /\.svg$/,
loader: 'svg-url-loader',
},
{
// some of our examples import SVG
test: /\.svg$/,
loader: 'svg-url-loader',
},
{
test: /\.(png|jpg)$/,
use: ['file-loader'],
},
],
},
}
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig, disableLazyCompilation: false })
})
return config
},
},
}

View File

@@ -1,73 +0,0 @@
// @ts-check
const { startDevServer } = require('@cypress/webpack-dev-server')
const path = require('path')
const babelConfig = require('../../babel.config.js')
/** @type import("webpack").Configuration */
const webpackConfig = {
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
mode: 'development',
devtool: false,
output: {
publicPath: '/',
chunkFilename: '[name].bundle.js',
},
module: {
rules: [
{
test: /\.(js|jsx|mjs|ts|tsx)$/,
loader: 'babel-loader',
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '..', '..', '.babel-cache') },
},
{
test: /\.modules\.css$/i,
exclude: [/node_modules/],
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
{
test: /\.css$/,
exclude: [/node_modules/, /\.modules\.css$/i],
use: ['style-loader', 'css-loader'],
},
{
// some of our examples import SVG
test: /\.svg$/,
loader: 'svg-url-loader',
},
{
// some of our examples import SVG
test: /\.svg$/,
loader: 'svg-url-loader',
},
{
test: /\.(png|jpg)$/,
use: ['file-loader'],
},
],
},
}
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
if (config.testingType !== 'component') {
throw Error(`This is a component testing project. testingType should be 'component'. Received ${config.testingType}`)
}
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig, disableLazyCompilation: false })
})
return config
}

View File

@@ -4,4 +4,17 @@ module.exports = {
'testFiles': '**/*spec.js',
'viewportWidth': 500,
'viewportHeight': 500,
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,16 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -2,5 +2,13 @@ module.exports = {
'component': {
'testFiles': '**/*.test.{js,ts,jsx,tsx}',
'componentFolder': 'src',
setupNodeEvents (on, config) {
const cracoConfig = require('./craco.config.js')
const devServer = require('@cypress/react/plugins/craco')
devServer(on, config, cracoConfig)
return config
},
},
}

View File

@@ -1,13 +0,0 @@
// @ts-check
const cracoConfig = require('../../craco.config.js')
const devServer = require('@cypress/react/plugins/craco')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
devServer(on, config, cracoConfig)
return config
}

View File

@@ -6,6 +6,30 @@ export default defineConfig({
'component': {
'testFiles': '**/*.spec.{js,ts,jsx,tsx}',
'componentFolder': 'src',
setupNodeEvents (on, config) {
const findReactScriptsWebpackConfig = require('@cypress/react/plugins/react-scripts/findReactScriptsWebpackConfig')
const { startDevServer } = require('@cypress/webpack-dev-server')
const _ = require('lodash')
const map = _.map([4, 8], (n) => n * 2)
console.log(map)
require('@cypress/code-coverage/task')(on, config)
const webpackConfig = findReactScriptsWebpackConfig(config)
const rules = webpackConfig.module.rules.find((rule) => !!rule.oneOf).oneOf
const babelRule = rules.find((rule) => typeof rule.loader === 'string' && /babel-loader/.test(rule.loader))
typeof babelRule.options !== 'string' && babelRule.options.plugins.push(require.resolve('babel-plugin-istanbul'))
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig })
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
'env': {
'cypress-react-selector': {

View File

@@ -1,29 +0,0 @@
// @ts-check
const findReactScriptsWebpackConfig = require('@cypress/react/plugins/react-scripts/findReactScriptsWebpackConfig')
const { startDevServer } = require('@cypress/webpack-dev-server')
const _ = require('lodash')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
const map = _.map([4, 8], (n) => n * 2)
console.log(map)
require('@cypress/code-coverage/task')(on, config)
const webpackConfig = findReactScriptsWebpackConfig(config)
const rules = webpackConfig.module.rules.find((rule) => !!rule.oneOf).oneOf
const babelRule = rules.find((rule) => typeof rule.loader === 'string' && /babel-loader/.test(rule.loader))
typeof babelRule.options !== 'string' && babelRule.options.plugins.push(require.resolve('babel-plugin-istanbul'))
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig })
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -5,4 +5,13 @@ module.exports = {
'viewportHeight': 800,
'componentFolder': 'cypress/components',
'pluginsFile': 'cypress/plugins.js',
'component': {
setupNodeEvents (on, config) {
const devServer = require('@cypress/react/plugins/next')
devServer(on, config)
return config
},
},
}

View File

@@ -1,10 +0,0 @@
const devServer = require('@cypress/react/plugins/next')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
return config
}

View File

@@ -8,4 +8,13 @@ module.exports = {
'env': {
'coverage': true,
},
'component': {
setupNodeEvents (on, config) {
const devServer = require('@cypress/react/plugins/next')
devServer(on, config)
return config
},
},
}

View File

@@ -1,10 +0,0 @@
const devServer = require('@cypress/react/plugins/next')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
return config
}

View File

@@ -5,4 +5,17 @@ module.exports = {
'viewportWidth': 500,
'viewportHeight': 800,
'componentFolder': 'cypress/component',
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,16 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -4,4 +4,13 @@ module.exports = {
'viewportWidth': 500,
'viewportHeight': 800,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
return config
},
},
}

View File

@@ -1,10 +0,0 @@
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
return config
}

View File

@@ -5,4 +5,17 @@ module.exports = {
'viewportHeight': 800,
'experimentalFetchPolyfill': true,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,16 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -9,4 +9,19 @@ module.exports = {
'env': {
'coverage': true,
},
'component': {
setupNodeEvents (on, config) {
// load Webpack file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/load-webpack')
devServer(on, config, {
webpackFilename: 'webpack.config.js',
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,18 +0,0 @@
// @ts-check
// load Webpack file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/load-webpack')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config, {
webpackFilename: 'webpack.config.js',
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -13,4 +13,21 @@ module.exports = {
'prettier': true,
},
},
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
const { initPlugin: initSnapshots } = require('cypress-plugin-snapshots/plugin')
devServer(on, config)
// initialize the snapshots plugin following
// https://github.com/meinaart/cypress-plugin-snapshots
initSnapshots(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,20 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
const { initPlugin: initSnapshots } = require('cypress-plugin-snapshots/plugin')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// initialize the snapshots plugin following
// https://github.com/meinaart/cypress-plugin-snapshots
initSnapshots(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -8,4 +8,17 @@ module.exports = {
'env': {
'coverage': true,
},
config: {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,16 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -5,4 +5,18 @@ module.exports = {
'viewportWidth': 500,
'viewportHeight': 500,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
// let's bundle spec files and the components they include using
// the same bundling settings as the project by loading .babelrc
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/babel')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,17 +0,0 @@
// @ts-check
// let's bundle spec files and the components they include using
// the same bundling settings as the project by loading .babelrc
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/babel')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -5,4 +5,18 @@ module.exports = {
'viewportWidth': 500,
'viewportHeight': 500,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
// let's bundle spec files and the components they include using
// the same bundling settings as the project by loading .babelrc
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/babel')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,17 +0,0 @@
// @ts-check
// let's bundle spec files and the components they include using
// the same bundling settings as the project by loading .babelrc
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/babel')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -4,5 +4,19 @@ module.exports = {
"testFiles": "**/*cy-spec.js",
"viewportWidth": 1000,
"viewportHeight": 1000,
"componentFolder": "src"
}
"componentFolder": "src",
'component': {
setupNodeEvents(on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin')
addMatchImageSnapshotPlugin(on, config)
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}
}
}

View File

@@ -1,17 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
addMatchImageSnapshotPlugin(on, config)
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -8,4 +8,19 @@ module.exports = {
'env': {
'coverage': false,
},
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}
require('@applitools/eyes-cypress')(module)

View File

@@ -1,19 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}
// @ts-ignore
require('@applitools/eyes-cypress')(module)

View File

@@ -4,4 +4,19 @@ module.exports = {
'viewportWidth': 400,
'viewportHeight': 700,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
const happoTask = require('happo-cypress/task')
on('task', happoTask)
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,19 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const devServer = require('@cypress/react/plugins/react-scripts')
// @ts-ignore
const happoTask = require('happo-cypress/task')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
on('task', happoTask)
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -5,4 +5,17 @@ module.exports = {
'viewportWidth': 500,
'viewportHeight': 500,
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
// load file devServer that comes with this plugin
// https://github.com/bahmutov/@cypress/react#install
const devServer = require('@cypress/react/plugins/react-scripts')
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,16 +0,0 @@
// @ts-check
// load file devServer that comes with this plugin
// https://github.com/bahmutov/@cypress/react#install
const devServer = require('@cypress/react/plugins/react-scripts')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
devServer(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -4,4 +4,16 @@ module.exports = {
'testFiles': '**/*cy-spec.js',
'viewportWidth': 500,
'viewportHeight': 500,
'component': {
setupNodeEvents (on, config) {
require('@cypress/react/plugins/load-webpack')(on, config, {
// from the root of the project (folder with cypress.config.{ts|js} file)
webpackFilename: 'webpack.config.js',
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
},
},
}

View File

@@ -1,15 +0,0 @@
// @ts-check
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
require('@cypress/react/plugins/load-webpack')(on, config, {
// from the root of the project (folder with cypress.config.{ts|js} file)
webpackFilename: 'webpack.config.js',
})
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}

View File

@@ -4,4 +4,40 @@ module.exports = {
'testFiles': '**/*cy-spec.js',
'viewportWidth': 500,
'viewportHeight': 500,
'component': {
setupNodeEvents (on, config) {
const path = require('path')
const { startDevServer } = require('@cypress/webpack-dev-server')
const babelConfig = require('./babel.config')
/** @type import("webpack").Configuration */
const webpackConfig = {
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
mode: 'development',
devtool: false,
output: {
publicPath: '/',
chunkFilename: '[name].bundle.js',
},
// TODO: update with valid configuration for your components
module: {
rules: [
{
test: /\.(js|jsx|mjs|ts|tsx)$/,
loader: 'babel-loader',
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '.babel-cache') },
},
],
},
}
process.env.BABEL_ENV = 'test' // this is required to load commonjs babel plugin
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
// if adding code coverage, important to return updated config
return config
},
},
}

View File

@@ -1,40 +0,0 @@
// @ts-check
const path = require('path')
const { startDevServer } = require('@cypress/webpack-dev-server')
const babelConfig = require('../../babel.config')
/**
* Cypress Webpack devServer includes Babel env preset,
* but to transpile JSX code we need to add Babel React preset
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
/** @type import("webpack").Configuration */
const webpackConfig = {
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
mode: 'development',
devtool: false,
output: {
publicPath: '/',
chunkFilename: '[name].bundle.js',
},
// TODO: update with valid configuration for your components
module: {
rules: [
{
test: /\.(js|jsx|mjs|ts|tsx)$/,
loader: 'babel-loader',
options: { ...babelConfig, cacheDirectory: path.resolve(__dirname, '.babel-cache') },
},
],
},
}
process.env.BABEL_ENV = 'test' // this is required to load commonjs babel plugin
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
// if adding code coverage, important to return updated config
return config
}

View File

@@ -6,4 +6,21 @@ export default defineConfig({
'fixturesFolder': false,
'testFiles': '**/*.spec.*',
'componentFolder': 'cypress/components',
'component': {
setupNodeEvents (on, config) {
const path = require('path')
const { startDevServer } = require('./dist')
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
configFile: path.resolve(__dirname, 'vite.config.ts'),
},
})
})
return config
},
},
})

View File

@@ -1,15 +0,0 @@
const path = require('path')
const { startDevServer } = require('../dist')
module.exports = (on, config) => {
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
configFile: path.resolve(__dirname, '..', 'vite.config.ts'),
},
})
})
return config
}

View File

@@ -8,4 +8,24 @@ export default defineConfig({
'projectId': '134ej7',
'testFiles': '**/*spec.{js,ts,tsx}',
'experimentalFetchPolyfill': true,
'component': {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('./webpack.config')
if (!webpackConfig.resolve) {
webpackConfig.resolve = {}
}
webpackConfig.resolve.alias = {
...webpackConfig.resolve.alias,
'@vue/compiler-core$': '@vue/compiler-core/dist/compiler-core.cjs.js',
}
require('@cypress/code-coverage/task')(on, config)
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
return config
},
},
})

View File

@@ -1,26 +0,0 @@
/// <reference types="cypress" />
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('../../webpack.config')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
if (config.testingType !== 'component') {
return config
}
if (!webpackConfig.resolve) {
webpackConfig.resolve = {}
}
webpackConfig.resolve.alias = {
...webpackConfig.resolve.alias,
'@vue/compiler-core$': '@vue/compiler-core/dist/compiler-core.cjs.js',
}
require('@cypress/code-coverage/task')(on, config)
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))
return config
}

View File

@@ -3,4 +3,21 @@ module.exports = {
'fixturesFolder': false,
'testFiles': '**/*.spec.js',
'video': false,
'component': {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('./webpack.config')
on('dev-server:start', (options) => {
return startDevServer({
options,
webpackConfig,
})
})
require('@cypress/code-coverage/task')(on, config)
return config
},
},
}

View File

@@ -1,19 +0,0 @@
/// <reference types="cypress" />
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('../../webpack.config')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
on('dev-server:start', (options) => {
return startDevServer({
options,
webpackConfig,
})
})
require('@cypress/code-coverage/task')(on, config)
return config
}

View File

@@ -3,4 +3,33 @@ module.exports = {
'fixturesFolder': false,
'testFiles': '**/*spec.js',
'componentFolder': 'src',
'component': {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('@vue/cli-service/webpack.config')
on('dev-server:start', (options) => {
// HtmlPwaPlugin is coupled to a hook in HtmlWebpackPlugin
// that was deprecated after 3.x. We currently only support
// HtmlWebpackPlugin 4.x and 5.x.
// TODO: Figure out how to deal with 2 major versions old HtmlWebpackPlugin
// which is still in widespread usage.
const modifiedWebpackConfig = {
...webpackConfig,
plugins: (webpackConfig.plugins || []).filter((x) => {
return x.constructor.name !== 'HtmlPwaPlugin'
}),
}
return startDevServer({
options,
webpackConfig: modifiedWebpackConfig,
})
})
require('@cypress/code-coverage/task')(on, config)
return config
},
},
}

View File

@@ -1,31 +0,0 @@
/// <reference types="cypress" />
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('@vue/cli-service/webpack.config')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
on('dev-server:start', (options) => {
// HtmlPwaPlugin is coupled to a hook in HtmlWebpackPlugin
// that was deprecated after 3.x. We currently only support
// HtmlWebpackPlugin 4.x and 5.x.
// TODO: Figure out how to deal with 2 major versions old HtmlWebpackPlugin
// which is still in widespread usage.
const modifiedWebpackConfig = {
...webpackConfig,
plugins: (webpackConfig.plugins || []).filter((x) => {
return x.constructor.name !== 'HtmlPwaPlugin'
}),
}
return startDevServer({
options,
webpackConfig: modifiedWebpackConfig,
})
})
require('@cypress/code-coverage/task')(on, config)
return config
}

View File

@@ -1,3 +1,12 @@
module.exports = {
'integrationFolder': 'cypress/tests',
'e2e': {
setupNodeEvents (on, config) {
const webpackPreprocessor = require('./index')
on('file:preprocessor', webpackPreprocessor())
return config
},
},
}

View File

@@ -1,22 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const webpackPreprocessor = require('../../')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on) => {
on('file:preprocessor', webpackPreprocessor())
}

View File

@@ -1,4 +1,15 @@
module.exports = {
'fixturesFolder': false,
'supportFile': false,
'e2e': {
setupNodeEvents (on, config) {
const webpackPreprocessor = require('../..')
const defaults = webpackPreprocessor.defaultOptions
delete defaults.webpackOptions.module.rules[0].use[0].options.presets
on('file:preprocessor', webpackPreprocessor(defaults))
return config
},
},
}

View File

@@ -1,7 +0,0 @@
const webpackPreprocessor = require('../../../..')
const defaults = webpackPreprocessor.defaultOptions
module.exports = (on) => {
delete defaults.webpackOptions.module.rules[0].use[0].options.presets
on('file:preprocessor', webpackPreprocessor(defaults))
}

View File

@@ -3,4 +3,15 @@ import { defineConfig } from 'cypress'
export default defineConfig({
'fixturesFolder': false,
'supportFile': false,
'e2e': {
async setupNodeEvents (on, config) {
const webpackPreprocessor = await import('../..')
const webpack = await import('./webpack.config')
on('file:preprocessor', webpackPreprocessor({ webpack }))
return config
},
},
})

View File

@@ -1,7 +0,0 @@
const webpackPreprocessor = require('../../../..')
module.exports = (on) => {
const webpack = require('../../webpack.config.js')
on('file:preprocessor', webpackPreprocessor({ webpack }))
}

View File

@@ -20,10 +20,38 @@ export default defineConfig({
'component': {
'testFiles': '**/*.{spec,cy}.{js,ts,tsx,jsx}',
'supportFile': 'cypress/component/support/index.ts',
'pluginsFile': 'cypress/component/plugins/index.js',
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/vite-dev-server')
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
// TODO(tim): Figure out why this isn't being picked up
optimizeDeps: {
include: [
'@headlessui/vue',
'vue3-file-selector',
'just-my-luck',
'combine-properties',
'faker',
],
},
},
})
})
return config
},
},
'e2e': {
'pluginsFile': 'cypress/e2e/plugins/index.ts',
'supportFile': 'cypress/e2e/support/e2eSupport.ts',
async setupNodeEvents (on, config) {
const { monorepoPaths } = require('../../scripts/gulp/monorepoPaths')
const { e2ePluginSetup } = require('@packages/frontend-shared/cypress/e2e/e2ePluginSetup')
return await e2ePluginSetup(monorepoPaths.pkgApp, on, config)
},
},
})

View File

@@ -1,18 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = require('@packages/frontend-shared/cypress/plugins/index')

View File

@@ -58,7 +58,12 @@ describe('App', () => {
cy.loginUser()
cy.visitApp()
cy.withCtx(async (ctx) => {
ctx.config.cleanupCachedConfigForActiveProject()
// TODO: (Alejandro) This should be removed when we add a file listener to update the config file
if (ctx.currentProject) {
ctx.currentProject.config = null
ctx.currentProject.configChildProcess = null
}
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {}')
})

View File

@@ -1,23 +0,0 @@
/// <reference types="cypress" />
const { monorepoPaths } = require('../../../../../scripts/gulp/monorepoPaths')
import { e2ePluginSetup } from '@packages/frontend-shared/cypress/e2e/e2ePluginSetup'
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
module.exports = async (on, config) => {
return await e2ePluginSetup(monorepoPaths.pkgApp, on, config)
}

View File

@@ -1,22 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@@ -1,5 +1,5 @@
import type { DataContext } from '.'
import { AppActions, ElectronActions, FileActions, ProjectActions, WizardActions } from './actions'
import { AppActions, ProjectConfigDataActions, ElectronActions, FileActions, ProjectActions, WizardActions } from './actions'
import { AuthActions } from './actions/AuthActions'
import { DevActions } from './actions/DevActions'
import { cached } from './util'
@@ -41,4 +41,9 @@ export class DataActions {
get electron () {
return new ElectronActions(this.ctx)
}
@cached
get projectConfig () {
return new ProjectConfigDataActions(this.ctx)
}
}

View File

@@ -17,7 +17,7 @@ import {
BrowserDataSource,
StorybookDataSource,
CloudDataSource,
ConfigDataSource,
ProjectConfigDataSource,
EnvDataSource,
GraphQLDataSource,
HtmlDataSource,
@@ -42,7 +42,7 @@ export interface DataContextConfig {
os: PlatformName
launchArgs: LaunchArgs
launchOptions: OpenProjectLaunchOptions
electronApp: ElectronApp
electronApp?: ElectronApp
/**
* Default is to
*/
@@ -91,6 +91,8 @@ export class DataContext {
this.actions.app.refreshBrowsers(),
// load the cached user & validate the token on start
this.actions.auth.getUser(),
this.actions.app.refreshNodePathAndVersion(),
]
if (this._config._internalOptions.loadCachedProjects) {
@@ -153,6 +155,10 @@ export class DataContext {
return this.coreData.app.browsers
}
get nodePathAndVersion () {
return this.coreData.app.nodePathAndVersion
}
get baseError () {
return this.coreData.baseError
}
@@ -196,7 +202,7 @@ export class DataContext {
@cached
get config () {
return new ConfigDataSource(this)
return new ProjectConfigDataSource(this)
}
@cached

View File

@@ -1,5 +1,5 @@
import type Bluebird from 'bluebird'
import type { FoundBrowser } from '@packages/types'
import type { FoundBrowser, NodePathAndVersion } from '@packages/types'
import pDefer from 'p-defer'
import type { DataContext } from '..'
@@ -7,6 +7,7 @@ import type { DataContext } from '..'
export interface AppApiShape {
getBrowsers(): Promise<FoundBrowser[]>
ensureAndGetByNameOrPath(nameOrPath: string, returnAll?: boolean, browsers?: FoundBrowser[]): Bluebird<FoundBrowser | FoundBrowser[] | undefined>
findNodePathAndVersion(): Promise<{ path: string, version: string}>
}
export class AppActions {
@@ -85,4 +86,20 @@ export class AppActions {
return browsers.some((b) => this.idForBrowser(b) === this.idForBrowser(chosenBrowser))
}
async refreshNodePathAndVersion () {
if (this.ctx.coreData.app.refreshingNodePathAndVersion) {
return
}
const dfd = pDefer<NodePathAndVersion>()
this.ctx.coreData.app.refreshingNodePathAndVersion = dfd.promise
const nodePathAndVersion = await this.ctx._apis.appApi.findNodePathAndVersion()
this.ctx.coreData.app.nodePathAndVersion = nodePathAndVersion
dfd.resolve(nodePathAndVersion)
}
}

View File

@@ -25,7 +25,7 @@ export class ElectronActions {
this.electron.browserWindow?.hide()
if (this.isMac) {
this.ctx.electronApp.dock.hide()
this.ctx.electronApp?.dock.hide()
} else {
this.electron.browserWindow?.setSkipTaskbar(true)
}
@@ -35,7 +35,7 @@ export class ElectronActions {
this.electron.browserWindow?.show()
if (this.isMac) {
this.ctx.electronApp.dock.show()
this.ctx.electronApp?.dock.show()
} else {
this.electron.browserWindow?.setSkipTaskbar(false)
}

View File

@@ -26,7 +26,10 @@ export interface ProjectApiShape {
clearProjectPreferences(projectTitle: string): Promise<unknown>
clearAllProjectPreferences(): Promise<unknown>
closeActiveProject(): Promise<unknown>
error(type: string, ...args: any): Error
error: {
throw: (type: string, ...args: any) => Error
get(type: string, ...args: any): Error & { code: string, isCypressErr: boolean}
}
}
export class ProjectActions {
@@ -37,7 +40,7 @@ export class ProjectActions {
}
async clearActiveProject () {
this.ctx.coreData.currentProject = null
this.ctx.actions.projectConfig.killConfigProcess()
await this.api.closeActiveProject()
// TODO(tim): Improve general state management w/ immutability (immer) & updater fn
@@ -77,7 +80,24 @@ export class ProjectActions {
return this
}
private setCurrentProjectProperties (currentProjectProperties: Partial<ActiveProjectShape>) {
// Temporary: remove after other refactor lands
setActiveProjectForTestSetup (projectRoot: string) {
this.ctx.actions.projectConfig.killConfigProcess()
const title = this.ctx.project.projectTitle(projectRoot)
// Set initial properties, so we can set the config object on the active project
this.setCurrentProjectProperties({
projectRoot,
title,
ctPluginsInitialized: false,
e2ePluginsInitialized: false,
config: null,
configChildProcess: null,
})
}
setCurrentProjectProperties (currentProjectProperties: Partial<ActiveProjectShape>) {
this.ctx.coreData.currentProject = {
browsers: this.ctx.coreData.app.browsers,
...this.ctx.coreData.currentProject,

View File

@@ -0,0 +1,142 @@
import childProcess, { ChildProcess, ForkOptions } from 'child_process'
import _ from 'lodash'
import path from 'path'
import { EventEmitter } from 'events'
import pDefer from 'p-defer'
import type { DataContext } from '..'
import inspector from 'inspector'
interface ForkConfigProcessOptions {
projectRoot: string
configFilePath: string
}
/**
* Manages the lifecycle of the Config sourcing & Plugin execution
*/
export class ProjectConfigDataActions {
constructor (private ctx: DataContext) {}
static CHILD_PROCESS_FILE_PATH = path.join(__dirname, '../../../server/lib/util', 'require_async_child.js')
killConfigProcess () {
if (this.ctx.currentProject?.configChildProcess) {
this.ctx.currentProject.configChildProcess.process.kill()
this.ctx.currentProject.configChildProcess = null
}
}
refreshProjectConfig (configFilePath: string) {
if (!this.ctx.currentProject) {
throw new Error('Can\'t refresh project config without current project')
}
this.killConfigProcess()
const process = this.forkConfigProcess({
projectRoot: this.ctx.currentProject.projectRoot,
configFilePath,
})
const dfd = pDefer<Cypress.ConfigOptions>()
this.ctx.currentProject.configChildProcess = {
process,
executedPlugins: null,
resolvedBaseConfig: dfd.promise,
}
this.wrapConfigProcess(process, dfd)
return dfd.promise as Cypress.ConfigOptions
}
private forkConfigProcess (opts: ForkConfigProcessOptions) {
const configProcessArgs = ['--projectRoot', opts.projectRoot, '--file', opts.configFilePath]
const childOptions: ForkOptions = {
stdio: 'pipe',
cwd: path.dirname(opts.configFilePath),
env: {
...process.env,
NODE_OPTIONS: process.env.ORIGINAL_NODE_OPTIONS || '',
},
execPath: this.ctx.nodePathAndVersion?.path,
}
if (inspector.url()) {
childOptions.execArgv = _.chain(process.execArgv.slice(0))
.remove('--inspect-brk')
.push(`--inspect=${process.debugPort + 1}`)
.value()
}
this.ctx.debug('fork child process', ProjectConfigDataActions.CHILD_PROCESS_FILE_PATH, configProcessArgs, childOptions)
return childProcess.fork(ProjectConfigDataActions.CHILD_PROCESS_FILE_PATH, configProcessArgs, childOptions)
}
private wrapConfigProcess (child: ChildProcess, dfd: pDefer.DeferredPromise<Cypress.ConfigOptions>) {
const ipc = this.wrapIpc(child)
if (child.stdout && child.stderr) {
// manually pipe plugin stdout and stderr for dashboard capture
// @see https://github.com/cypress-io/cypress/issues/7434
child.stdout.on('data', (data) => process.stdout.write(data))
child.stderr.on('data', (data) => process.stderr.write(data))
}
ipc.on('loaded', (result) => {
this.ctx.debug('resolving with result %o', result)
dfd.resolve(result)
})
ipc.on('load:error', (type, ...args) => {
this.ctx.debug('load:error %s, rejecting', type)
this.killConfigProcess()
const err = this.ctx._apis.projectApi.error.get(type, ...args)
// if it's a non-cypress error, restore the initial error
if (!(err.message?.length)) {
err.isCypressErr = false
err.message = args[1]
err.code = type
err.name = type
}
dfd.reject(err)
})
this.ctx.debug('trigger the load of the file')
ipc.send('load')
}
protected wrapIpc (aProcess: ChildProcess) {
const emitter = new EventEmitter()
aProcess.on('message', (message: { event: string, args: any}) => {
return emitter.emit(message.event, ...message.args)
})
// prevent max listeners warning on ipc
// @see https://github.com/cypress-io/cypress/issues/1305#issuecomment-780895569
emitter.setMaxListeners(Infinity)
return {
send (event: string, ...args: any) {
if (aProcess.killed) {
return
}
return aProcess.send({
event,
args,
})
},
on: emitter.on.bind(emitter),
removeListener: emitter.removeListener.bind(emitter),
}
}
}

View File

@@ -8,4 +8,5 @@ export * from './DevActions'
export * from './ElectronActions'
export * from './FileActions'
export * from './ProjectActions'
export * from './ProjectConfigDataActions'
export * from './WizardActions'

View File

@@ -1,4 +1,4 @@
import { BUNDLERS, FoundBrowser, FoundSpec, FullConfig, Preferences } from '@packages/types'
import { BUNDLERS, FoundBrowser, FoundSpec, FullConfig, Preferences, NodePathAndVersion } from '@packages/types'
import type { NexusGenEnums, TestingTypeEnum } from '@packages/graphql/src/gen/nxs.gen'
import type { BrowserWindow } from 'electron'
import type { ChildProcess } from 'child_process'
@@ -20,8 +20,18 @@ export interface DevStateShape {
}
export interface ConfigChildProcessShape {
/**
* Child process executing the config & sourcing plugin events
*/
process: ChildProcess
/**
* Keeps track of which plugins we have executed in the current config process
*/
executedPlugins: null | 'e2e' | 'ct'
/**
* Config from the initial module.exports
*/
resolvedBaseConfig: Promise<Cypress.ConfigOptions>
}
export interface ActiveProjectShape extends ProjectShape {
@@ -32,7 +42,7 @@ export interface ActiveProjectShape extends ProjectShape {
isE2EConfigured: Maybe<boolean>
specs?: FoundSpec[]
config: Promise<FullConfig> | null
configChildProcess: ConfigChildProcessShape | null
configChildProcess?: ConfigChildProcessShape | null
preferences?: Preferences| null
browsers: FoundBrowser[] | null
}
@@ -42,6 +52,8 @@ export interface AppDataShape {
projects: ProjectShape[]
currentTestingType: Maybe<TestingTypeEnum>
refreshingBrowsers: Promise<FoundBrowser[]> | null
refreshingNodePathAndVersion: Promise<NodePathAndVersion> | null
nodePathAndVersion: NodePathAndVersion | null
}
export interface WizardDataShape {
@@ -92,6 +104,8 @@ export function makeCoreData (): CoreDataShape {
refreshingBrowsers: null,
browsers: null,
projects: [],
refreshingNodePathAndVersion: null,
nodePathAndVersion: null,
},
isAuthBrowserOpened: false,
currentProject: null,

View File

@@ -1,9 +1,28 @@
import type { FullConfig } from '@packages/types'
import path from 'path'
import type { DataContext } from '..'
export class ConfigDataSource {
export class ProjectConfigDataSource {
constructor (private ctx: DataContext) {}
async getOrCreateBaseConfig (configFilePath?: string) {
const configChildProcess = this.ctx.currentProject?.configChildProcess
if (!configChildProcess) {
if (!configFilePath) {
configFilePath = await this.getConfigFilePath()
}
if (!this.ctx.nodePathAndVersion) {
await this.ctx.actions.app.refreshNodePathAndVersion()
}
return this.ctx.deref.actions.projectConfig.refreshProjectConfig(configFilePath)
}
return configChildProcess.resolvedBaseConfig
}
async getConfigForProject (projectRoot: string): Promise<FullConfig> {
if (!this.ctx.coreData.currentProject) {
throw new Error(`Cannot access config without currentProject`)
@@ -31,8 +50,12 @@ export class ConfigDataSource {
if (foundConfigFiles.length === 1) {
const configFile = foundConfigFiles[0]
if (!configFile) {
throw this.ctx._apis.projectApi.error.throw('NO_DEFAULT_CONFIG_FILE_FOUND', projectRoot)
}
if (configFile === legacyConfigFile) {
throw this.ctx._apis.projectApi.error('CONFIG_FILE_MIGRATION_NEEDED', projectRoot, configFile)
throw this.ctx._apis.projectApi.error.throw('CONFIG_FILE_MIGRATION_NEEDED', projectRoot, configFile)
}
return configFile
@@ -43,20 +66,24 @@ export class ConfigDataSource {
if (foundConfigFiles.includes(legacyConfigFile)) {
const foundFiles = foundConfigFiles.filter((f) => f !== legacyConfigFile)
throw this.ctx._apis.projectApi.error('LEGACY_CONFIG_FILE', projectRoot, ...foundFiles)
throw this.ctx._apis.projectApi.error.throw('LEGACY_CONFIG_FILE', projectRoot, ...foundFiles)
}
throw this.ctx._apis.projectApi.error('CONFIG_FILES_LANGUAGE_CONFLICT', projectRoot, ...foundConfigFiles)
throw this.ctx._apis.projectApi.error.throw('CONFIG_FILES_LANGUAGE_CONFLICT', projectRoot, ...foundConfigFiles)
}
throw this.ctx._apis.projectApi.error('NO_DEFAULT_CONFIG_FILE_FOUND', projectRoot)
throw this.ctx._apis.projectApi.error.throw('NO_DEFAULT_CONFIG_FILE_FOUND', projectRoot)
}
async cleanupCachedConfigForActiveProject () {
if (!this.ctx.coreData.currentProject?.config) {
return
protected async getConfigFilePath () {
const projectRoot = this.ctx.currentProject?.projectRoot
if (!projectRoot) {
throw new Error('Can\'t het the config file path without current project root')
}
this.ctx.coreData.currentProject.config = null
const defaultConfigBasename = await this.getDefaultConfigBasename(projectRoot)
return path.join(projectRoot, defaultConfigBasename)
}
}

View File

@@ -3,12 +3,12 @@
export * from './BrowserDataSource'
export * from './CloudDataSource'
export * from './ConfigDataSource'
export * from './EnvDataSource'
export * from './FileDataSource'
export * from './GitDataSource'
export * from './GraphQLDataSource'
export * from './HtmlDataSource'
export * from './ProjectConfigDataSource'
export * from './ProjectDataSource'
export * from './SettingsDataSource'
export * from './StorybookDataSource'

View File

@@ -18,4 +18,30 @@ module.exports = {
'reporterOptions': {
'configFile': '../../mocha-reporter-config.json',
},
'e2e': {
setupNodeEvents (on, config) {
const express = require('express')
express().use(express.static('dist')).listen(5005)
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
on('file:preprocessor', webpackPreprocessor())
return config
},
},
'component': {
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackConfig = require('./webpack.config').default
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig })
})
return config
},
},
}

View File

@@ -1,18 +0,0 @@
const express = require('express')
const { startDevServer } = require('@cypress/webpack-dev-server')
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
const webpackConfig = require('../../webpack.config').default
express().use(express.static('dist')).listen(5005)
module.exports = (on, config) => {
if (config.testingType === 'component') {
on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig })
})
} else {
on('file:preprocessor', webpackPreprocessor())
}
return config
}

View File

@@ -2,9 +2,6 @@ import { defineConfig } from 'cypress'
export default defineConfig({
'projectId': 'ypt4pf',
'e2e': {
'baseUrl': 'http://localhost:3500',
},
'testFiles': '**/*',
'hosts': {
'*.foobar.com': '127.0.0.1',
@@ -13,4 +10,8 @@ export default defineConfig({
'reporterOptions': {
'configFile': '../../mocha-reporter-config.json',
},
'e2e': {
'setupNodeEvents': require('./cypress/plugins'),
'baseUrl': 'http://localhost:3500',
},
})

View File

@@ -1,4 +1,5 @@
const { _, Promise } = Cypress
const path = require('path')
describe('src/cy/commands/task', () => {
context('#task', {
@@ -209,7 +210,7 @@ describe('src/cy/commands/task', () => {
expect(lastLog.get('error')).to.eq(err)
expect(lastLog.get('state')).to.eq('failed')
expect(err.message).to.eq(`\`cy.task('bar')\` failed with the following error:\n\nThe task 'bar' was not handled in the plugins file. The following tasks are registered: return:arg, arg:is:undefined, wait, create:long:file\n\nFix this in your plugins file here:\n${Cypress.config('pluginsFile')}`)
expect(err.message).to.eq(`\`cy.task('bar')\` failed with the following error:\n\nThe task 'bar' was not handled in the setupNodeEvents method. The following tasks are registered: return:arg, arg:is:undefined, wait, create:long:file\n\nFix this in your setupNodeEvents method here:\n${path.join(Cypress.config('projectRoot'), Cypress.config('configFile'))}`)
done()
})

View File

@@ -31,7 +31,7 @@ babelLoader.use.options.plugins = _.reject(babelLoader.use.options.plugins, (plu
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on) => {
module.exports = (on, config) => {
on('file:preprocessor', wp({ webpackOptions }))
on('task', {
@@ -59,4 +59,6 @@ module.exports = (on) => {
return null
},
})
return config
}

View File

@@ -18,6 +18,34 @@ export default defineConfig({
'componentFolder': 'src',
'component': {
'testFiles': '**/*.spec.{js,ts,tsx,jsx}',
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/vite-dev-server')
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
if (config.testingType === 'component') {
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
// TODO(tim): Figure out why this isn't being picked up
optimizeDeps: {
include: [
'@headlessui/vue',
'vue3-file-selector',
'just-my-luck',
'combine-properties',
'faker',
],
},
},
})
})
}
return config // IMPORTANT to return a config
},
},
'e2e': {
'supportFile': 'cypress/e2e/support/e2eSupport.ts',

View File

@@ -1,48 +0,0 @@
/**
* @type {import('@cypress/vite-dev-server')}
*/
const { startDevServer } = require('@cypress/vite-dev-server')
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
if (config.testingType === 'component') {
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
// TODO(tim): Figure out why this isn't being picked up
optimizeDeps: {
include: [
'@headlessui/vue',
'vue3-file-selector',
'just-my-luck',
'combine-properties',
'faker',
],
},
},
})
})
}
return config // IMPORTANT to return a config
}

View File

@@ -29,8 +29,8 @@ export const mutation = mutationType({
t.field('internal_clearLatestProjectCache', {
type: 'Boolean',
resolve: (_, args, ctx) => {
ctx.actions.project.clearLatestProjectCache()
resolve: async (_, args, ctx) => {
await ctx.actions.project.clearLatestProjectCache()
return true
},
@@ -53,8 +53,8 @@ export const mutation = mutationType({
args: {
projectTitle: nonNull(stringArg()),
},
resolve: (_, args, ctx) => {
ctx.actions.project.clearProjectPreferencesCache(args.projectTitle)
resolve: async (_, args, ctx) => {
await ctx.actions.project.clearProjectPreferencesCache(args.projectTitle)
return true
},
@@ -62,8 +62,8 @@ export const mutation = mutationType({
t.field('internal_clearAllProjectPreferencesCache', {
type: 'Boolean',
resolve: (_, args, ctx) => {
ctx.actions.project.clearAllProjectPreferencesCache()
resolve: async (_, args, ctx) => {
await ctx.actions.project.clearAllProjectPreferencesCache()
return true
},

View File

@@ -1,4 +1,7 @@
export default {
import { defineConfig } from 'cypress'
import { e2ePluginSetup } from '@packages/frontend-shared/cypress/e2e/e2ePluginSetup'
export default defineConfig({
'projectId': 'sehy69',
'viewportWidth': 800,
'viewportHeight': 850,
@@ -17,10 +20,43 @@ export default {
'testFiles': '**/*.spec.{js,ts,tsx,jsx}',
'supportFile': 'cypress/component/support/index.ts',
'pluginsFile': 'cypress/component/plugins/index.js',
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/vite-dev-server')
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
if (config.testingType === 'component') {
on('dev-server:start', async (options) => {
return startDevServer({
options,
viteConfig: {
// TODO(tim): Figure out why this isn't being picked up
optimizeDeps: {
include: [
'@headlessui/vue',
'vue3-file-selector',
'just-my-luck',
'combine-properties',
'faker',
],
},
},
})
})
}
return config // IMPORTANT to return a config
},
},
'e2e': {
'supportFile': 'cypress/e2e/support/e2eSupport.ts',
'integrationFolder': 'cypress/e2e/integration',
'pluginsFile': 'cypress/e2e/plugins/index.ts',
async setupNodeEvents (on, config) {
const { monorepoPaths } = require('../../scripts/gulp/monorepoPaths')
return await e2ePluginSetup(monorepoPaths.pkgLaunchpad, on, config)
},
},
}
})

View File

@@ -1,18 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = require('@packages/frontend-shared/cypress/plugins/index')

View File

@@ -12,7 +12,7 @@ describe('Plugin error handling', () => {
.and('contain.text', 'The function exported by the plugins file threw an error')
cy.withCtx(async (ctx) => {
await ctx.actions.file.writeFileInProject('cypress/plugins/index.js', `module.exports = (on, config) => {}`)
await ctx.actions.file.writeFileInProject('cypress.config.js', `module.exports = { e2e: { baseUrl: 'https://cypress.com' } }`)
})
cy.get('[data-testid=error-retry-button]').click()

View File

@@ -1,23 +0,0 @@
/// <reference types="cypress" />
const { monorepoPaths } = require('../../../../../scripts/gulp/monorepoPaths')
import { e2ePluginSetup } from '@packages/frontend-shared/cypress/e2e/e2ePluginSetup'
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
export default async (on, config) => {
return await e2ePluginSetup(monorepoPaths.pkgLaunchpad, on, config)
}

View File

@@ -13,4 +13,13 @@ export default defineConfig({
'runMode': 2,
'openMode': 0,
},
'e2e': {
setupNodeEvents (on, config) {
const express = require('express')
express().use(express.static('dist')).listen(5006)
return config
},
},
})

View File

@@ -1,12 +0,0 @@
// const cp = require('child_process')
// cp.exec('http-server -p 5006 dist')
const express = require('express')
express().use(express.static('dist')).listen(5006)
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on: Function) => {
}

View File

@@ -12,5 +12,36 @@ export default defineConfig({
},
component: {
testFiles: '**/*spec.{ts,tsx}',
setupNodeEvents (on, config) {
const { startDevServer } = require('@cypress/webpack-dev-server')
function injectStylesInlineForPercyInPlace (webpackConfig) {
webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => {
if (rule?.use[0]?.loader.includes('mini-css-extract-plugin')) {
return {
...rule,
use: [{
loader: 'style-loader',
}],
}
}
return rule
})
}
on('dev-server:start', (options) => {
const { default: webpackConfig } = require('./webpack.config.ts')
injectStylesInlineForPercyInPlace(webpackConfig)
return startDevServer({
webpackConfig,
options,
})
})
return config
},
},
})

View File

@@ -1,36 +0,0 @@
/// <reference types="cypress" />
const path = require('path')
const { startDevServer } = require('@cypress/webpack-dev-server')
function injectStylesInlineForPercyInPlace (webpackConfig) {
webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => {
if (rule?.use[0]?.loader.includes('mini-css-extract-plugin')) {
return {
...rule,
use: [{
loader: 'style-loader',
}],
}
}
return rule
})
}
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
on('dev-server:start', (options) => {
/** @type {import('webpack').Configuration} */
const { default: webpackConfig } = require(path.resolve(__dirname, '..', '..', 'webpack.config.ts'))
injectStylesInlineForPercyInPlace(webpackConfig)
return startDevServer({
webpackConfig,
options,
})
})
return config
}

View File

@@ -12,4 +12,7 @@ module.exports = {
'reporterOptions': {
'configFile': '../../mocha-reporter-config.json',
},
'e2e': {
'setupNodeEvents': require('./cypress/plugins'),
},
}

View File

@@ -1,20 +1,3 @@
exports['lib/plugins/child/run_plugins sends error message if pluginsFile is missing 1'] = `
Error: Cannot find module '/does/not/exist.coffee'
`
exports['lib/plugins/child/run_plugins sends error message if requiring pluginsFile errors 1'] = `
Error: error thrown by pluginsFile
`
exports['lib/plugins/child/run_plugins sends error message if pluginsFile has syntax error 1'] = `
<path>syntax_error.js)
SyntaxError: Unexpected end of input
[stack trace]
`
exports['lib/plugins/child/run_plugins sends error message if pluginsFile does not export a function 1'] = `
null
exports['lib/plugins/child/run_plugins sends error message if setupNodeEvents is not a function 1'] = `
plugins-file
`

View File

@@ -93,19 +93,6 @@ exports['lib/scaffold .fileTree returns tree-like structure of scaffolded 1'] =
}
]
},
{
"name": "cypress",
"children": [
{
"name": "plugins",
"children": [
{
"name": "index.js"
}
]
}
]
}
]
exports['lib/scaffold .fileTree leaves out integration tests if using component testing 1'] = [
@@ -203,19 +190,6 @@ exports['lib/scaffold .fileTree leaves out integration tests if using component
}
]
},
{
"name": "cypress",
"children": [
{
"name": "plugins",
"children": [
{
"name": "index.js"
}
]
}
]
}
]
exports['lib/scaffold .fileTree leaves out fixtures if configured to false 1'] = [
@@ -305,19 +279,6 @@ exports['lib/scaffold .fileTree leaves out fixtures if configured to false 1'] =
}
]
},
{
"name": "cypress",
"children": [
{
"name": "plugins",
"children": [
{
"name": "index.js"
}
]
}
]
}
]
exports['lib/scaffold .fileTree leaves out support if configured to false 1'] = [
@@ -404,19 +365,6 @@ exports['lib/scaffold .fileTree leaves out support if configured to false 1'] =
}
]
},
{
"name": "cypress",
"children": [
{
"name": "plugins",
"children": [
{
"name": "index.js"
}
]
}
]
}
]
exports['lib/scaffold .support creates supportFolder and commands.js and index.js when supportFolder does not exist 1'] = `

View File

@@ -18,6 +18,7 @@ const debug = Debug('cypress:server:config')
import { options, breakingOptions } from './config_options'
import { getProcessEnvVars, CYPRESS_SPECIAL_ENV_VARS } from './util/config'
import type { DataContext } from '@packages/data-context'
const dashesOrUnderscoresRe = /^(_-)+/
@@ -185,9 +186,13 @@ export type FullConfig =
resolved: ResolvedConfigurationOptions
}
export function get (projectRoot, options: {configFile?: string | false } = { configFile: undefined }): Promise<FullConfig> {
export function get (
projectRoot,
options: { configFile?: string | false } = { configFile: undefined },
ctx: DataContext,
): Promise<FullConfig> {
return Promise.all([
settings.read(projectRoot, options).then(validateFile(options.configFile ?? 'cypress.config.{ts|js}')),
settings.read(projectRoot, options, ctx).then(validateFile(options.configFile ?? 'cypress.config.{ts|js}')),
settings.readEnv(projectRoot).then(validateFile('cypress.env.json')),
])
.spread((settings, envFile) => {
@@ -298,7 +303,6 @@ export function mergeDefaults (config: Record<string, any> = {}, options: Record
validateNoBreakingConfig(config)
return setSupportFileAndFolder(config)
.then(setPluginsFile)
.then(setScaffoldPaths)
.then(_.partialRight(setNodeBinary, options.onWarning))
}
@@ -342,10 +346,10 @@ export function updateWithPluginValues (cfg, overrides) {
// make sure every option returned from the plugins file
// passes our validation functions
validate(overrides, (errMsg) => {
if (cfg.pluginsFile && cfg.projectRoot) {
const relativePluginsPath = path.relative(cfg.projectRoot, cfg.pluginsFile)
if (cfg.configFile && cfg.projectRoot) {
const relativeConfigPath = path.relative(cfg.projectRoot, cfg.configFile)
return errors.throw('PLUGINS_CONFIG_VALIDATION_ERROR', relativePluginsPath, errMsg)
return errors.throw('PLUGINS_CONFIG_VALIDATION_ERROR', relativeConfigPath, errMsg)
}
return errors.throw('CONFIG_VALIDATION_ERROR', errMsg)
@@ -553,63 +557,6 @@ export function setSupportFileAndFolder (obj) {
})
}
// set pluginsFile to an absolute path with the following rules:
// - do nothing if pluginsFile is falsey
// - look up the absolute path via node, so 'cypress/plugins' can resolve
// to 'cypress/plugins/index.js' or 'cypress/plugins/index.coffee'
// - if not found
// * and the pluginsFile is set to the default
// - and the path to the pluginsFile directory exists
// * assume the user doesn't need a pluginsFile, set it to false
// so it's ignored down the pipeline
// - and the path to the pluginsFile directory does not exist
// * set it to cypress/plugins/index.js, it will get scaffolded
// * and the pluginsFile is NOT set to the default
// - throw an error, because it should be there if the user
// explicitly set it
export const setPluginsFile = Promise.method((obj) => {
if (!obj.pluginsFile) {
return obj
}
obj = _.clone(obj)
const {
pluginsFile,
} = obj
debug(`setting plugins file ${pluginsFile}`)
debug(`for project root ${obj.projectRoot}`)
return Promise
.try(() => {
// resolve full path with extension
obj.pluginsFile = utils.resolveModule(pluginsFile)
return debug(`set pluginsFile to ${obj.pluginsFile}`)
}).catch({ code: 'MODULE_NOT_FOUND' }, () => {
debug('plugins module does not exist %o', { pluginsFile })
const isLoadingDefaultPluginsFile = pluginsFile === path.resolve(obj.projectRoot, defaultValues.pluginsFile)
return utils.discoverModuleFile({
filename: pluginsFile,
isDefault: isLoadingDefaultPluginsFile,
projectRoot: obj.projectRoot,
})
.then((result) => {
if (result === null) {
return errors.throw('PLUGINS_FILE_ERROR', path.resolve(obj.projectRoot, pluginsFile))
}
debug('setting plugins file to %o', { result })
obj.pluginsFile = result
return obj
})
}).return(obj)
})
export function setParentTestsPaths (obj) {
// projectRoot: "/path/to/project"
// integrationFolder: "/path/to/project/cypress/integration"

View File

@@ -559,34 +559,19 @@ const getMsgByType = function (type, arg1 = {}, arg2, arg3) {
Or you might have renamed the extension of your \`supportFile\` to \`.ts\`. If that's the case, restart the test runner.
Learn more at https://on.cypress.io/support-file-missing-or-invalid`
case 'PLUGINS_FILE_ERROR':
case 'SETUP_NODE_EVENTS_IS_NOT_FUNCTION':
msg = stripIndent`\
The plugins file is missing or invalid.
Your \`pluginsFile\` is set to \`${arg1}\`, but either the file is missing, it contains a syntax error, or threw an error when required. The \`pluginsFile\` must be a \`.js\`, \`.ts\`, or \`.coffee\` file.
Or you might have renamed the extension of your \`pluginsFile\`. If that's the case, restart the test runner.
Please fix this, or set \`pluginsFile\` to \`false\` if a plugins file is not necessary for your project.`.trim()
if (arg2) {
return { msg, details: arg2 }
}
return msg
case 'PLUGINS_DIDNT_EXPORT_FUNCTION':
msg = stripIndent`\
The \`pluginsFile\` must export a function with the following signature:
The \`setupNodeEvents\` method must BE a function with the following signature:
\`\`\`
module.exports = function (on, config) {
setupNodeEvents (on, config) {
// configure plugins here
}
\`\`\`
Learn more: https://on.cypress.io/plugins-api
We loaded the \`pluginsFile\` from: \`${arg1}\`
We loaded the \`setupNodeEvents\` from: \`${arg1}\`
It exported:`
@@ -598,10 +583,10 @@ const getMsgByType = function (type, arg1 = {}, arg2, arg3) {
We invoked the function exported by \`${arg1}\`, but it threw an error.`
return { msg, details: arg2 }
case 'PLUGINS_UNEXPECTED_ERROR':
msg = `The following error was thrown by a plugin. We stopped running your tests because a plugin crashed. Please check your plugins file (\`${arg1}\`)`
case 'SETUP_NODE_EVENTS_UNEXPECTED_ERROR':
msg = `The following error was thrown by a plugin. We stopped running your tests because a plugin crashed. Please check your setupNodeEvents method for (\`${arg1}\`) on file (\`${arg2}\`)`
return { msg, details: arg2 }
return { msg, details: arg3 }
case 'PLUGINS_VALIDATION_ERROR':
msg = `The following validation error was thrown by your plugins file (\`${arg1}\`).`
@@ -639,7 +624,7 @@ const getMsgByType = function (type, arg1 = {}, arg2, arg3) {
filePath = `\`${arg1}\``
return stripIndent`\
An invalid configuration value returned from the plugins file: ${chalk.blue(filePath)}
An invalid configuration value returned from the setupNodeEvents on config file: ${chalk.blue(filePath)}
${chalk.yellow(arg2)}`
// general configuration error not-specific to configuration or plugins files

View File

@@ -1,6 +1,6 @@
import { DataContext } from '@packages/data-context'
import os from 'os'
import { app } from 'electron'
import type { App } from 'electron'
import specsUtil from './util/specs'
import type { FindSpecs, FoundBrowser, LaunchArgs, LaunchOpts, OpenProjectLaunchOptions, PlatformName, Preferences, SettingsOptions } from '@packages/types'
@@ -12,6 +12,7 @@ import { EventEmitter } from 'events'
import { openProject } from './open_project'
import cache from './cache'
import errors from './errors'
import findSystemNode from './util/find_system_node'
import { graphqlSchema } from '@packages/graphql/src/schema'
import type { InternalDataContextOptions } from '@packages/data-context/src/DataContext'
import { openExternal } from '@packages/server/lib/gui/links'
@@ -19,6 +20,7 @@ import { openExternal } from '@packages/server/lib/gui/links'
const { getBrowsers, ensureAndGetByNameOrPath } = browserUtils
interface MakeDataContextOptions {
electronApp?: App
os: PlatformName
rootBus: EventEmitter
launchArgs: LaunchArgs
@@ -28,7 +30,8 @@ interface MakeDataContextOptions {
let legacyDataContext: DataContext | undefined
// For testing
export function clearLegacyDataContext () {
export async function clearLegacyDataContext () {
await legacyDataContext?.destroy()
legacyDataContext = undefined
}
@@ -49,15 +52,17 @@ export function makeLegacyDataContext (launchArgs: LaunchArgs = {} as LaunchArgs
return legacyDataContext
}
export function makeDataContext (options: MakeDataContextOptions) {
return new DataContext({
export function makeDataContext (options: MakeDataContextOptions): DataContext {
const ctx = new DataContext({
schema: graphqlSchema,
...options,
launchOptions: {},
electronApp: app,
appApi: {
getBrowsers,
ensureAndGetByNameOrPath,
findNodePathAndVersion () {
return findSystemNode.findNodePathAndVersion()
},
},
authApi: {
getUser () {
@@ -72,7 +77,7 @@ export function makeDataContext (options: MakeDataContextOptions) {
},
projectApi: {
getConfig (projectRoot: string, options?: SettingsOptions) {
return config.get(projectRoot, options)
return config.get(projectRoot, options, ctx)
},
launchProject (browser: FoundBrowser, spec: Cypress.Spec, options?: LaunchOpts) {
return openProject.launch({ ...browser }, spec, options)
@@ -110,8 +115,8 @@ export function makeDataContext (options: MakeDataContextOptions) {
closeActiveProject () {
return openProject.closeActiveProject()
},
error (type: string, ...args: any) {
throw errors.throw(type, ...args)
get error () {
return errors
},
},
electronApi: {
@@ -120,4 +125,6 @@ export function makeDataContext (options: MakeDataContextOptions) {
},
},
})
return ctx
}

View File

@@ -131,7 +131,7 @@ export = {
ready (options: {projectRoot?: string} = {}) {
const { projectRoot } = options
const { serverPortPromise, bus, ctx } = process.env.LAUNCHPAD
? runInternalServer(options)
? runInternalServer(options, undefined, app)
: { bus: new EventEmitter, serverPortPromise: Promise.resolve(undefined), ctx: null }
// TODO: potentially just pass an event emitter

View File

@@ -1,17 +1,19 @@
import os from 'os'
import { EventEmitter } from 'events'
import type { App } from 'electron'
import { makeDataContext } from '../makeDataContext'
import { makeGraphQLServer } from '../gui/makeGraphQLServer'
import { assertValidPlatform } from '@packages/types/src/platform'
export function runInternalServer (launchArgs, _internalOptions = { loadCachedProjects: true }) {
export function runInternalServer (launchArgs, _internalOptions = { loadCachedProjects: true }, electronApp?: App) {
const bus = new EventEmitter()
const platform = os.platform()
assertValidPlatform(platform)
const ctx = makeDataContext({
electronApp,
os: platform,
rootBus: bus,
launchArgs,

View File

@@ -453,13 +453,15 @@ export class OpenProject {
debug('opening project %s', path)
debug('and options %o', options)
const testingType = args.testingType === 'component' ? 'component' : 'e2e'
// store the currently open project
this.openProject = new ProjectBase({
testingType: args.testingType === 'component' ? 'component' : 'e2e',
testingType,
projectRoot: path,
options: {
...options,
testingType: args.testingType,
testingType,
},
})

Some files were not shown because too many files have changed in this diff Show More