Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
66dcf80
adding types to support new devServer contract
tgriesser Mar 31, 2022
b115c4f
initial commit, webpack-dev-server-fresh package
tgriesser Mar 31, 2022
d512f68
wip cypress tests for webpack-dev-server-fresh
tgriesser Mar 31, 2022
24456d4
Passing e2e open mode test
tgriesser Mar 31, 2022
7187cf7
Examples working for webpack/wds versions
tgriesser Mar 31, 2022
7f83ff8
new convention for system testing via project-fixtures directory
tgriesser Mar 31, 2022
35be22c
cleaning up some of the devServer
tgriesser Mar 31, 2022
223b1ea
Fixing up tests, types, add system tests
tgriesser Apr 1, 2022
5377d71
change import
tgriesser Apr 1, 2022
7fd7a6a
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 1, 2022
ef3c223
fixes for CI failures / CI workflow
tgriesser Apr 1, 2022
17416d3
Fix
tgriesser Apr 1, 2022
bfe2ad4
minor cleanup
tgriesser Apr 1, 2022
1f0ed9c
Add fixture to ct project
tgriesser Apr 1, 2022
738588b
circle fixes
tgriesser Apr 1, 2022
a4e6389
make changes reflecting zach's html PR changes
tgriesser Apr 1, 2022
b82940d
thanks percy
tgriesser Apr 1, 2022
ad77637
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 1, 2022
f707b34
get it
tgriesser Apr 1, 2022
afa8c5a
Revert change to webpack-dev-server/package.json
tgriesser Apr 4, 2022
91d6dce
Revert "Revert change to webpack-dev-server/package.json"
tgriesser Apr 4, 2022
1c99864
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 4, 2022
08c7ea0
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 4, 2022
cca7a16
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 4, 2022
a63206e
fix types
tgriesser Apr 5, 2022
0cf09cc
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 5, 2022
fe7a28d
dependency + test fixes
tgriesser Apr 5, 2022
01f9a06
Merge branch '10.0-release' into tgriesser/feat/UNIFY-1267
tgriesser Apr 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,5 @@ system-tests/projects/nuxtjs-vue2-configured/**/*

system-tests/projects/react-app-webpack-5-unconfigured/**/*

system-tests/project-fixtures/**
system-tests/projects/**/*/expected-cypress*/**/*
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ system-tests/fixtures/large-img
/npm/design-system/cypress/videos
/npm/design-system/.babel-cache

# from npm/webpack-dev-server-fresh
/npm/webpack-dev-server-fresh/cypress/videos

# from runner-ct
/packages/runner-ct/cypress/screenshots

Expand Down
35 changes: 33 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,8 @@ jobs:
run-app-integration-tests-chrome,
run-frontend-shared-component-tests-chrome,
run-launchpad-component-tests-chrome,
run-launchpad-integration-tests-chrome
run-launchpad-integration-tests-chrome,
run-webpack-dev-server-fresh-integration-tests
- run:
command: |
PERCY_PARALLEL_NONCE=$CIRCLE_SHA1 \
Expand Down Expand Up @@ -1433,6 +1434,28 @@ jobs:
path: /tmp/artifacts
- store-npm-logs

run-webpack-dev-server-fresh-integration-tests:
<<: *defaults
# parallelism: 3 TODO: Add parallelism once we have more specs
steps:
- restore_cached_workspace
- restore_cached_system_tests_deps
- run:
command: |
CYPRESS_KONFIG_ENV=production \
CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \
PERCY_PARALLEL_NONCE=$CIRCLE_SHA1 \
PERCY_ENABLE=${PERCY_TOKEN:-0} \
PERCY_PARALLEL_TOTAL=-1 \
yarn percy exec --parallel -- -- \
yarn cypress:run --record --parallel --group webpack-dev-server-fresh
working_directory: npm/webpack-dev-server-fresh
- store_test_results:
path: /tmp/cypress
- store_artifacts:
path: /tmp/artifacts
- store-npm-logs

ui-components-integration-tests:
<<: *defaults
steps:
Expand Down Expand Up @@ -1494,9 +1517,13 @@ jobs:
<<: *defaults
steps:
- restore_cached_workspace
- restore_cached_system_tests_deps
- run:
name: Run tests
command: yarn workspace @cypress/webpack-dev-server test
- run:
name: Run tests
command: yarn workspace @cypress/webpack-dev-server-fresh test

npm-vite-dev-server:
<<: *defaults
Expand Down Expand Up @@ -2226,6 +2253,10 @@ linux-workflow: &linux-workflow
percy: true
requires:
- build
- run-webpack-dev-server-fresh-integration-tests:
context: [test-runner:cypress-record-key, test-runner:percy]
requires:
- system-tests-node-modules-install
- run-app-component-tests-chrome:
context: [test-runner:launchpad-tests, test-runner:percy]
percy: true
Expand All @@ -2241,7 +2272,7 @@ linux-workflow: &linux-workflow
- build
- npm-webpack-dev-server:
requires:
- build
- system-tests-node-modules-install
- npm-vite-dev-server:
requires:
- build
Expand Down
32 changes: 29 additions & 3 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2868,7 +2868,7 @@ declare namespace Cypress {
/**
* Handle Cypress plugins
*/
setupNodeEvents: (on: PluginEvents, config: PluginConfigOptions) => Promise<PluginConfigOptions> | PluginConfigOptions
setupNodeEvents: (on: PluginEvents, config: PluginConfigOptions) => Promise<PluginConfigOptions | void> | PluginConfigOptions | void

indexHtmlFile: string
}
Expand Down Expand Up @@ -2919,6 +2919,7 @@ declare namespace Cypress {
namespace: string
projectRoot: string
devServerPublicPathRoute: string
cypressBinaryRoot: string
}

/**
Expand Down Expand Up @@ -2964,9 +2965,34 @@ declare namespace Cypress {
*/
type CoreConfigOptions = Partial<Omit<ResolvedConfigOptions, TestingType>>

interface DefineDevServerConfig {
// This interface can be extended by the user, to inject the types for their
// preferred bundler: e.g.
//
// import type * as webpack from 'webpack'
//
// declare global {
// namespace Cypress {
// interface DefineDevServerConfig {
// webpackConfig?: webpack.Configuration
// }
// }
// }
[key: string]: any
}

type PickConfigOpt<T> = T extends keyof DefineDevServerConfig ? DefineDevServerConfig[T] : any

type DevServerFn<ComponentDevServerOpts = any> = (cypressDevServerConfig: DevServerConfig, devServerConfig: ComponentDevServerOpts) => ResolvedDevServerConfig | Promise<ResolvedDevServerConfig>

interface DevServerConfigObject {
bundler: 'webpack'
framework: 'react'
webpackConfig?: PickConfigOpt<'webpackConfig'>
}

interface ComponentConfigOptions<ComponentDevServerOpts = any> extends Omit<CoreConfigOptions, 'baseUrl'> {
devServer: DevServerFn<ComponentDevServerOpts>
devServer: DevServerFn<ComponentDevServerOpts> | DevServerConfigObject
devServerConfig?: ComponentDevServerOpts
}

Expand Down Expand Up @@ -5428,7 +5454,7 @@ declare namespace Cypress {

interface ResolvedDevServerConfig {
port: number
close: (done?: () => any) => void
close: (done?: (err?: Error) => any) => void
}

interface PluginEvents {
Expand Down
Empty file.
65 changes: 65 additions & 0 deletions npm/webpack-dev-server-fresh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# @cypress/webpack-dev-server-fresh

Implements the APIs for the object-syntax of the Cypress Component-testing "webpack dev server".

Object syntax:

```ts
import { defineConfig } from 'cypress'

export default defineConfig({
component: {
devServer: {
framework: 'create-react-app',
bundler: 'webpack',
// webpackConfig?: Will try to infer, if passed it will be used as is
}
}
})
```

Function syntax:

```ts
import { devServer } from '@cypress/webpack-dev-server'
import { defineConfig } from 'cypress'

export default defineConfig({
component: {
devServer(cypressConfig) {
return devServer({
cypressConfig,
framework: 'react',
webpackConfig: require('./webpack.config.js')
})
}
}
})
```

## Testing

Unit tests can be run with `npm test`. Integration tests can be run with `yarn cypress:run`

This module should be primarily covered by system-tests / open-mode tests. All system-tests directories should be created using the notation:

`webpack${major}_wds${devServerMajor}-$framework{-$variant}`

- webpack4_wds3-react
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit... seems inconsistent w.r.t. _ and -.

We could do packages separated w/ _? Eg webpack4_wds_create-react-app5.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I had this to distinguish between the webpack variants & frameworks. Don't mind if we do trailing _

- webpack4_wds4-next-11
- webpack5_wds3-next-12
- webpack4_wds4-create-react-app

## Architecture

There should be a single publicly-exported entrypoint for the module, `devServer`, all other types and functions should be considered internal/implementation details, and types stripped from the output.

The `devServer` will first source the modules from the user's project, falling back to our own bundled versions of libraries. This ensures that the user has installed the current modules, and throws an error if the user does not have the library installed.

From there, we check the "framework" field to source or define any known webpack transforms to aid in the compilation.

We then merge the sourced config with the user's webpack config, and layer on our own transforms, and provide this to a webpack instance. The webpack instance used to create a webpack-dev-server, which is returned.

## Changelog

[Changelog](./CHANGELOG.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
exports['makeWebpackConfig ignores userland webpack `output.publicPath` 1'] = {
"output": {
"publicPath": "/test-public-path/",
"filename": "[name].js"
},
"mode": "development",
"optimization": {
"splitChunks": {
"chunks": "all"
}
},
"plugins": [
"HtmlWebpackPlugin",
"CypressCTWebpackPlugin"
]
}
26 changes: 26 additions & 0 deletions npm/webpack-dev-server-fresh/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig } from 'cypress'

export default defineConfig({
projectId: 'ypt4pf',
e2e: {
defaultCommandTimeout: 10000, // these take a bit longer b/c they're e2e open mode test
async setupNodeEvents (on, config) {
if (!process.env.HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS) {
throw new Error('HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS is missing. Close Cypress and run tests using the `yarn cypress:*` commands from the `packages/app` directory')
}

// Delete this as we only want to honor it on parent Cypress when doing E2E Cypress in Cypress testing
delete process.env.HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS
process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF = 'true'
const { e2ePluginSetup } = require('@packages/frontend-shared/cypress/e2e/e2ePluginSetup') as typeof import('@packages/frontend-shared/cypress/e2e/e2ePluginSetup')

return await e2ePluginSetup(on, config)
},
},
// @ts-ignore We are setting these namespaces in order to properly test Cypress in Cypress
clientRoute: '/__app/',
namespace: '__cypress-app',
socketIoRoute: '/__app-socket',
socketIoCookie: '__app-socket',
devServerPublicPathRoute: '/__cypress-app/src',
})
60 changes: 60 additions & 0 deletions npm/webpack-dev-server-fresh/cypress/e2e/react.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/// <reference types="cypress" />
/// <reference path="../support/e2e.ts" />
import type { e2eProjectDirs } from '@packages/frontend-shared/cypress/e2e/support/e2eProjectDirs'

type ProjectDirs = typeof e2eProjectDirs

const WEBPACK_REACT: ProjectDirs[number][] = ['webpack4_wds3-react', 'webpack4_wds4-react', 'webpack5_wds3-react', 'webpack5_wds4-react']

// Add to this list to focus on a particular permutation
const ONLY_PROJECTS: ProjectDirs[number][] = []

for (const project of WEBPACK_REACT) {
if (ONLY_PROJECTS.length && !ONLY_PROJECTS.includes(project)) {
continue
}

describe(`Working with ${project}`, () => {
beforeEach(() => {
cy.scaffoldProject(project)
cy.openProject(project)
cy.startAppServer('component')
})

it('should mount a passing test', () => {
cy.visitApp()
cy.contains('App.cy.jsx').click()
cy.get('.passed > .num').should('contain', 1)
})

it('MissingReact: should fail, rerun, succeed', () => {
cy.once('uncaught:exception', () => {
// Ignore the uncaught exception in the AUT
return false
})

cy.visitApp()
cy.contains('MissingReact.cy.jsx').click()
cy.get('.failed > .num').should('contain', 1)
cy.withCtx(async (ctx) => {
await ctx.actions.file.writeFileInProject(`src/MissingReact.jsx`,
`import React from 'react';
${await ctx.actions.file.readFileInProject('src/MissingReact.jsx')}`)
})
Comment on lines +39 to +43
Copy link
Member Author

Choose a reason for hiding this comment

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

Tests in open mode that the webpack-dev-server is able to auto-refresh when we fix issues in the user code.

Copy link
Contributor

Choose a reason for hiding this comment

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

New infra 💯

I think this is a good one to demo next biweekly demo - if we don't show this stuff off and champion it, most people won't know. I think a lot of people are not using system-tests in the most productive way for this reason.


cy.get('.passed > .num').should('contain', 1)
})

it('MissingReactInSpec: should fail, rerun, succeed', () => {
cy.visitApp()
cy.contains('MissingReactInSpec.cy.jsx').click()
cy.get('.failed > .num').should('contain', 1)
cy.withCtx(async (ctx) => {
await ctx.actions.file.writeFileInProject(`src/MissingReactInSpec.cy.jsx`,
await ctx.actions.file.readFileInProject('src/App.cy.jsx'))
})
Comment on lines +50 to +55
Copy link
Member Author

Choose a reason for hiding this comment

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

Tests in open mode that the webpack-dev-server is able to auto-refresh when we fix issues in the spec.


cy.get('.passed > .num').should('contain', 1)
})
})
}
37 changes: 37 additions & 0 deletions npm/webpack-dev-server-fresh/cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
20 changes: 20 additions & 0 deletions npm/webpack-dev-server-fresh/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import '@packages/frontend-shared/cypress/e2e/support/e2eSupport'

// Alternatively you can use CommonJS syntax:
// require('./commands')
Loading