mirror of
https://github.com/cypress-io/cypress.git
synced 2026-04-22 15:12:27 -05:00
Merge pull request #16127 from cypress-io/lachlan/fe0b63c29-master-into-develop
chore: resolve conflicts in master(fe0b63c29) to develop back merge
This commit is contained in:
+11
@@ -1336,6 +1336,13 @@ jobs:
|
||||
path: npm/react/test_results
|
||||
- store-npm-logs
|
||||
|
||||
npm-mount-utils:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- restore_cached_workspace
|
||||
- run:
|
||||
name: Build
|
||||
command: yarn workspace @cypress/mount-utils build
|
||||
|
||||
npm-create-cypress-tests:
|
||||
<<: *defaults
|
||||
@@ -1934,6 +1941,9 @@ linux-workflow: &linux-workflow
|
||||
- npm-react:
|
||||
requires:
|
||||
- build
|
||||
- npm-mount-utils:
|
||||
requires:
|
||||
- build
|
||||
- npm-create-cypress-tests:
|
||||
requires:
|
||||
- build
|
||||
@@ -1949,6 +1959,7 @@ linux-workflow: &linux-workflow
|
||||
- npm-eslint-plugin-dev
|
||||
- npm-create-cypress-tests
|
||||
- npm-react
|
||||
- npm-mount-utils
|
||||
- npm-vue
|
||||
- npm-design-system
|
||||
- npm-webpack-batteries-included-preprocessor
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# @cypress/mount-utils-v1.0.0 (2021-04-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve handling of userland injected styles in component testing ([#16024](https://github.com/cypress-io/cypress/issues/16024)) ([fe0b63c](https://github.com/cypress-io/cypress/commit/fe0b63c299947470c9cdce3a0d00364a1e224bdb))
|
||||
@@ -0,0 +1,10 @@
|
||||
# @cypress/mount-utils
|
||||
|
||||
> **Note** this package is not meant to be used outside of cypress component testing.
|
||||
|
||||
This librares exports some shared types and utility functions designed to build adapters for components frameworks.
|
||||
|
||||
It is used in:
|
||||
|
||||
- [`@cypress/react`](https://github.com/cypress-io/cypress/tree/develop/npm/react)
|
||||
- [`@cypress/vue`](https://github.com/cypress-io/cypress/tree/develop/npm/vue)
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@cypress/mount-utils",
|
||||
"version": "0.0.0-development",
|
||||
"description": "Shared utilities for the various component testing adapters",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build-prod": "tsc",
|
||||
"watch": "tsc -w"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.2.3"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cypress-io/cypress.git"
|
||||
},
|
||||
"homepage": "https://github.com/cypress-io/cypress/tree/master/npm/mount-utils#readme",
|
||||
"bugs": "https://github.com/cypress-io/cypress/issues/new?template=1-bug-report.md",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,68 @@
|
||||
import { StyleOptions } from './mount'
|
||||
/// <reference types="cypress" />
|
||||
|
||||
/**
|
||||
* Additional styles to inject into the document.
|
||||
* A component might need 3rd party libraries from CDN,
|
||||
* local CSS files and custom styles.
|
||||
*/
|
||||
export interface StyleOptions {
|
||||
/**
|
||||
* Creates <link href="..." /> element for each stylesheet
|
||||
* @alias stylesheet
|
||||
*/
|
||||
stylesheets: string | string[]
|
||||
/**
|
||||
* Creates <link href="..." /> element for each stylesheet
|
||||
* @alias stylesheets
|
||||
*/
|
||||
stylesheet: string | string[]
|
||||
/**
|
||||
* Creates <style>...</style> element and inserts given CSS.
|
||||
* @alias styles
|
||||
*/
|
||||
style: string | string[]
|
||||
/**
|
||||
* Creates <style>...</style> element for each given CSS text.
|
||||
* @alias style
|
||||
*/
|
||||
styles: string | string[]
|
||||
/**
|
||||
* Loads each file and creates a <style>...</style> element
|
||||
* with the loaded CSS
|
||||
* @alias cssFile
|
||||
*/
|
||||
cssFiles: string | string[]
|
||||
/**
|
||||
* Single CSS file to load into a <style></style> element
|
||||
* @alias cssFile
|
||||
*/
|
||||
cssFile: string | string[]
|
||||
}
|
||||
|
||||
export const ROOT_ID = '__cy_root'
|
||||
|
||||
/**
|
||||
* Remove any style or extra link elements from the iframe placeholder
|
||||
* left from any previous test
|
||||
*
|
||||
*/
|
||||
export function cleanupStyles () {
|
||||
const styles = document.body.querySelectorAll('[data-cy=injected-style-tag]')
|
||||
|
||||
styles.forEach((styleElement) => {
|
||||
if (styleElement.parentElement) {
|
||||
styleElement.parentElement.removeChild(styleElement)
|
||||
}
|
||||
})
|
||||
|
||||
const links = document.body.querySelectorAll('[data-cy=injected-stylesheet]')
|
||||
|
||||
links.forEach((link) => {
|
||||
if (link.parentElement) {
|
||||
link.parentElement.removeChild(link)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert links to external style resources.
|
||||
@@ -14,6 +78,7 @@ function insertStylesheets (
|
||||
link.type = 'text/css'
|
||||
link.rel = 'stylesheet'
|
||||
link.href = href
|
||||
link.dataset.cy = 'injected-stylesheet'
|
||||
document.body.insertBefore(link, el)
|
||||
})
|
||||
}
|
||||
@@ -25,6 +90,7 @@ function insertStyles (styles: string[], document: Document, el: HTMLElement | n
|
||||
styles.forEach((style) => {
|
||||
const styleElement = document.createElement('style')
|
||||
|
||||
styleElement.dataset.cy = 'injected-style-tag'
|
||||
styleElement.appendChild(document.createTextNode(style))
|
||||
document.body.insertBefore(styleElement, el)
|
||||
})
|
||||
@@ -124,3 +190,20 @@ export const injectStylesBeforeElement = (
|
||||
|
||||
return insertLocalCssFiles(cssFiles, document, el, options.log)
|
||||
}
|
||||
|
||||
export function setupHooks (optionalCallback?: Function) {
|
||||
// When running component specs, we cannot allow "cy.visit"
|
||||
// because it will wipe out our preparation work, and does not make much sense
|
||||
// thus we overwrite "cy.visit" to throw an error
|
||||
Cypress.Commands.overwrite('visit', () => {
|
||||
throw new Error(
|
||||
'cy.visit from a component spec is not allowed',
|
||||
)
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
beforeEach(() => {
|
||||
optionalCallback?.()
|
||||
cleanupStyles()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "es2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */,
|
||||
"module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"skipLibCheck": true,
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
] /* Specify library files to be included in the compilation: */,
|
||||
"allowJs": true /* Allow javascript files to be compiled. */,
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
"declaration": true /* Generates corresponding '.d.ts' file. */,
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "dist" /* Redirect output structure to the directory. */,
|
||||
// "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": false /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true,
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
"types": ["cypress"] /* Type declaration files to be included in compilation. */,
|
||||
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "*.js"]
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
# [@cypress/react-v5.3.4](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.3.3...@cypress/react-v5.3.4) (2021-04-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve handling of userland injected styles in component testing ([#16024](https://github.com/cypress-io/cypress/issues/16024)) ([fe0b63c](https://github.com/cypress-io/cypress/commit/fe0b63c299947470c9cdce3a0d00364a1e224bdb))
|
||||
|
||||
# [@cypress/react-v5.3.3](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.3.2...@cypress/react-v5.3.3) (2021-04-13)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import * as React from 'react'
|
||||
import { mount } from '@cypress/react'
|
||||
import styled, { ThemeProvider } from 'styled-components'
|
||||
|
||||
const lightest = '#FFFEFD'
|
||||
const light = '#FEFCF1'
|
||||
const darker = '#C49A03'
|
||||
const darkest = '#382E0A'
|
||||
|
||||
export const theme = {
|
||||
primaryDark: darkest,
|
||||
primaryLight: lightest,
|
||||
primaryLightDarker: light,
|
||||
primaryHover: darker,
|
||||
}
|
||||
|
||||
const styledComponentsStyle = 'margin-bottom:1rem'
|
||||
const Line = styled.div`
|
||||
${styledComponentsStyle}
|
||||
`
|
||||
|
||||
export const SearchResults = (props) => {
|
||||
return (
|
||||
<div>
|
||||
{props.results.map((result) => {
|
||||
return (
|
||||
<Line>
|
||||
{result.title}
|
||||
</Line>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mountComponent = ({ results }, options) => {
|
||||
return mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<div style={{ margin: '6rem', maxWidth: '105rem' }}>
|
||||
<SearchResults results={results} />
|
||||
</div>
|
||||
</ThemeProvider>,
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
const inlineStyle = 'body { background: blue; }'
|
||||
const bulmaCDN = 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css'
|
||||
|
||||
describe('SearchResults', () => {
|
||||
it('should inject styles into <head>', () => {
|
||||
mountComponent({
|
||||
results: [{ title: 'Org 1' }, { title: 'Org 2' }],
|
||||
},
|
||||
{
|
||||
stylesheets: [bulmaCDN],
|
||||
style: inlineStyle,
|
||||
})
|
||||
|
||||
cy.get('link').should('exist')
|
||||
cy.get('link').should('have.attr', 'href', bulmaCDN)
|
||||
})
|
||||
|
||||
it('style-components injected styles from previous test should not be cleaned up \
|
||||
but styles and stylesheets in mount should be', () => {
|
||||
// style-components injected style should NOT have bene cleaned up
|
||||
cy.get('style').should('contain.text', styledComponentsStyle)
|
||||
|
||||
// cleaned up inline <style> from previous test
|
||||
cy.get('style').should('not.contain.text', inlineStyle)
|
||||
|
||||
// cleaned up bulma CDN link from previous test
|
||||
cy.get('link').should('not.exist')
|
||||
|
||||
mountComponent({
|
||||
results: [{ title: 'Org 1' }, { title: 'Org 2' }],
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -17,6 +17,7 @@
|
||||
"watch": "yarn build --watch --watch.exclude ./dist/**/*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cypress/mount-utils": "0.0.0-development",
|
||||
"@cypress/webpack-preprocessor": "0.0.0-development",
|
||||
"debug": "4.3.2",
|
||||
"find-webpack": "2.2.1",
|
||||
|
||||
@@ -24,6 +24,7 @@ function createEntry (options) {
|
||||
external: [
|
||||
'react',
|
||||
'react-dom',
|
||||
'@cypress/mount-utils',
|
||||
],
|
||||
plugins: [
|
||||
resolve(), commonjs(),
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
export function setupHooks (unmount: (opts: { log: boolean }) => void) {
|
||||
// When running component specs, we cannot allow "cy.visit"
|
||||
// because it will wipe out our preparation work, and does not make much sense
|
||||
// thus we overwrite "cy.visit" to throw an error
|
||||
Cypress.Commands.overwrite('visit', () => {
|
||||
throw new Error(
|
||||
'cy.visit from a component spec is not allowed',
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* Remove any style or extra link elements from the iframe placeholder
|
||||
* left from any previous test
|
||||
*
|
||||
*/
|
||||
function cleanupStyles () {
|
||||
const styles = document.body.querySelectorAll('style')
|
||||
|
||||
styles.forEach((styleElement) => {
|
||||
if (styleElement.parentElement) {
|
||||
styleElement.parentElement.removeChild(styleElement)
|
||||
}
|
||||
})
|
||||
|
||||
const links = document.body.querySelectorAll('link[rel=stylesheet]')
|
||||
|
||||
links.forEach((link) => {
|
||||
if (link.parentElement) {
|
||||
link.parentElement.removeChild(link)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
unmount({ log: false })
|
||||
cleanupStyles()
|
||||
})
|
||||
}
|
||||
+8
-53
@@ -1,10 +1,12 @@
|
||||
import * as React from 'react'
|
||||
import * as ReactDOM from 'react-dom'
|
||||
import getDisplayName from './getDisplayName'
|
||||
import { injectStylesBeforeElement } from './utils'
|
||||
import { setupHooks } from './hooks'
|
||||
|
||||
const ROOT_ID = '__cy_root'
|
||||
import {
|
||||
injectStylesBeforeElement,
|
||||
StyleOptions,
|
||||
ROOT_ID,
|
||||
setupHooks,
|
||||
} from '@cypress/mount-utils'
|
||||
|
||||
/**
|
||||
* Inject custom style text or CSS file or 3rd party style resources
|
||||
@@ -128,17 +130,11 @@ const _mount = (type: 'mount' | 'rerender', jsx: React.ReactNode, options: Mount
|
||||
}) as unknown as globalThis.Cypress.Chainable<MountReturn>
|
||||
}
|
||||
|
||||
let initialInnerHtml = ''
|
||||
|
||||
Cypress.on('run:start', () => {
|
||||
initialInnerHtml = document.head.innerHTML
|
||||
})
|
||||
|
||||
/**
|
||||
* Removes the mounted component. Notice this command automatically
|
||||
* queues up the `unmount` into Cypress chain, thus you don't need `.then`
|
||||
* to call it.
|
||||
* @see https://github.com/bahmutov/@cypress/react/tree/main/cypress/component/basic/unmount
|
||||
* @see https://github.com/cypress-io/cypress/tree/develop/npm/react/cypress/component/basic/unmount
|
||||
* @example
|
||||
```
|
||||
import { mount, unmount } from '@cypress/react'
|
||||
@@ -184,9 +180,7 @@ Cypress.on('test:before:run', () => {
|
||||
const el = document.getElementById(ROOT_ID)
|
||||
|
||||
if (el) {
|
||||
const wasUnmounted = ReactDOM.unmountComponentAtNode(el)
|
||||
|
||||
document.head.innerHTML = initialInnerHtml
|
||||
ReactDOM.unmountComponentAtNode(el)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -233,45 +227,6 @@ export interface ReactModule {
|
||||
source: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional styles to inject into the document.
|
||||
* A component might need 3rd party libraries from CDN,
|
||||
* local CSS files and custom styles.
|
||||
*/
|
||||
export interface StyleOptions {
|
||||
/**
|
||||
* Creates <link href="..." /> element for each stylesheet
|
||||
* @alias stylesheet
|
||||
*/
|
||||
stylesheets: string | string[]
|
||||
/**
|
||||
* Creates <link href="..." /> element for each stylesheet
|
||||
* @alias stylesheets
|
||||
*/
|
||||
stylesheet: string | string[]
|
||||
/**
|
||||
* Creates <style>...</style> element and inserts given CSS.
|
||||
* @alias styles
|
||||
*/
|
||||
style: string | string[]
|
||||
/**
|
||||
* Creates <style>...</style> element for each given CSS text.
|
||||
* @alias style
|
||||
*/
|
||||
styles: string | string[]
|
||||
/**
|
||||
* Loads each file and creates a <style>...</style> element
|
||||
* with the loaded CSS
|
||||
* @alias cssFile
|
||||
*/
|
||||
cssFiles: string | string[]
|
||||
/**
|
||||
* Single CSS file to load into a <style></style> element
|
||||
* @alias cssFile
|
||||
*/
|
||||
cssFile: string | string[]
|
||||
}
|
||||
|
||||
export interface MountReactComponentOptions {
|
||||
alias: string
|
||||
ReactDom: typeof ReactDOM
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# [@cypress/vue-v2.2.1](https://github.com/cypress-io/cypress/compare/@cypress/vue-v2.2.0...@cypress/vue-v2.2.1) (2021-04-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve handling of userland injected styles in component testing ([#16024](https://github.com/cypress-io/cypress/issues/16024)) ([fe0b63c](https://github.com/cypress-io/cypress/commit/fe0b63c299947470c9cdce3a0d00364a1e224bdb))
|
||||
|
||||
# [@cypress/vue-v2.2.0](https://github.com/cypress-io/cypress/compare/@cypress/vue-v2.1.1...@cypress/vue-v2.2.0) (2021-04-05)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { mount, mountCallback } from '@cypress/vue'
|
||||
import RedBox from './RedBox.vue'
|
||||
|
||||
const tailwindCdnLink = 'https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css'
|
||||
|
||||
const inlineStyle = 'body { background: blue; }'
|
||||
|
||||
describe('RedBox 1', () => {
|
||||
const template = '<red-box :status="true" />'
|
||||
const options = {
|
||||
@@ -11,14 +15,17 @@ describe('RedBox 1', () => {
|
||||
},
|
||||
// you can inject additional styles to be downloaded
|
||||
//
|
||||
style: inlineStyle,
|
||||
stylesheets: [
|
||||
// you can use external links
|
||||
'https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css',
|
||||
tailwindCdnLink,
|
||||
],
|
||||
}
|
||||
|
||||
it('displays red Hello RedBox', () => {
|
||||
mount({ template }, options)
|
||||
// shoud have injected the inline styling.
|
||||
cy.get('style').should('contain.text', inlineStyle)
|
||||
|
||||
cy.contains('Hello RedBox')
|
||||
cy.get('[data-cy=box]')
|
||||
@@ -38,12 +45,19 @@ describe('RedBox 2', () => {
|
||||
},
|
||||
stylesheets: [
|
||||
// you can use external links
|
||||
'https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css',
|
||||
tailwindCdnLink,
|
||||
],
|
||||
}
|
||||
|
||||
beforeEach(mountCallback({ template }, options))
|
||||
beforeEach(() => {
|
||||
// should clean up links inserted via mounting options before each test.
|
||||
cy.get('link').should('not.exist')
|
||||
mount({ template }, options)
|
||||
})
|
||||
|
||||
it('displays Goodbye RedBox', () => {
|
||||
// cleaned up inline <style> from previous test
|
||||
cy.get('style').should('not.contain.text', inlineStyle)
|
||||
cy.contains('Goodbye RedBox')
|
||||
})
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"test-ci": "node ../../scripts/run-ct-examples.js --examplesList=./examples.env"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cypress/mount-utils": "0.0.0-development",
|
||||
"@vue/test-utils": "^1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,6 +24,7 @@ function createEntry (options) {
|
||||
external: [
|
||||
'vue',
|
||||
'@vue/test-utils',
|
||||
'@cypress/mount-utils',
|
||||
'@cypress/webpack-dev-server',
|
||||
],
|
||||
plugins: [
|
||||
|
||||
+27
-65
@@ -7,14 +7,16 @@ import {
|
||||
Wrapper,
|
||||
enableAutoDestroy,
|
||||
} from '@vue/test-utils'
|
||||
|
||||
const ROOT_ID = '__cy_root'
|
||||
import {
|
||||
injectStylesBeforeElement,
|
||||
StyleOptions,
|
||||
ROOT_ID,
|
||||
setupHooks,
|
||||
} from '@cypress/mount-utils'
|
||||
|
||||
const defaultOptions: (keyof MountOptions)[] = [
|
||||
'vue',
|
||||
'extensions',
|
||||
'style',
|
||||
'stylesheets',
|
||||
]
|
||||
|
||||
const registerGlobalComponents = (Vue, options) => {
|
||||
@@ -224,37 +226,6 @@ interface MountOptions {
|
||||
*/
|
||||
vue: unknown
|
||||
|
||||
/**
|
||||
* CSS style string to inject when mounting the component
|
||||
*
|
||||
* @memberof MountOptions
|
||||
* @example
|
||||
* const style = `
|
||||
* .todo.done {
|
||||
* text-decoration: line-through;
|
||||
* color: gray;
|
||||
* }`
|
||||
* mount(Todo, { style })
|
||||
*/
|
||||
style: string
|
||||
|
||||
/**
|
||||
* Stylesheet(s) urls to inject as `<link ... />` elements when
|
||||
* mounting the component
|
||||
*
|
||||
* @memberof MountOptions
|
||||
* @example
|
||||
* const template = '...'
|
||||
* const stylesheets = '/node_modules/tailwindcss/dist/tailwind.min.css'
|
||||
* mount({ template }, { stylesheets })
|
||||
*
|
||||
* @example
|
||||
* const template = '...'
|
||||
* const stylesheets = ['https://cdn.../lib.css', 'https://lib2.css']
|
||||
* mount({ template }, { stylesheets })
|
||||
*/
|
||||
stylesheets: string | string[]
|
||||
|
||||
/**
|
||||
* Extra Vue plugins, mixins, local components to register while
|
||||
* mounting this component
|
||||
@@ -268,7 +239,7 @@ interface MountOptions {
|
||||
/**
|
||||
* Utility type for union of options passed to "mount(..., options)"
|
||||
*/
|
||||
type MountOptionsArgument = Partial<ComponentOptions & MountOptions & VueTestUtilsConfigOptions>
|
||||
type MountOptionsArgument = Partial<ComponentOptions & MountOptions & StyleOptions & VueTestUtilsConfigOptions>
|
||||
|
||||
// when we mount a Vue component, we add it to the global Cypress object
|
||||
// so here we extend the global Cypress namespace and its Cypress interface
|
||||
@@ -307,21 +278,20 @@ function failTestOnVueError (err, vm, info) {
|
||||
window.top.onerror(err)
|
||||
}
|
||||
|
||||
let initialInnerHtml = ''
|
||||
|
||||
Cypress.on('run:start', () => {
|
||||
initialInnerHtml = document.head.innerHTML
|
||||
})
|
||||
|
||||
function registerAutoDestroy ($destroy: () => void) {
|
||||
Cypress.on('test:before:run', () => {
|
||||
$destroy()
|
||||
document.head.innerHTML = initialInnerHtml
|
||||
})
|
||||
}
|
||||
|
||||
enableAutoDestroy(registerAutoDestroy)
|
||||
|
||||
const injectStyles = (options: StyleOptions) => {
|
||||
const el = document.getElementById(ROOT_ID)
|
||||
|
||||
return injectStylesBeforeElement(options, document, el)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts a Vue component inside Cypress browser.
|
||||
* @param {object} component imported from Vue file
|
||||
@@ -352,6 +322,18 @@ export const mount = (
|
||||
.window({
|
||||
log: false,
|
||||
})
|
||||
.then(() => {
|
||||
const { style, stylesheets, stylesheet, styles, cssFiles, cssFile } = optionsOrProps
|
||||
|
||||
injectStyles({
|
||||
style,
|
||||
stylesheets,
|
||||
stylesheet,
|
||||
styles,
|
||||
cssFiles,
|
||||
cssFile,
|
||||
})
|
||||
})
|
||||
.then((win) => {
|
||||
const localVue = createLocalVue()
|
||||
|
||||
@@ -376,28 +358,6 @@ export const mount = (
|
||||
|
||||
let el = document.getElementById(ROOT_ID)
|
||||
|
||||
if (typeof options.stylesheets === 'string') {
|
||||
options.stylesheets = [options.stylesheets]
|
||||
}
|
||||
|
||||
if (Array.isArray(options.stylesheets)) {
|
||||
options.stylesheets.forEach((href) => {
|
||||
const link = document.createElement('link')
|
||||
|
||||
link.type = 'text/css'
|
||||
link.rel = 'stylesheet'
|
||||
link.href = href
|
||||
el.append(link)
|
||||
})
|
||||
}
|
||||
|
||||
if (options.style) {
|
||||
const style = document.createElement('style')
|
||||
|
||||
style.appendChild(document.createTextNode(options.style))
|
||||
el.append(style)
|
||||
}
|
||||
|
||||
const componentNode = document.createElement('div')
|
||||
|
||||
el.append(componentNode)
|
||||
@@ -431,3 +391,5 @@ export const mountCallback = (
|
||||
) => {
|
||||
return () => mount(component, options)
|
||||
}
|
||||
|
||||
setupHooks()
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# [@cypress/webpack-dev-server-v1.1.4](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.1.3...@cypress/webpack-dev-server-v1.1.4) (2021-04-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **webpack:** allow load custom asset on windows ([#16099](https://github.com/cypress-io/cypress/issues/16099)) ([7340851](https://github.com/cypress-io/cypress/commit/7340851097c792ca0d8d3157c3d803dccdd905d2)), closes [#16097](https://github.com/cypress-io/cypress/issues/16097)
|
||||
|
||||
# [@cypress/webpack-dev-server-v1.1.3](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.1.2...@cypress/webpack-dev-server-v1.1.3) (2021-04-13)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import webpack, { Compiler, compilation, Plugin } from 'webpack'
|
||||
import webpack, { Compiler } from 'webpack'
|
||||
import { EventEmitter } from 'events'
|
||||
import _ from 'lodash'
|
||||
import semver from 'semver'
|
||||
@@ -14,11 +14,11 @@ export interface CypressCTOptionsPluginOptions {
|
||||
devServerEvents?: EventEmitter
|
||||
}
|
||||
|
||||
export interface CypressCTWebpackContext extends compilation.Compilation {
|
||||
export interface CypressCTWebpackContext {
|
||||
_cypress: CypressCTOptionsPluginOptions
|
||||
}
|
||||
|
||||
export default class CypressCTOptionsPlugin implements Plugin {
|
||||
export default class CypressCTOptionsPlugin {
|
||||
private files: Cypress.Cypress['spec'][] = []
|
||||
private supportFile: string
|
||||
private errorEmitted = false
|
||||
@@ -33,7 +33,7 @@ export default class CypressCTOptionsPlugin implements Plugin {
|
||||
this.devServerEvents = options.devServerEvents
|
||||
}
|
||||
|
||||
private pluginFunc = (context: CypressCTWebpackContext, module: compilation.Module) => {
|
||||
private pluginFunc = (context: CypressCTWebpackContext) => {
|
||||
context._cypress = {
|
||||
files: this.files,
|
||||
projectRoot: this.projectRoot,
|
||||
@@ -44,7 +44,7 @@ export default class CypressCTOptionsPlugin implements Plugin {
|
||||
private setupCustomHMR = (compiler: webpack.Compiler) => {
|
||||
compiler.hooks.afterCompile.tap(
|
||||
'CypressCTOptionsPlugin',
|
||||
(compilation: compilation.Compilation) => {
|
||||
(compilation) => {
|
||||
const stats = compilation.getStats()
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
@@ -59,7 +59,7 @@ export default class CypressCTOptionsPlugin implements Plugin {
|
||||
|
||||
compiler.hooks.afterEmit.tap(
|
||||
'CypressCTOptionsPlugin',
|
||||
(compilation: compilation.Compilation) => {
|
||||
(compilation) => {
|
||||
if (!compilation.getStats().hasErrors()) {
|
||||
this.devServerEvents.emit('dev-server:compile:success')
|
||||
}
|
||||
@@ -72,7 +72,7 @@ export default class CypressCTOptionsPlugin implements Plugin {
|
||||
* @param compilation webpack 4 `compilation.Compilation`, webpack 5
|
||||
* `Compilation`
|
||||
*/
|
||||
private plugin = (compilation: compilation.Compilation) => {
|
||||
private plugin = (compilation) => {
|
||||
this.devServerEvents.on('dev-server:specs:changed', (specs) => {
|
||||
if (_.isEqual(specs, this.files)) return
|
||||
|
||||
|
||||
@@ -16038,7 +16038,7 @@ enhanced-resolve@4.1.0:
|
||||
memory-fs "^0.4.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0, enhanced-resolve@^4.3.0:
|
||||
enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0, enhanced-resolve@^4.3.0, enhanced-resolve@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
|
||||
integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
|
||||
@@ -35998,16 +35998,7 @@ ts-pnp@1.1.6, ts-pnp@^1.1.2, ts-pnp@^1.1.6:
|
||||
strip-bom "^3.0.0"
|
||||
strip-json-comments "^2.0.0"
|
||||
|
||||
tsconfig-paths-webpack-plugin@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.3.0.tgz#a7461723c20623ca9148621a5ce36532682ad2ff"
|
||||
integrity sha512-MpQeZpwPY4gYASCUjY4yt2Zj8yv86O8f++3Ai4o0yI0fUC6G1syvnL9VuY71PBgimRYDQU47f12BEmJq9wRaSw==
|
||||
dependencies:
|
||||
chalk "^2.3.0"
|
||||
enhanced-resolve "^4.0.0"
|
||||
tsconfig-paths "^3.4.0"
|
||||
|
||||
tsconfig-paths-webpack-plugin@^3.5.1:
|
||||
tsconfig-paths-webpack-plugin@^3.3.0, tsconfig-paths-webpack-plugin@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.1.tgz#e4dbf492a20dca9caab60086ddacb703afc2b726"
|
||||
integrity sha512-n5CMlUUj+N5pjBhBACLq4jdr9cPTitySCjIosoQm0zwK99gmrcTGAfY9CwxRFT9+9OleNWXPRUcxsKP4AYExxQ==
|
||||
@@ -36016,7 +36007,7 @@ tsconfig-paths-webpack-plugin@^3.5.1:
|
||||
enhanced-resolve "^5.7.0"
|
||||
tsconfig-paths "^3.9.0"
|
||||
|
||||
tsconfig-paths@3.9.0, tsconfig-paths@^3.4.0, tsconfig-paths@^3.9.0:
|
||||
tsconfig-paths@3.9.0, tsconfig-paths@^3.9.0:
|
||||
version "3.9.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
|
||||
integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==
|
||||
|
||||
Reference in New Issue
Block a user