Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3f5b69c
automatically polyfill window.fetch with XMLHttpRequest
bahmutov Jun 5, 2020
414cdea
yarn lock
bahmutov Jun 5, 2020
969069f
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 5, 2020
254cc50
Revert "yarn lock"
bahmutov Jun 5, 2020
81e97aa
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 5, 2020
5b579ea
yarn lock for has-binary2
bahmutov Jun 5, 2020
eb4ea44
add test polyfill recipe PR
bahmutov Jun 5, 2020
f96bdeb
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 5, 2020
2ce27ce
removing eval, using this.XMLHttpRequest to inject proper XMLHttpRequ…
JessicaSachs Jun 5, 2020
8f7c9a9
fixing build
JessicaSachs Jun 5, 2020
89cda9a
dev patches
JessicaSachs Jun 5, 2020
0990b4e
try patching differently, doubt it would work
bahmutov Jun 5, 2020
dbbd1a0
merge develop
bahmutov Jun 9, 2020
60063ab
last merge conflict
bahmutov Jun 9, 2020
f2e8988
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 9, 2020
89d13a8
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 9, 2020
30bba54
bind fetch polyfill to content window
bahmutov Jun 9, 2020
10ae257
remake unfetch patch
bahmutov Jun 9, 2020
7902378
Merge branch 'polyfill-fetch' of github.com:cypress-io/cypress into p…
bahmutov Jun 9, 2020
2a85c31
add e2e tests for fetch polyfill
bahmutov Jun 9, 2020
9f59760
switch to fetch constructor away from this
bahmutov Jun 9, 2020
d6aa5b7
update patch file
bahmutov Jun 9, 2020
4494913
Update packages/driver/README.md
bahmutov Jun 9, 2020
6aee0c7
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 10, 2020
2f2e2b7
removed unfetch from root level
bahmutov Jun 10, 2020
d318fb7
adding experimentalFetchPolyfill
bahmutov Jun 10, 2020
135e262
only drop fetch polyfill if experimentalFetchPolyfill is true
bahmutov Jun 10, 2020
4386f7b
enable experimentalFetchPolyfill in the e2e test
bahmutov Jun 10, 2020
df44bdb
set state and add test for no polyfill
bahmutov Jun 10, 2020
28f3e03
add experimentalFetchPolyfill to cypress.json schema
bahmutov Jun 10, 2020
62a8b53
update unit test
bahmutov Jun 10, 2020
05e89b1
Merge branch 'develop' into polyfill-fetch
bahmutov Jun 15, 2020
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
9 changes: 4 additions & 5 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1273,9 +1273,8 @@ jobs:
- test-binary-against-repo:
repo: cypress-example-recipes
command: npm run test:ci
# https://github.com/cypress-io/cypress-example-recipes/pull/501
pull_request_id: 501
folder: examples/unit-testing__lit-element
pull_request_id: 503
folder: examples/stubbing-spying__window-fetch

"test-binary-against-kitchensink":
<<: *defaults
Expand Down Expand Up @@ -1590,11 +1589,11 @@ linux-workflow: &linux-workflow
- build-binary
- build-npm-package
- test-binary-against-recipe-pull-request:
name: Shadow DOM recipe
name: Test fetch polyfill
filters:
branches:
only:
- pull/7469
- polyfill-fetch
requires:
- build-binary
- build-npm-package
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
"pre-commit": "lint-staged"
}
},
"dependencies": {
"unfetch": "4.1.0"
},
"devDependencies": {
"@cypress/bumpercar": "2.0.12",
"@cypress/commit-message-install": "3.1.3",
Expand Down
7 changes: 7 additions & 0 deletions packages/driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ In the browser
localStorage.debug = "cypress:driver"
```

## Patches

- `sinon`
- `unfetch` to polyfill `fetch`. Added `this` and changed function to arrow function to be able to load `fetch` in the spec window, but point the polyfill at the `window.XMLHttpRequest` in the application under test window.

Note: when creating a patch, make sure there is no `package-lock.json` file! Also rename the patch to have ".dev.patch" extension.

<!-- ## Catalog of Events

TODO: this data is accurate but also somewhat out of date.
Expand Down
1 change: 1 addition & 0 deletions packages/driver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"text-mask-addons": "3.8.0",
"underscore": "1.9.1",
"underscore.string": "3.3.5",
"unfetch": "4.1.0",
"url-parse": "1.4.7",
"vanilla-text-mask": "5.1.1",
"wait-on": "3.3.0",
Expand Down
119 changes: 119 additions & 0 deletions packages/driver/patches/unfetch+4.1.0.dev.patch

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/driver/src/cypress/cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const $CommandQueue = require('./command_queue')
const $VideoRecorder = require('../cy/video-recorder')
const $TestConfigOverrides = require('../cy/testConfigOverrides')

const { registerFetch } = require('unfetch')

const privateProps = {
props: { name: 'state', url: true },
privates: { name: 'state', url: false },
Expand Down Expand Up @@ -258,6 +260,10 @@ const create = function (specWindow, Cypress, Cookies, state, config, log) {

contentWindow.CSSStyleSheet.prototype.insertRule = _.wrap(insertRule, cssModificationSpy)
contentWindow.CSSStyleSheet.prototype.deleteRule = _.wrap(deleteRule, cssModificationSpy)

// drop "fetch" polyfill that replaces it with XMLHttpRequest
// from the app iframe that we wrap for network stubbing
contentWindow.fetch = registerFetch(contentWindow)
} catch (error) {} // eslint-disable-line no-empty
}

Expand Down
142 changes: 142 additions & 0 deletions packages/server/test/e2e/8_fetch_polyfill_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
const e2e = require('../support/helpers/e2e').default
const { stripIndent } = require('common-tags')
const bodyParser = require('body-parser')

const onServer = function (app) {
app.use(bodyParser.json({ extended: false }))

app.get('/get-json', (req, res) => {
return res.json([1, 2, 3])
})

app.get('/get-text', (req, res) => {
return res.send('pong')
})

app.post('/add', (req, res) => {
if (req.body.method !== 'add') {
throw new Error('wrong body method')
}

return res.json({ answer: req.body.a + req.body.b })
})

// page posts a JSON object
app.get('/addition', (req, res) => {
return res.send(stripIndent`
<body>
<div id="result"></div>
<script>
const data = {
method: 'add',
a: 2,
b: 15
}
fetch('/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then((response) => {
if (!response) {
throw new Error('no response')
}
if (!response.ok) {
throw new Error('response is not ok')
}
return response.json()
}).then(j => {
// either answer from the server
// or from the network stub
if (j.answer !== 17 && j.answer !== 193) {
throw new Error('wrong answer')
}
document.getElementById('result').innerText = 'answer: ' + j.answer
})
</script>
</body>
`)
})

// page fetches JSON array
app.get('/first', (req, res) => {
return res.send(stripIndent`
<body>
<script>
fetch('/get-json')
.then((response) => {
if (!response) {
throw new Error('no response')
}
if (!response.ok) {
throw new Error('response is not ok')
}
return response.json()
})
.then((list) => {
if (list.length !== 3) {
throw new Error('Wrong number of items')
}
if (list[0] !== 1) {
throw new Error('Wrong first item')
}
if (list[1] !== 2) {
throw new Error('Wrong second item')
}
if (list[2] !== 3) {
throw new Error('Wrong third item')
}
})
</script>
<a href="/second">second</a>
</body>
`)
})

// page fetches text
app.get('/second', (req, res) => {
return res.send(stripIndent`
<body>
<div id="result"></div>
<script>
fetch('/get-text')
.then((response) => {
if (!response) {
throw new Error('no response')
}
if (!response.ok) {
throw new Error('response is not ok')
}
if (response.status !== 200) {
throw new Error('response status not 200')
}
return response.text()
})
.then((text) => {
// allow response from the server
// or stub response
if (text !== 'pong' && text !== 'mock pong') {
throw new Error('Wrong text response')
}
document.getElementById('result').innerText = 'text: ' + text
})
</script>
</body>
`)
})
}

describe('e2e fetch polyfill', () => {
e2e.setup({
servers: {
port: 1818,
onServer,
},
})

e2e.it('passes', {
spec: 'fetch_spec.coffee',
snapshot: false,
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
describe "fetch works", ->
it "spies on fetch requests", ->
cy.server()
cy.route("/get-json").as("get-json")
cy.visit("http://localhost:1818/first")
cy.wait("@get-json")

it "spies on fetch requests from second page", ->
cy.server()
cy.route("/get-text").as("get-text")
cy.visit("http://localhost:1818/first")
cy.contains("a", "second").click()
cy.wait("@get-text")
# confirm the real response from the server is shown
cy.contains("text: pong").should("be.visible")

it "stubs GET fetch text", ->
cy.server()
cy.route("/get-text", "mock pong")
cy.visit("http://localhost:1818/second")
# confirm the stub response is shown
cy.contains("text: mock pong").should("be.visible")

it "spies on fetch POST", ->
cy.server()
cy.route("POST", "/add").as("add")
cy.visit("http://localhost:1818/addition")
cy.wait("@add")
# confirm the response from the server is displayed
cy.contains("answer: 17").should('be.visible')

it "stubs fetch POST", ->
cy.server()
cy.route("POST", "/add", {answer: 193}).as("add")
cy.visit("http://localhost:1818/addition")
cy.wait("@add")
# confirm the stub was used
cy.contains("answer: 193").should('be.visible')

5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -24721,6 +24721,11 @@ undertaker@^1.2.1:
object.reduce "^1.0.0"
undertaker-registry "^1.0.0"

[email protected]:
version "4.1.0"
resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db"
integrity sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg==

unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
Expand Down