Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove some CT functions and props #24419

Merged
merged 33 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1b53465
fix: remove mountHook function for React
astone123 Oct 26, 2022
57017e3
fix: remove `unmount` from @cypress/react exports
astone123 Oct 26, 2022
5a8d20f
fix: remove `unmount` from the @cypress/react readme
astone123 Oct 26, 2022
18dbb15
fix: don't alias React components on mount
astone123 Oct 26, 2022
1b85c21
fix: remove `mountCallback` from Vue adapters
astone123 Oct 26, 2022
5a5b4b7
fix: remove style injection utility functions from `mount-utils`
astone123 Oct 26, 2022
5aef766
fix: fix React tests
astone123 Oct 26, 2022
ad3c939
fix: fix more React tests
astone123 Oct 26, 2022
d29b7db
fix: fix more tests
astone123 Oct 26, 2022
59c43e4
fix: fix screenshot test styles
astone123 Oct 27, 2022
8821316
fix: update documentation around mount-utils styles; fix tests
astone123 Oct 27, 2022
eaec2e7
fix: update Vue docs to use `props` key rather than `propsData`
astone123 Oct 27, 2022
732baf4
Merge branch 'release/11.0.0' into astone123/ct-functionality
astone123 Oct 27, 2022
8f4be07
fix: add test styles back in
astone123 Oct 27, 2022
56ce83d
Merge branch 'astone123/ct-functionality' of github.com:cypress-io/cy…
astone123 Oct 27, 2022
b253b7f
update unmount test and export getContainerEl for back compat
lmiller1990 Nov 1, 2022
e8af254
better errors
lmiller1990 Nov 1, 2022
08a1e49
docs
lmiller1990 Nov 1, 2022
c6063ae
error for unmount
lmiller1990 Nov 1, 2022
5344f19
test for error
lmiller1990 Nov 1, 2022
bd54572
fix last test
lmiller1990 Nov 1, 2022
3941029
adjust language to reflect removed methods
lmiller1990 Nov 2, 2022
50cdbc8
one last deprecation
lmiller1990 Nov 2, 2022
699ef5e
fix error
lmiller1990 Nov 2, 2022
f37ba0b
Merge remote-tracking branch 'origin/release/11.0.0' into astone123/c…
lmiller1990 Nov 3, 2022
a809f4f
wip - [skip ci]
lmiller1990 Nov 3, 2022
299efd8
use proxy to catch errors
lmiller1990 Nov 3, 2022
e4b9943
deprecate alias
lmiller1990 Nov 3, 2022
4af263a
update tests
lmiller1990 Nov 3, 2022
b6ac980
update on link
lmiller1990 Nov 3, 2022
6e98295
use on links properly
lmiller1990 Nov 3, 2022
ead16d1
Merge branch 'release/11.0.0' of github.com:cypress-io/cypress into a…
astone123 Nov 3, 2022
bc9d8cd
revert changes
lmiller1990 Nov 4, 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
28 changes: 5 additions & 23 deletions npm/mount-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ All the functionality used to create the first party Mount adapters is available

In addition, we recommend that Mount Adapters:

- receive a second argument that extends `StyleOptions` from `@cypress/mount-utils`
- calls `injectStylesBeforeElement` from `@cypress/mount-utils` before mounting the component
- calls `setupHooks` to register the required lifecycle hooks for `@cypress/mount-utils` to work

This will let the user inject styles `<style>...</style>` and stylesheets `<link rel="stylesheet">`, which is very useful for developing components.
- call `setupHooks` to register the required lifecycle hooks for `@cypress/mount-utils` to work

### Example Mount Adapter: Web Components

Expand All @@ -39,9 +35,7 @@ Here's a simple yet realistic example of Mount Adapter targeting Web Components.
import {
ROOT_SELECTOR,
setupHooks,
injectStylesBeforeElement,
getContainerEl,
StyleOptions
getContainerEl
} from "@cypress/mount-utils";

Cypress.on("run:start", () => {
Expand Down Expand Up @@ -69,8 +63,7 @@ function maybeRegisterComponent<T extends CustomElementConstructor>(
}

export function mount(
webComponent: CustomElementConstructor,
options?: Partial<StyleOptions>
webComponent: CustomElementConstructor
): Cypress.Chainable {
// Get root selector defined in `cypress/support.component-index.html
const $root = document.querySelector(ROOT_SELECTOR)!;
Expand All @@ -83,9 +76,6 @@ export function mount(
/// Register Web Component
maybeRegisterComponent(name, webComponent);

// Inject user styles before mounting the component
injectStylesBeforeElement(options ?? {}, document, getContainerEl())

// Render HTML containing component.
$root.innerHTML = `<${name} id="root"></${name}>`;

Expand All @@ -100,8 +90,7 @@ export function mount(
return cy.wrap(document.querySelector("#root"), { log: false });
}

// Setup Cypress lifecycle hooks. This tears down any styles
// injected by injectStylesBeforeElement, etc.
// Setup Cypress lifecycle hooks.
setupHooks();
```

Expand Down Expand Up @@ -131,14 +120,7 @@ export class WebCounter extends HTMLElement {

describe('web-component.cy.ts', () => {
it('playground', () => {
cy.mount(WebCounter, {
styles: `
button {
background: lightblue;
color: white;
}
`
})
cy.mount(WebCounter)
})
})
```
Expand Down
225 changes: 35 additions & 190 deletions npm/mount-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,3 @@
/**
lmiller1990 marked this conversation as resolved.
Show resolved Hide resolved
* 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_SELECTOR = '[data-cy-root]'

export const getContainerEl = (): HTMLElement => {
Expand All @@ -49,156 +10,6 @@ export const getContainerEl = (): HTMLElement => {
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`)
}

/**
* 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.
*/
function insertStylesheets (
stylesheets: string[],
document: Document,
el: HTMLElement | null,
) {
stylesheets.forEach((href) => {
const link = document.createElement('link')

link.type = 'text/css'
link.rel = 'stylesheet'
link.href = href
link.dataset.cy = 'injected-stylesheet'
document.body.insertBefore(link, el)
})
}

/**
* Inserts a single stylesheet element
*/
function insertStyles (styles: string[], document: Document, el: HTMLElement | null) {
styles.forEach((style) => {
const styleElement = document.createElement('style')

styleElement.dataset.cy = 'injected-style-tag'
styleElement.appendChild(document.createTextNode(style))
document.body.insertBefore(styleElement, el)
})
}

function insertSingleCssFile (
cssFilename: string,
document: Document,
el: HTMLElement | null,
log?: boolean,
) {
return cy.readFile(cssFilename, { log }).then((css) => {
const style = document.createElement('style')

style.appendChild(document.createTextNode(css))
document.body.insertBefore(style, el)
})
}

/**
* Reads the given CSS file from local file system
* and adds the loaded style text as an element.
*/
function insertLocalCssFiles (
cssFilenames: string[],
document: Document,
el: HTMLElement | null,
log?: boolean,
) {
return Cypress.Promise.mapSeries(cssFilenames, (cssFilename) => {
return insertSingleCssFile(cssFilename, document, el, log)
})
}

/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*/
export const injectStylesBeforeElement = (
options: Partial<StyleOptions & { log: boolean }>,
document: Document,
el: HTMLElement | null,
): HTMLElement => {
if (!el) return

// first insert all stylesheets as Link elements
let stylesheets: string[] = []

if (typeof options.stylesheet === 'string') {
stylesheets.push(options.stylesheet)
} else if (Array.isArray(options.stylesheet)) {
stylesheets = stylesheets.concat(options.stylesheet)
}

if (typeof options.stylesheets === 'string') {
options.stylesheets = [options.stylesheets]
}

if (options.stylesheets) {
stylesheets = stylesheets.concat(options.stylesheets)
}

insertStylesheets(stylesheets, document, el)

// insert any styles as <style>...</style> elements
let styles: string[] = []

if (typeof options.style === 'string') {
styles.push(options.style)
} else if (Array.isArray(options.style)) {
styles = styles.concat(options.style)
}

if (typeof options.styles === 'string') {
styles.push(options.styles)
} else if (Array.isArray(options.styles)) {
styles = styles.concat(options.styles)
}

insertStyles(styles, document, el)

// now load any css files by path and add their content
// as <style>...</style> elements
let cssFiles: string[] = []

if (typeof options.cssFile === 'string') {
cssFiles.push(options.cssFile)
} else if (Array.isArray(options.cssFile)) {
cssFiles = cssFiles.concat(options.cssFile)
}

if (typeof options.cssFiles === 'string') {
cssFiles.push(options.cssFiles)
} else if (Array.isArray(options.cssFiles)) {
cssFiles = cssFiles.concat(options.cssFiles)
}

return insertLocalCssFiles(cssFiles, document, el, options.log)
}

export function setupHooks (optionalCallback?: Function) {
// Consumed by the framework "mount" libs. A user might register their own mount in the scaffolded 'commands.js'
// file that is imported by e2e and component support files by default. We don't want CT side effects to run when e2e
Expand All @@ -220,6 +31,40 @@ export function setupHooks (optionalCallback?: Function) {
// @ts-ignore
Cypress.on('test:before:run', () => {
optionalCallback?.()
cleanupStyles()
})
}

/**
* Remove any style or extra link elements from the iframe placeholder
* left from any previous test
*
* @ Removed as of Cypress 11.0.0
astone123 marked this conversation as resolved.
Show resolved Hide resolved
*/
export function cleanupStyles () {
astone123 marked this conversation as resolved.
Show resolved Hide resolved
throw new Error('cleanupStyles is no longer supported. See https://docs.cypress.io/guides/references/migration-guide#Component-Testing-Changes to migrate.')
}

/**
* Additional styles to inject into the document.
* A component might need 3rd party libraries from CDN,
* local CSS files and custom styles.
*
* Removed as of Cypress 11.0.0.
* @see https://docs.cypress.io/guides/references/migration-guide#Component-Testing-Changes
*/
export type StyleOptions = unknown

/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*
* Removed as of Cypress 11.0.0.
* @see https://docs.cypress.io/guides/references/migration-guide#Component-Testing-Changes
*/
export const injectStylesBeforeElement = (
options: Partial<StyleOptions & { log: boolean }>,
document: Document,
el: HTMLElement | null,
): HTMLElement => {
throw new Error('injectStylesBeforeElement is no longer supported. See https://docs.cypress.io/guides/references/migration-guide#Component-Testing-Changes to migrate.')
}
24 changes: 2 additions & 22 deletions npm/react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ For more information, please check the official docs for [running Cypress](https

- `mount` is the most important function, allows to mount a given React component as a mini web application and interact with it using Cypress commands
- `createMount` factory function that creates new `mount` function with default options
- `unmount` removes previously mounted component, mostly useful to test how the component cleans up after itself
- `mountHook` mounts a given React Hook in a test component for full testing, see `hooks` example

## Examples

Expand Down Expand Up @@ -65,20 +63,7 @@ it('looks right', () => {
})
```

### Extra styles

You can pass additional styles, css files and external stylesheets to load, see [docs/styles.md](./docs/styles.md) for the full list of options.

```js
const todo = {
id: '123',
title: 'Write more tests',
}
mount(<Todo todo={todo} />, {
stylesheets: [
'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
],
})
See [docs/styles.md](./docs/styles.md) for full list of options.
```

You may also specify the `ReactDOM` package to use. This can be useful in complex monorepo setups that have different versions of React and React DOM installed. If you see an error relating to [mismatching versions of React or React DOM](https://reactjs.org/warnings/invalid-hook-call-warning.html#mismatching-versions-of-react-and-react-dom), this may be the solution. You can do this using the `ReactDom` option:
Expand All @@ -87,12 +72,7 @@ You may also specify the `ReactDOM` package to use. This can be useful in comple
// if you have multiple versions of ReactDom in your monorepo
import ReactDom from 'react-dom'

mount(<Todo todo={todo} />, {
stylesheets: [
'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
],
ReactDom
})
mount(<Todo todo={todo} />, { reactDom: ReactDom })
```

## Compatibility
Expand Down
7 changes: 1 addition & 6 deletions npm/react/cypress/component/advanced/hooks/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
# testing React hooks

- [counter-with-hooks.spec.js](counter-with-hooks.spec.js) and [counter2-with-hooks.spec.js](counter2-with-hooks.spec.js) test React components that uses hooks
- [use-counter.spec.js](use-counter.spec.js) shows how to test a React hook using `mountHook` function

![Hook test](images/hook.png)

Note: hooks are mounted inside a test component following the approach shown in [react-hooks-testing-library](https://github.com/testing-library/react-hooks-testing-library/blob/master/src/pure.js)
- [counter-with-hooks.spec.js](counter-with-hooks.spec.js) and [counter2-with-hooks.spec.js](counter2-with-hooks.spec.js) test React components that uses hooks
Binary file not shown.
25 changes: 0 additions & 25 deletions npm/react/cypress/component/advanced/hooks/use-counter.cy.jsx

This file was deleted.

Loading