Skip to content

Commit

Permalink
fix: support ressources with relative paths
Browse files Browse the repository at this point in the history
  • Loading branch information
fochlac committed Jun 4, 2023
1 parent 9d4a3d2 commit 5e4d02e
Show file tree
Hide file tree
Showing 15 changed files with 4,450 additions and 16 deletions.
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ _Released 05/14/2023 (PENDING)_

- Reverted [#26452](/~https://github.com/cypress-io/cypress/pull/26630) which introduced a bug that prevents users from using End to End with Yarn 3. Fixed in [#26735](/~https://github.com/cypress-io/cypress/pull/26735). Fixes [#26676](/~https://github.com/cypress-io/cypress/issues/26676).
- Moved `types` condition to the front of `package.json#exports` since keys there are meant to be order-sensitive. Fixed in [#26630](/~https://github.com/cypress-io/cypress/pull/26630).
- Write spec-path to aut-iframe query parameter instead of path to allow for proper forwarding relative asset requests to the devserver. Fixed in [#26844](/~https://github.com/cypress-io/cypress/pull/26844).

## 12.12.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ describe('React Memory Router', () => {
cy.log('**About** component')
cy.contains('h2', 'About')
// because the routing is in memory, the URL stays at the spec filename
cy.location('pathname').should('match', /in-memory.cy.jsx$/)
cy.location('search').should('match', /in-memory.cy.jsx$/)

// Go to home route
cy.contains('a', 'Home').click()

cy.log('**Home** component')
cy.contains('h2', 'Home') // from the "Home" component
// still at the spec url
cy.location('pathname').should('match', /in-memory.cy.jsx$/)
cy.location('search').should('match', /in-memory.cy.jsx$/)

// Go to about route
cy.log('back to **About** component')
cy.contains('a', 'About').click()

cy.contains('h2', 'About')
// still at the spec url
cy.location('pathname').should('match', /in-memory.cy.jsx$/)
cy.location('search').should('match', /in-memory.cy.jsx$/)
})
})
2 changes: 1 addition & 1 deletion npm/react/cypress/component/basic/window.cy.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ it('has the same window from the component as from test', () => {
mount(<Component />)
cy.contains('component')
cy.window()
.its('location.pathname')
.its('location.search')
// this filename
.should('match', /window.cy.jsx$/)

Expand Down
4 changes: 2 additions & 2 deletions npm/webpack-dev-server/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const makeImport = (file: Cypress.Cypress['spec'], filename: string, chunkName:
const magicComments = chunkName ? `/* webpackChunkName: "${chunkName}" */` : ''

return `"${filename}": {
shouldLoad: () => decodeURI(document.location.pathname).includes("${file.absolute}"),
shouldLoad: () => (new URL(document.location)).searchParams.get("specPath") === "${file.absolute}",
load: () => import("${file.absolute}" ${magicComments}),
absolute: "${file.absolute.split(path.sep).join(path.posix.sep)}",
relative: "${file.relative.split(path.sep).join(path.posix.sep)}",
Expand All @@ -33,7 +33,7 @@ const makeImport = (file: Cypress.Cypress['spec'], filename: string, chunkName:
* @returns {Record<string, ReturnType<makeImport>}
* {
* "App.spec.js": {
* shouldLoad: () => document.location.pathname.includes("cypress/component/App.spec.js"),
* shouldLoad: () => (new URL(document.location)).searchParams.get("specPath") === "cypress/component/App.spec.js",
* load: () => {
* return import("/Users/projects/my-app/cypress/component/App.spec.js" \/* webpackChunkName: "spec-0" *\/)
* },
Expand Down
5 changes: 4 additions & 1 deletion packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,10 @@ function runSpecCT (config, spec: SpecFile) {
const autIframe = getAutIframeModel()
const $autIframe: JQuery<HTMLIFrameElement> = autIframe.create().appendTo($container)

const specSrc = getSpecUrl(config.namespace, spec.absolute)
// the iframe controller will forward the specpath via header to the devserver.
// using a query parameter allows us to recognize relative requests and proxy them to the devserver.
const specIndexUrl = `index.html?specPath=${encodeURI(spec.absolute)}`
const specSrc = getSpecUrl(config.namespace, specIndexUrl)

autIframe._showInitialBlankPage()
$autIframe.prop('src', specSrc)
Expand Down
22 changes: 14 additions & 8 deletions packages/server/lib/controllers/iframes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,20 @@ export const iframesController = {
},

component: ({ config, nodeProxy }: CT, req: Request, res: Response) => {
// always proxy to the index.html file
// attach header data for webservers
// to properly intercept and serve assets from the correct src root
// TODO: define a contract for dev-server plugins to configure this behavior
req.headers.__cypress_spec_path = encodeURI(req.params[0])
req.url = `${config.devServerPublicPathRoute}/index.html`

// user the node proxy here instead of the network proxy
// requests to the index.html are from initializing the iframe. They include the specPath as query parameter
const specPath = req.query.specPath

if (typeof specPath === 'string') {
// for those requests we need to provide the spec-path via this header
req.headers.__cypress_spec_path = encodeURI(specPath)
req.url = `${config.devServerPublicPathRoute}/index.html`
delete req.query.specPath
} else {
// all requests should be forwarded to the devserver, preserving there relative paths so assets with relative urls work.
req.url = `${config.devServerPublicPathRoute}/${req.params[0]}`
}

// use the node proxy here instead of the network proxy
// to avoid the user accidentally intercepting and modifying
// our internal index.html handler

Expand Down
2 changes: 1 addition & 1 deletion system-tests/lib/dep-installer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function getRelativePathToProjectDir (projectDir: string) {
async function restoreLockFileRelativePaths (opts: { projectDir: string, lockFilePath: string, relativePathToMonorepoRoot: string }) {
const relativePathToProjectDir = getRelativePathToProjectDir(opts.projectDir)
const lockFileContents = (await fs.readFile(opts.lockFilePath, 'utf8'))
.replaceAll(opts.relativePathToMonorepoRoot, relativePathToProjectDir)
.replaceAll(opts.relativePathToMonorepoRoot.replace(/\\+/g, '/'), relativePathToProjectDir.replace(/\\+/g, '/'))

await fs.writeFile(opts.lockFilePath, lockFileContents)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { defineConfig } = require('cypress')

module.exports = defineConfig({
component: {
experimentalSingleTabRunMode: true,
supportFile: false,
devServer: {
bundler: 'webpack',
},
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>
24 changes: 24 additions & 0 deletions system-tests/projects/webpack-dev-server-relative/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "ct-webpack-relative",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7",
"@babel/preset-react": "^7",
"@cypress/webpack-dev-server": "file:../../../npm/webpack-dev-server",
"babel-loader": "^8.2.4",
"copy-webpack-plugin": "11.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"webpack": "^5.74.0",
"webpack-dev-server": "^4.11.1"
},
"license": "ISC",
"author": "",
"keywords": []
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'
import { mount } from 'cypress/react'

describe('webpack-dev-server', () => {
it('image with relative path should load', () => {
mount(<img src="./quak.png" />)
cy.get('img').should('be.visible').then(($img) => {
expect($img[0].naturalWidth).to.be.greaterThan(0)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const CopyPlugin = require('copy-webpack-plugin')

module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react'],
},
},
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{ from: './src/quak.png', to: 'quak.png' },
],
}),
],
}
Loading

0 comments on commit 5e4d02e

Please sign in to comment.