diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 2085c9b154de..77cf6c77892b 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -7,6 +7,7 @@ _Released 12/3/2024 (PENDING)_ - Removed support for Node.js 16 and Node.js 21. Addresses [#29930](https://github.com/cypress-io/cypress/issues/29930). - Prebuilt binaries for Linux are no longer compatible with Linux distributions based on glibc <2.28, for example: Ubuntu 14-18, RHEL 7, CentOS 7, Amazon Linux 2. Addresses [#29601](https://github.com/cypress-io/cypress/issues/29601). +- The `experimentalFetchPolyfill` configuration option was removed. This option was deprecated in Cypress 6.0.0. We recommend using `cy.intercept()` for handling fetch requests. Addressed in [#30466](https://github.com/cypress-io/cypress/pull/30466). - We removed yielding the second argument of `before:browser:launch` as an array of browser arguments. This behavior has been deprecated since Cypress 4.0.0. Addressed in [#30460](https://github.com/cypress-io/cypress/pull/30460). - The `cypress open-ct` and `cypress run-ct` CLI commands were removed. Please use `cypress open --component` or `cypress run --component` respectively instead. Addressed in [#30456](https://github.com/cypress-io/cypress/pull/30456) - The undocumented methods `Cypress.backend('firefox:force:gc')` and `Cypress.backend('log:memory:pressure')` were removed. Addresses [#30222](https://github.com/cypress-io/cypress/issues/30222). diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index adbabd3f5cc2..49369e731007 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -3181,10 +3181,6 @@ declare namespace Cypress { * The user agent the browser sends in all request headers. */ userAgent: null | string - /** - * Polyfills `window.fetch` to enable Network spying and stubbing - */ - experimentalFetchPolyfill: boolean /** * Override default config options for Component Testing runner. diff --git a/npm/react/cypress.config.js b/npm/react/cypress.config.js index 2764f9c4c037..6dbae3753b06 100644 --- a/npm/react/cypress.config.js +++ b/npm/react/cypress.config.js @@ -5,7 +5,6 @@ module.exports = { 'env': { 'reactDevtools': true, }, - 'experimentalFetchPolyfill': true, 'component': { experimentalSingleTabRunMode: true, 'excludeSpecPattern': [ diff --git a/npm/react/cypress/component/basic/network/README.md b/npm/react/cypress/component/basic/network/README.md index 2d1c2eea9bd8..a5d90d66d20a 100644 --- a/npm/react/cypress/component/basic/network/README.md +++ b/npm/react/cypress/component/basic/network/README.md @@ -1,4 +1,3 @@ # Mocking network - [1-users-spec.js](1-users-spec.js) tests [1-users.jsx](1-users.jsx) that uses Axios to GET a list of users. Axios uses XMLHttpRequest to receive the data -- [2-users-fetch-spec.js](2-users-fetch-spec.js) tests [2-users-fetch.jsx](2-users-fetch.jsx) that uses `fetch` directly, assuming `"experimentalFetchPolyfill": true` in `cypress.json`, read [Experimental Fetch Polyfill](https://www.cypress.io/blog/2020/06/29/experimental-fetch-polyfill/) diff --git a/npm/vue/cypress.config.ts b/npm/vue/cypress.config.ts index d4c8b1be979c..35f6d7cc2298 100644 --- a/npm/vue/cypress.config.ts +++ b/npm/vue/cypress.config.ts @@ -5,7 +5,6 @@ export default defineConfig({ 'viewportHeight': 500, 'responseTimeout': 2500, 'projectId': '134ej7', - 'experimentalFetchPolyfill': true, 'e2e': { 'supportFile': false, }, diff --git a/packages/app/cypress/e2e/settings.cy.ts b/packages/app/cypress/e2e/settings.cy.ts index df69f27d2576..3ce10688a29a 100644 --- a/packages/app/cypress/e2e/settings.cy.ts +++ b/packages/app/cypress/e2e/settings.cy.ts @@ -183,13 +183,6 @@ describe('App: Settings', () => { href: 'https://on.cypress.io/experiments', }) - cy.get('[data-cy="experiment-experimentalFetchPolyfill"]').within(() => { - cy.validateExternalLink({ - name: 'cy.intercept()', - href: 'https://on.cypress.io/intercept', - }) - }) - cy.get('[data-cy="experiment-experimentalInteractiveRunEvents"]').within(() => { cy.validateExternalLink({ name: 'before:run', diff --git a/packages/config/__snapshots__/index.spec.ts.js b/packages/config/__snapshots__/index.spec.ts.js index c366c3230ee0..9d6ca3731f71 100644 --- a/packages/config/__snapshots__/index.spec.ts.js +++ b/packages/config/__snapshots__/index.spec.ts.js @@ -34,7 +34,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1 'env': {}, 'execTimeout': 60000, 'experimentalCspAllowList': false, - 'experimentalFetchPolyfill': false, 'experimentalInteractiveRunEvents': false, 'experimentalRunAllSpecs': false, 'experimentalMemoryManagement': false, @@ -125,7 +124,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys f 'env': {}, 'execTimeout': 60000, 'experimentalCspAllowList': false, - 'experimentalFetchPolyfill': false, 'experimentalInteractiveRunEvents': false, 'experimentalRunAllSpecs': false, 'experimentalMemoryManagement': false, @@ -212,7 +210,6 @@ exports['config/src/index .getPublicConfigKeys returns list of public config key 'env', 'execTimeout', 'experimentalCspAllowList', - 'experimentalFetchPolyfill', 'experimentalInteractiveRunEvents', 'experimentalRunAllSpecs', 'experimentalMemoryManagement', diff --git a/packages/config/src/options.ts b/packages/config/src/options.ts index 87bfa61496d0..c9e4d9e7702d 100644 --- a/packages/config/src/options.ts +++ b/packages/config/src/options.ts @@ -203,11 +203,6 @@ const driverConfigOptions: Array = [ validation: validate.validateAny(validate.isBoolean, validate.isArrayIncludingAny('script-src-elem', 'script-src', 'default-src', 'form-action', 'child-src', 'frame-src')), overrideLevel: 'never', requireRestartOnChange: 'server', - }, { - name: 'experimentalFetchPolyfill', - defaultValue: false, - validation: validate.isBoolean, - isExperimental: true, }, { name: 'experimentalInteractiveRunEvents', defaultValue: false, diff --git a/packages/config/test/project/utils.spec.ts b/packages/config/test/project/utils.spec.ts index 0a3ee14c76b8..ffa0f49001b0 100644 --- a/packages/config/test/project/utils.spec.ts +++ b/packages/config/test/project/utils.spec.ts @@ -1062,7 +1062,6 @@ describe('config/src/project/utils', () => { experimentalSkipDomainInjection: { value: null, from: 'default' }, experimentalJustInTimeCompile: { value: false, from: 'default' }, experimentalCspAllowList: { value: false, from: 'default' }, - experimentalFetchPolyfill: { value: false, from: 'default' }, experimentalInteractiveRunEvents: { value: false, from: 'default' }, experimentalMemoryManagement: { value: false, from: 'default' }, experimentalOriginDependencies: { value: false, from: 'default' }, @@ -1159,7 +1158,6 @@ describe('config/src/project/utils', () => { experimentalSkipDomainInjection: { value: null, from: 'default' }, experimentalJustInTimeCompile: { value: false, from: 'default' }, experimentalCspAllowList: { value: false, from: 'default' }, - experimentalFetchPolyfill: { value: false, from: 'default' }, experimentalInteractiveRunEvents: { value: false, from: 'default' }, experimentalMemoryManagement: { value: false, from: 'default' }, experimentalOriginDependencies: { value: false, from: 'default' }, diff --git a/packages/data-context/src/sources/migration/legacyOptions.ts b/packages/data-context/src/sources/migration/legacyOptions.ts index cebec2fde419..c0cd4ba8da2a 100644 --- a/packages/data-context/src/sources/migration/legacyOptions.ts +++ b/packages/data-context/src/sources/migration/legacyOptions.ts @@ -86,11 +86,6 @@ const resolvedOptions: Array = [ name: 'exit', defaultValue: true, canUpdateDuringTestTime: false, - }, { - name: 'experimentalFetchPolyfill', - defaultValue: false, - isExperimental: true, - canUpdateDuringTestTime: false, }, { name: 'experimentalInteractiveRunEvents', defaultValue: false, diff --git a/packages/driver/README.md b/packages/driver/README.md index 1c469c7a1145..0d9967f5775e 100644 --- a/packages/driver/README.md +++ b/packages/driver/README.md @@ -46,9 +46,6 @@ Note: you may need to enable "Verbose" or "Debug" log levels inside the browser' ## Patches -- `sinon` -- `unfetch` to polyfill `fetch`. Added constructor function to point XMLHttpRequest to 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. ## Cross-origin Testing diff --git a/packages/driver/package.json b/packages/driver/package.json index 3547683eade9..ab8cb0ecaaef 100644 --- a/packages/driver/package.json +++ b/packages/driver/package.json @@ -77,7 +77,6 @@ "source-map": "0.8.0-beta.0", "text-mask-addons": "3.8.0", "underscore.string": "3.3.6", - "unfetch": "4.1.0", "url-parse": "1.5.10", "vanilla-text-mask": "5.1.1", "vite": "5.2.11", diff --git a/packages/driver/patches/unfetch+4.1.0.dev.patch b/packages/driver/patches/unfetch+4.1.0.dev.patch deleted file mode 100644 index 5361b2a5644e..000000000000 --- a/packages/driver/patches/unfetch+4.1.0.dev.patch +++ /dev/null @@ -1,130 +0,0 @@ -diff --git a/node_modules/unfetch/dist/unfetch.es.js b/node_modules/unfetch/dist/unfetch.es.js -deleted file mode 100644 -index af22f48..0000000 ---- a/node_modules/unfetch/dist/unfetch.es.js -+++ /dev/null -@@ -1,2 +0,0 @@ --export default function(e,n){return n=n||{},new Promise(function(t,r){var s=new XMLHttpRequest,o=[],u=[],i={},a=function(){return{ok:2==(s.status/100|0),statusText:s.statusText,status:s.status,url:s.responseURL,text:function(){return Promise.resolve(s.responseText)},json:function(){return Promise.resolve(JSON.parse(s.responseText))},blob:function(){return Promise.resolve(new Blob([s.response]))},clone:a,headers:{keys:function(){return o},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var l in s.open(n.method||"get",e,!0),s.onload=function(){s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){o.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(a())},s.onerror=r,s.withCredentials="include"==n.credentials,n.headers)s.setRequestHeader(l,n.headers[l]);s.send(n.body||null)})} --//# sourceMappingURL=unfetch.mjs.map -diff --git a/node_modules/unfetch/dist/unfetch.es.js.map b/node_modules/unfetch/dist/unfetch.es.js.map -deleted file mode 100644 -index efa624a..0000000 ---- a/node_modules/unfetch/dist/unfetch.es.js.map -+++ /dev/null -@@ -1 +0,0 @@ --{"version":3,"file":"unfetch.es.js","sources":["../src/index.js"],"sourcesContent":["export default typeof fetch=='function' ? fetch.bind() : function(url, options) {\n\toptions = options || {};\n\treturn new Promise( (resolve, reject) => {\n\t\tlet request = new XMLHttpRequest();\n\n\t\trequest.open(options.method || 'get', url, true);\n\n\t\tfor (let i in options.headers) {\n\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t}\n\n\t\trequest.withCredentials = options.credentials=='include';\n\n\t\trequest.onload = () => {\n\t\t\tresolve(response());\n\t\t};\n\n\t\trequest.onerror = reject;\n\n\t\trequest.send(options.body || null);\n\n\t\tfunction response() {\n\t\t\tlet keys = [],\n\t\t\t\tall = [],\n\t\t\t\theaders = {},\n\t\t\t\theader;\n\n\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\tkeys.push(key = key.toLowerCase());\n\t\t\t\tall.push([key, value]);\n\t\t\t\theader = headers[key];\n\t\t\t\theaders[key] = header ? `${header},${value}` : value;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tok: (request.status/100|0) == 2,\t\t// 200-299\n\t\t\t\tstatus: request.status,\n\t\t\t\tstatusText: request.statusText,\n\t\t\t\turl: request.responseURL,\n\t\t\t\tclone: response,\n\t\t\t\ttext: () => Promise.resolve(request.responseText),\n\t\t\t\tjson: () => Promise.resolve(request.responseText).then(JSON.parse),\n\t\t\t\tblob: () => Promise.resolve(new Blob([request.response])),\n\t\t\t\theaders: {\n\t\t\t\t\tkeys: () => keys,\n\t\t\t\t\tentries: () => all,\n\t\t\t\t\tget: n => headers[n.toLowerCase()],\n\t\t\t\t\thas: n => n.toLowerCase() in headers\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n"],"names":["let"],"mappings":"AAAA,YAAe,OAAO,KAAK,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,SAAS,GAAG,EAAE,OAAO,EAAE;CAC/E,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;CACxB,OAAO,IAAI,OAAO,EAAE,UAAC,OAAO,EAAE,MAAM,EAAE;EACrCA,IAAI,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;;EAEnC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;;EAEjD,KAAKA,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;GAChD;;EAED,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC;;EAEzD,OAAO,CAAC,MAAM,GAAG,YAAG;GACnB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;GACpB,CAAC;;EAEF,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC;;EAEzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;;EAEnC,SAAS,QAAQ,GAAG;GACnBA,IAAI,IAAI,GAAG,EAAE;IACZ,GAAG,GAAG,EAAE;IACR,OAAO,GAAG,EAAE;IACZ,MAAM,CAAC;;GAER,OAAO,CAAC,qBAAqB,EAAE,CAAC,OAAO,CAAC,8BAA8B,EAAE,UAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE;IACvF,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACnC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACvB,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAG,MAAS,MAAE,GAAE,KAAK,IAAK,KAAK,CAAC;IACrD,CAAC,CAAC;;GAEH,OAAO;IACN,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9B,GAAG,EAAE,OAAO,CAAC,WAAW;IACxB,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,YAAG,SAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAA;IACjD,IAAI,EAAE,YAAG,SAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAA;IAClE,IAAI,EAAE,YAAG,SAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAA;IACzD,OAAO,EAAE;KACR,IAAI,EAAE,YAAG,SAAG,IAAI,GAAA;KAChB,OAAO,EAAE,YAAG,SAAG,GAAG,GAAA;KAClB,GAAG,EAAE,UAAA,CAAC,EAAC,SAAG,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,GAAA;KAClC,GAAG,EAAE,UAAA,CAAC,EAAC,SAAG,CAAC,CAAC,WAAW,EAAE,IAAI,OAAO,GAAA;KACpC;IACD,CAAC;GACF;EACD,CAAC,CAAC;CACH,CAAA;;"} -\ No newline at end of file -diff --git a/node_modules/unfetch/dist/unfetch.js b/node_modules/unfetch/dist/unfetch.js -deleted file mode 100644 -index ccd2565..0000000 ---- a/node_modules/unfetch/dist/unfetch.js -+++ /dev/null -@@ -1,2 +0,0 @@ --module.exports=function(e,n){return n=n||{},new Promise(function(t,r){var s=new XMLHttpRequest,o=[],u=[],i={},a=function(){return{ok:2==(s.status/100|0),statusText:s.statusText,status:s.status,url:s.responseURL,text:function(){return Promise.resolve(s.responseText)},json:function(){return Promise.resolve(JSON.parse(s.responseText))},blob:function(){return Promise.resolve(new Blob([s.response]))},clone:a,headers:{keys:function(){return o},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var l in s.open(n.method||"get",e,!0),s.onload=function(){s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){o.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(a())},s.onerror=r,s.withCredentials="include"==n.credentials,n.headers)s.setRequestHeader(l,n.headers[l]);s.send(n.body||null)})}; --//# sourceMappingURL=unfetch.js.map -diff --git a/node_modules/unfetch/dist/unfetch.js.map b/node_modules/unfetch/dist/unfetch.js.map -deleted file mode 100644 -index 3507b3d..0000000 ---- a/node_modules/unfetch/dist/unfetch.js.map -+++ /dev/null -@@ -1 +0,0 @@ --{"version":3,"file":"unfetch.js","sources":["../src/index.mjs"],"sourcesContent":["export default function(url, options) {\n\toptions = options || {};\n\treturn new Promise( (resolve, reject) => {\n\t\tconst request = new XMLHttpRequest();\n\t\tconst keys = [];\n\t\tconst all = [];\n\t\tconst headers = {};\n\n\t\tconst response = () => ({\n\t\t\tok: (request.status/100|0) == 2,\t\t// 200-299\n\t\t\tstatusText: request.statusText,\n\t\t\tstatus: request.status,\n\t\t\turl: request.responseURL,\n\t\t\ttext: () => Promise.resolve(request.responseText),\n\t\t\tjson: () => Promise.resolve(JSON.parse(request.responseText)),\n\t\t\tblob: () => Promise.resolve(new Blob([request.response])),\n\t\t\tclone: response,\n\t\t\theaders: {\n\t\t\t\tkeys: () => keys,\n\t\t\t\tentries: () => all,\n\t\t\t\tget: n => headers[n.toLowerCase()],\n\t\t\t\thas: n => n.toLowerCase() in headers\n\t\t\t}\n\t\t});\n\n\t\trequest.open(options.method || 'get', url, true);\n\n\t\trequest.onload = () => {\n\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\tkeys.push(key = key.toLowerCase());\n\t\t\t\tall.push([key, value]);\n\t\t\t\theaders[key] = headers[key] ? `${headers[key]},${value}` : value;\n\t\t\t});\n\t\t\tresolve(response());\n\t\t};\n\n\t\trequest.onerror = reject;\n\n\t\trequest.withCredentials = options.credentials=='include';\n\n\t\tfor (const i in options.headers) {\n\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t}\n\n\t\trequest.send(options.body || null);\n\t});\n}\n"],"names":["url","options","Promise","resolve","reject","request","XMLHttpRequest","keys","all","headers","response","ok","status","statusText","responseURL","text","responseText","json","JSON","parse","blob","Blob","clone","entries","get","n","toLowerCase","has","const","i","open","method","onload","getAllResponseHeaders","replace","m","key","value","push","onerror","withCredentials","credentials","setRequestHeader","send","body"],"mappings":"eAAe,SAASA,EAAKC,UAC5BA,EAAUA,GAAW,GACd,IAAIC,iBAAUC,EAASC,OACvBC,EAAU,IAAIC,eACdC,EAAO,GACPC,EAAM,GACNC,EAAU,GAEVC,oBACLC,GAA8B,IAAzBN,EAAQO,OAAO,IAAI,GACxBC,WAAYR,EAAQQ,WACpBD,OAAQP,EAAQO,OAChBZ,IAAKK,EAAQS,YACbC,uBAAYb,QAAQC,QAAQE,EAAQW,eACpCC,uBAAYf,QAAQC,QAAQe,KAAKC,MAAMd,EAAQW,gBAC/CI,uBAAYlB,QAAQC,QAAQ,IAAIkB,KAAK,CAAChB,EAAQK,aAC9CY,MAAOZ,EACPD,QAAS,CACRF,uBAAYA,GACZgB,0BAAef,GACfgB,aAAKC,UAAKhB,EAAQgB,EAAEC,gBACpBC,aAAKF,UAAKA,EAAEC,gBAAiBjB,UAmB1BmB,IAAMC,KAfXxB,EAAQyB,KAAK7B,EAAQ8B,QAAU,MAAO/B,GAAK,GAE3CK,EAAQ2B,kBACP3B,EAAQ4B,wBAAwBC,QAAQ,wCAAiCC,EAAGC,EAAKC,GAChF9B,EAAK+B,KAAKF,EAAMA,EAAIV,eACpBlB,EAAI8B,KAAK,CAACF,EAAKC,IACf5B,EAAQ2B,GAAO3B,EAAQ2B,GAAU3B,EAAQ2B,OAAQC,EAAUA,IAE5DlC,EAAQO,MAGTL,EAAQkC,QAAUnC,EAElBC,EAAQmC,gBAAuC,WAArBvC,EAAQwC,YAElBxC,EAAQQ,QACvBJ,EAAQqC,iBAAiBb,EAAG5B,EAAQQ,QAAQoB,IAG7CxB,EAAQsC,KAAK1C,EAAQ2C,MAAQ"} -\ No newline at end of file -diff --git a/node_modules/unfetch/dist/unfetch.mjs b/node_modules/unfetch/dist/unfetch.mjs -index af22f48..23ed5a5 100644 ---- a/node_modules/unfetch/dist/unfetch.mjs -+++ b/node_modules/unfetch/dist/unfetch.mjs -@@ -1,2 +1,3 @@ --export default function(e,n){return n=n||{},new Promise(function(t,r){var s=new XMLHttpRequest,o=[],u=[],i={},a=function(){return{ok:2==(s.status/100|0),statusText:s.statusText,status:s.status,url:s.responseURL,text:function(){return Promise.resolve(s.responseText)},json:function(){return Promise.resolve(JSON.parse(s.responseText))},blob:function(){return Promise.resolve(new Blob([s.response]))},clone:a,headers:{keys:function(){return o},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var l in s.open(n.method||"get",e,!0),s.onload=function(){s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){o.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(a())},s.onerror=r,s.withCredentials="include"==n.credentials,n.headers)s.setRequestHeader(l,n.headers[l]);s.send(n.body||null)})} --//# sourceMappingURL=unfetch.mjs.map -+export const registerFetch = (win) => { -+ return function(e,n){return n=n||{},new Promise((t,r) => {var s=new win.XMLHttpRequest,o=[],u=[],i={},a=function(){return{ok:2==(s.status/100|0),statusText:s.statusText,status:s.status,url:s.responseURL,text:function(){return Promise.resolve(s.responseText)},json:function(){return Promise.resolve(JSON.parse(s.responseText))},blob:function(){return Promise.resolve(new Blob([s.response]))},clone:a,headers:{keys:function(){return o},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var l in s.open(n.method||"get",e,!0),s.onload=function(){s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){o.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(a())},s.onerror=r,s.withCredentials="include"==n.credentials,n.headers)s.setRequestHeader(l,n.headers[l]);s.send(n.body||null)})} -+} -diff --git a/node_modules/unfetch/dist/unfetch.mjs.map b/node_modules/unfetch/dist/unfetch.mjs.map -deleted file mode 100644 -index 658823a..0000000 ---- a/node_modules/unfetch/dist/unfetch.mjs.map -+++ /dev/null -@@ -1 +0,0 @@ --{"version":3,"file":"unfetch.mjs","sources":["../src/index.mjs"],"sourcesContent":["export default function(url, options) {\n\toptions = options || {};\n\treturn new Promise( (resolve, reject) => {\n\t\tconst request = new XMLHttpRequest();\n\t\tconst keys = [];\n\t\tconst all = [];\n\t\tconst headers = {};\n\n\t\tconst response = () => ({\n\t\t\tok: (request.status/100|0) == 2,\t\t// 200-299\n\t\t\tstatusText: request.statusText,\n\t\t\tstatus: request.status,\n\t\t\turl: request.responseURL,\n\t\t\ttext: () => Promise.resolve(request.responseText),\n\t\t\tjson: () => Promise.resolve(JSON.parse(request.responseText)),\n\t\t\tblob: () => Promise.resolve(new Blob([request.response])),\n\t\t\tclone: response,\n\t\t\theaders: {\n\t\t\t\tkeys: () => keys,\n\t\t\t\tentries: () => all,\n\t\t\t\tget: n => headers[n.toLowerCase()],\n\t\t\t\thas: n => n.toLowerCase() in headers\n\t\t\t}\n\t\t});\n\n\t\trequest.open(options.method || 'get', url, true);\n\n\t\trequest.onload = () => {\n\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\tkeys.push(key = key.toLowerCase());\n\t\t\t\tall.push([key, value]);\n\t\t\t\theaders[key] = headers[key] ? `${headers[key]},${value}` : value;\n\t\t\t});\n\t\t\tresolve(response());\n\t\t};\n\n\t\trequest.onerror = reject;\n\n\t\trequest.withCredentials = options.credentials=='include';\n\n\t\tfor (const i in options.headers) {\n\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t}\n\n\t\trequest.send(options.body || null);\n\t});\n}\n"],"names":["url","options","Promise","resolve","reject","request","XMLHttpRequest","keys","all","headers","response","ok","status","statusText","responseURL","text","responseText","json","JSON","parse","blob","Blob","clone","entries","get","n","toLowerCase","has","const","i","open","method","onload","getAllResponseHeaders","replace","m","key","value","push","onerror","withCredentials","credentials","setRequestHeader","send","body"],"mappings":"eAAe,SAASA,EAAKC,UAC5BA,EAAUA,GAAW,GACd,IAAIC,iBAAUC,EAASC,OACvBC,EAAU,IAAIC,eACdC,EAAO,GACPC,EAAM,GACNC,EAAU,GAEVC,oBACLC,GAA8B,IAAzBN,EAAQO,OAAO,IAAI,GACxBC,WAAYR,EAAQQ,WACpBD,OAAQP,EAAQO,OAChBZ,IAAKK,EAAQS,YACbC,uBAAYb,QAAQC,QAAQE,EAAQW,eACpCC,uBAAYf,QAAQC,QAAQe,KAAKC,MAAMd,EAAQW,gBAC/CI,uBAAYlB,QAAQC,QAAQ,IAAIkB,KAAK,CAAChB,EAAQK,aAC9CY,MAAOZ,EACPD,QAAS,CACRF,uBAAYA,GACZgB,0BAAef,GACfgB,aAAKC,UAAKhB,EAAQgB,EAAEC,gBACpBC,aAAKF,UAAKA,EAAEC,gBAAiBjB,UAmB1BmB,IAAMC,KAfXxB,EAAQyB,KAAK7B,EAAQ8B,QAAU,MAAO/B,GAAK,GAE3CK,EAAQ2B,kBACP3B,EAAQ4B,wBAAwBC,QAAQ,wCAAiCC,EAAGC,EAAKC,GAChF9B,EAAK+B,KAAKF,EAAMA,EAAIV,eACpBlB,EAAI8B,KAAK,CAACF,EAAKC,IACf5B,EAAQ2B,GAAO3B,EAAQ2B,GAAU3B,EAAQ2B,OAAQC,EAAUA,IAE5DlC,EAAQO,MAGTL,EAAQkC,QAAUnC,EAElBC,EAAQmC,gBAAuC,WAArBvC,EAAQwC,YAElBxC,EAAQQ,QACvBJ,EAAQqC,iBAAiBb,EAAG5B,EAAQQ,QAAQoB,IAG7CxB,EAAQsC,KAAK1C,EAAQ2C,MAAQ"} -\ No newline at end of file -diff --git a/node_modules/unfetch/dist/unfetch.umd.js b/node_modules/unfetch/dist/unfetch.umd.js -deleted file mode 100644 -index cdab30c..0000000 ---- a/node_modules/unfetch/dist/unfetch.umd.js -+++ /dev/null -@@ -1,2 +0,0 @@ --!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.unfetch=n()}(this,function(){return function(e,n){return n=n||{},new Promise(function(t,o){var r=new XMLHttpRequest,s=[],u=[],i={},f=function(){return{ok:2==(r.status/100|0),statusText:r.statusText,status:r.status,url:r.responseURL,text:function(){return Promise.resolve(r.responseText)},json:function(){return Promise.resolve(JSON.parse(r.responseText))},blob:function(){return Promise.resolve(new Blob([r.response]))},clone:f,headers:{keys:function(){return s},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var a in r.open(n.method||"get",e,!0),r.onload=function(){r.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){s.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(f())},r.onerror=o,r.withCredentials="include"==n.credentials,n.headers)r.setRequestHeader(a,n.headers[a]);r.send(n.body||null)})}}); --//# sourceMappingURL=unfetch.umd.js.map -diff --git a/node_modules/unfetch/dist/unfetch.umd.js.map b/node_modules/unfetch/dist/unfetch.umd.js.map -deleted file mode 100644 -index 57a2761..0000000 ---- a/node_modules/unfetch/dist/unfetch.umd.js.map -+++ /dev/null -@@ -1 +0,0 @@ --{"version":3,"file":"unfetch.umd.js","sources":["../src/index.mjs"],"sourcesContent":["export default function(url, options) {\n\toptions = options || {};\n\treturn new Promise( (resolve, reject) => {\n\t\tconst request = new XMLHttpRequest();\n\t\tconst keys = [];\n\t\tconst all = [];\n\t\tconst headers = {};\n\n\t\tconst response = () => ({\n\t\t\tok: (request.status/100|0) == 2,\t\t// 200-299\n\t\t\tstatusText: request.statusText,\n\t\t\tstatus: request.status,\n\t\t\turl: request.responseURL,\n\t\t\ttext: () => Promise.resolve(request.responseText),\n\t\t\tjson: () => Promise.resolve(JSON.parse(request.responseText)),\n\t\t\tblob: () => Promise.resolve(new Blob([request.response])),\n\t\t\tclone: response,\n\t\t\theaders: {\n\t\t\t\tkeys: () => keys,\n\t\t\t\tentries: () => all,\n\t\t\t\tget: n => headers[n.toLowerCase()],\n\t\t\t\thas: n => n.toLowerCase() in headers\n\t\t\t}\n\t\t});\n\n\t\trequest.open(options.method || 'get', url, true);\n\n\t\trequest.onload = () => {\n\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\tkeys.push(key = key.toLowerCase());\n\t\t\t\tall.push([key, value]);\n\t\t\t\theaders[key] = headers[key] ? `${headers[key]},${value}` : value;\n\t\t\t});\n\t\t\tresolve(response());\n\t\t};\n\n\t\trequest.onerror = reject;\n\n\t\trequest.withCredentials = options.credentials=='include';\n\n\t\tfor (const i in options.headers) {\n\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t}\n\n\t\trequest.send(options.body || null);\n\t});\n}\n"],"names":["url","options","Promise","resolve","reject","request","XMLHttpRequest","keys","all","headers","response","ok","status","statusText","responseURL","text","responseText","json","JSON","parse","blob","Blob","clone","entries","get","n","toLowerCase","has","const","i","open","method","onload","getAllResponseHeaders","replace","m","key","value","push","onerror","withCredentials","credentials","setRequestHeader","send","body"],"mappings":"6KAAe,SAASA,EAAKC,UAC5BA,EAAUA,GAAW,GACd,IAAIC,iBAAUC,EAASC,OACvBC,EAAU,IAAIC,eACdC,EAAO,GACPC,EAAM,GACNC,EAAU,GAEVC,oBACLC,GAA8B,IAAzBN,EAAQO,OAAO,IAAI,GACxBC,WAAYR,EAAQQ,WACpBD,OAAQP,EAAQO,OAChBZ,IAAKK,EAAQS,YACbC,uBAAYb,QAAQC,QAAQE,EAAQW,eACpCC,uBAAYf,QAAQC,QAAQe,KAAKC,MAAMd,EAAQW,gBAC/CI,uBAAYlB,QAAQC,QAAQ,IAAIkB,KAAK,CAAChB,EAAQK,aAC9CY,MAAOZ,EACPD,QAAS,CACRF,uBAAYA,GACZgB,0BAAef,GACfgB,aAAKC,UAAKhB,EAAQgB,EAAEC,gBACpBC,aAAKF,UAAKA,EAAEC,gBAAiBjB,UAmB1BmB,IAAMC,KAfXxB,EAAQyB,KAAK7B,EAAQ8B,QAAU,MAAO/B,GAAK,GAE3CK,EAAQ2B,kBACP3B,EAAQ4B,wBAAwBC,QAAQ,wCAAiCC,EAAGC,EAAKC,GAChF9B,EAAK+B,KAAKF,EAAMA,EAAIV,eACpBlB,EAAI8B,KAAK,CAACF,EAAKC,IACf5B,EAAQ2B,GAAO3B,EAAQ2B,GAAU3B,EAAQ2B,OAAQC,EAAUA,IAE5DlC,EAAQO,MAGTL,EAAQkC,QAAUnC,EAElBC,EAAQmC,gBAAuC,WAArBvC,EAAQwC,YAElBxC,EAAQQ,QACvBJ,EAAQqC,iBAAiBb,EAAG5B,EAAQQ,QAAQoB,IAG7CxB,EAAQsC,KAAK1C,EAAQ2C,MAAQ"} -\ No newline at end of file -diff --git a/node_modules/unfetch/src/index.d.ts b/node_modules/unfetch/src/index.d.ts -index 0c53ad9..8dd2d54 100644 ---- a/node_modules/unfetch/src/index.d.ts -+++ b/node_modules/unfetch/src/index.d.ts -@@ -14,4 +14,6 @@ declare namespace unfetch { - - declare const unfetch: typeof fetch; - -+export function registerFetch(window: Window): unfetch; -+ - export default unfetch; -diff --git a/node_modules/unfetch/src/index.mjs b/node_modules/unfetch/src/index.mjs -deleted file mode 100644 -index 783ad42..0000000 ---- a/node_modules/unfetch/src/index.mjs -+++ /dev/null -@@ -1,47 +0,0 @@ --export default function(url, options) { -- options = options || {}; -- return new Promise( (resolve, reject) => { -- const request = new XMLHttpRequest(); -- const keys = []; -- const all = []; -- const headers = {}; -- -- const response = () => ({ -- ok: (request.status/100|0) == 2, // 200-299 -- statusText: request.statusText, -- status: request.status, -- url: request.responseURL, -- text: () => Promise.resolve(request.responseText), -- json: () => Promise.resolve(JSON.parse(request.responseText)), -- blob: () => Promise.resolve(new Blob([request.response])), -- clone: response, -- headers: { -- keys: () => keys, -- entries: () => all, -- get: n => headers[n.toLowerCase()], -- has: n => n.toLowerCase() in headers -- } -- }); -- -- request.open(options.method || 'get', url, true); -- -- request.onload = () => { -- request.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, (m, key, value) => { -- keys.push(key = key.toLowerCase()); -- all.push([key, value]); -- headers[key] = headers[key] ? `${headers[key]},${value}` : value; -- }); -- resolve(response()); -- }; -- -- request.onerror = reject; -- -- request.withCredentials = options.credentials=='include'; -- -- for (const i in options.headers) { -- request.setRequestHeader(i, options.headers[i]); -- } -- -- request.send(options.body || null); -- }); --} diff --git a/packages/driver/src/cy/overrides.ts b/packages/driver/src/cy/overrides.ts index cc9c1c4fac97..5d4e873ddfc7 100644 --- a/packages/driver/src/cy/overrides.ts +++ b/packages/driver/src/cy/overrides.ts @@ -1,5 +1,4 @@ import _ from 'lodash' -import { registerFetch } from 'unfetch' import $selection from '../dom/selection' import type { ICypress } from '../cypress' @@ -55,14 +54,6 @@ export const create = (state: StateFunc, config: ICypress['config'], focused: IF contentWindow.CSSStyleSheet.prototype.insertRule = _.wrap(insertRule, cssModificationSpy) contentWindow.CSSStyleSheet.prototype.deleteRule = _.wrap(deleteRule, cssModificationSpy) - - if (config('experimentalFetchPolyfill')) { - // drop "fetch" polyfill that replaces it with XMLHttpRequest - // from the app iframe that we wrap for network stubbing - contentWindow.fetch = registerFetch(contentWindow) - // flag the polyfill to test this experimental feature easier - state('fetchPolyfilled', true) - } } catch (error) {} // eslint-disable-line no-empty } diff --git a/packages/frontend-shared/cypress/fixtures/config.json b/packages/frontend-shared/cypress/fixtures/config.json index a88d6e939039..30279be66244 100644 --- a/packages/frontend-shared/cypress/fixtures/config.json +++ b/packages/frontend-shared/cypress/fixtures/config.json @@ -87,11 +87,6 @@ "from": "default", "field": "experimentalCspAllowList" }, - { - "value": false, - "from": "default", - "field": "experimentalFetchPolyfill" - }, { "value": true, "from": "default", diff --git a/packages/frontend-shared/src/locales/en-US.json b/packages/frontend-shared/src/locales/en-US.json index 572adb0646d4..12633d1ae238 100644 --- a/packages/frontend-shared/src/locales/en-US.json +++ b/packages/frontend-shared/src/locales/en-US.json @@ -584,10 +584,6 @@ "name": "CSP Allow List", "description": "Enables Cypress to selectively permit Content-Security-Policy and Content-Security-Policy-Report-Only header directives, including those that might otherwise block Cypress from running." }, - "experimentalFetchPolyfill": { - "name": "Fetch polyfill", - "description": "Automatically replaces `window.fetch` with a polyfill that Cypress can spy on and stub. Note: `experimentalFetchPolyfill` has been deprecated in Cypress 6.0.0 and will be removed in a future release. Consider using [`cy.intercept()`](https://on.cypress.io/intercept) to intercept `fetch` requests instead." - }, "experimentalInteractiveRunEvents": { "name": "Interactive run events", "description": "Allows listening to the [`before:run`](https://on.cypress.io/before-run), [`after:run`](https://on.cypress.io/after-run), [`before:spec`](https://on.cypress.io/before-spec), and [`after:spec`](https://on.cypress.io/after-spec) events in plugins during interactive mode." diff --git a/packages/server/lib/experiments.ts b/packages/server/lib/experiments.ts index 6f115e307c23..f8607a07f7a6 100644 --- a/packages/server/lib/experiments.ts +++ b/packages/server/lib/experiments.ts @@ -46,12 +46,11 @@ interface StringValues { * @example ``` { - experimentalFetchPolyfill: 'Polyfills `window.fetch` to enable Network spying and stubbing.' + experimentalRunAllSpecs: 'Enables the "Run All Specs" UI feature, allowing the execution of multiple specs sequentially' } ``` */ const _summaries: StringValues = { - experimentalFetchPolyfill: 'Polyfills `window.fetch` to enable Network spying and stubbing.', experimentalInteractiveRunEvents: 'Allows listening to the `before:run`, `after:run`, `before:spec`, and `after:spec` events in the plugins file during interactive mode.', experimentalJustInTimeCompile: 'Just-In-Time compiling', experimentalModifyObstructiveThirdPartyCode: 'Applies `modifyObstructiveCode` to third party `.html` and `.js`, removes subresource integrity, and modifies the user agent in Electron.', @@ -71,12 +70,11 @@ const _summaries: StringValues = { * @example ``` { - experimentalFetchPolyfill: 'Fetch polyfill' + experimentalRunAllSpecs: 'Run All Specs' } ``` */ const _names: StringValues = { - experimentalFetchPolyfill: 'Fetch Polyfill', experimentalInteractiveRunEvents: 'Interactive Mode Run Events', experimentalJustInTimeCompile: 'Enables Just-In-Time (JIT) compiling for component testing, which will only compile assets related to the spec before the spec is run. Currently supported for Vite and Webpack.', experimentalModifyObstructiveThirdPartyCode: 'Modify Obstructive Third Party Code', diff --git a/system-tests/__snapshots__/results_spec.ts.js b/system-tests/__snapshots__/results_spec.ts.js index bcc4f872c47e..5945b4bff6e8 100644 --- a/system-tests/__snapshots__/results_spec.ts.js +++ b/system-tests/__snapshots__/results_spec.ts.js @@ -21,7 +21,6 @@ exports['module api and after:run results'] = ` "env": {}, "execTimeout": 60000, "experimentalCspAllowList": false, - "experimentalFetchPolyfill": false, "experimentalInteractiveRunEvents": false, "experimentalRunAllSpecs": false, "experimentalMemoryManagement": false, diff --git a/system-tests/test/fetch_polyfill_spec.js b/system-tests/test/fetch_polyfill_spec.js deleted file mode 100644 index e70c938a971e..000000000000 --- a/system-tests/test/fetch_polyfill_spec.js +++ /dev/null @@ -1,163 +0,0 @@ -const systemTests = require('../lib/system-tests').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` - -
- - - `) - }) - - // page fetches JSON array - app.get('/first', (req, res) => { - return res.send(stripIndent` - - - second - - `) - }) - - // page fetches text - app.get('/second', (req, res) => { - return res.send(stripIndent` - -
- - - `) - }) -} - -describe('e2e fetch polyfill', () => { - systemTests.setup({ - servers: { - port: 1818, - onServer, - }, - }) - - systemTests.it('passes', { - browser: '!webkit', // TODO(webkit): fix+unskip - spec: 'fetch.cy.js', - snapshot: false, - config: { - experimentalFetchPolyfill: true, - }, - }) -}) - -describe('e2e no fetch polyfill', () => { - systemTests.setup({ - servers: { - port: 1818, - onServer, - }, - }) - - systemTests.it('passes', { - spec: 'fetch_no_polyfill.cy.js', - snapshot: false, - config: { - experimentalFetchPolyfill: false, - }, - }) -}) diff --git a/yarn.lock b/yarn.lock index b9fda62391e4..cfda207108a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30875,11 +30875,6 @@ undici-types@~6.19.2: resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== -unfetch@4.1.0: - 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@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"