-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Fixtures do not support JavaScript in .js files #1271
Comments
This is true, we likely need to rethink how we handle |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
It'd be lovely if |
@brian-mann Sincere question: why are |
@sandro-pasquali the reason is that there are two contexts - the browser context and node context. Because of this, it's not as simple as what you'd expect. Fixtures are utilized inside of the browser, which means you use them like this... That's fine except... how is the Alternatively, we could evaluate Another problem with the node context approach is that arguments would have to be JSON serializable. That's probably not that big of a problem but it means you cannot pass functions or instances or even I'm probably more okay with opting to go with the There has been some dialog amongst our team to effectively rewrite the entire fixtures approach in Cypress because we feel it's been large superseded by better approaches and initially was sort of a "stop-gap" feature invented years ago. |
@sandro-pasquali forgot to mention that you can interop between the browser + node context seamlessly with This is effectively the approach I described above as the 2nd option. The only downside is that you'll have to write your node code for version |
I'm running into similar issues with something like this: [
{ /* ... */ },
];
Removing the trailing semicolon fixes it, however my prettier editor plugin auto-appends it on save. I was expecting the fixtures to become part of the browser bundle and also tried This is more like default JS and more flexible anyway (passing the fixture as an object reference): import notificationsFixture from '../fixtures/notifications';
describe('Notifications', () => {
it('lists notifications', () => {
cy.server();
cy.route('GET', '/api/notifications', notificationsFixture);
// or
cy.fixture(notificationsFixture).as('notifications');
cy.route('GET', '/api/notifications', '@notifications');
// ...
});
}); This could even become a backwards-compatible API change (i. e., check whether the fixture is a string or an object)? Edit: I also don't get auto-reload of my tests when I change a fixture, which could be solved by this as well. |
Maybe we need to update the document to state that js fixture is not what people normally expect. module.exports = {
a: 1
} but not this (with semicolon automatically added by my editor setting) module.exports = {
a: 1
}; This throws |
Any news about this? It's really hard to maintain our fixtures since they are quite big with only slight changes here and there. One change in any of them and you have to update all of them. |
Take a look at cy.task - it can be used to generate any object in node context, including fixture json files that you could load later. Or use cy.writeFile to do the same. Or even JavaScript right from the tests and instead of fixture stub in cy.route use the created object.
…Sent from my iPhone
On Jan 27, 2019, at 18:56, SLOBYYYY ***@***.***> wrote:
Any news about this? It's really hard to maintain our fixtures since they are quite big with only slight changes here and there. One change in any of them and you have to update all of them.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Thanks @bahmutov for mentioning I just started with Cypress and I wanted to prevent the issue that @SLOBYYYY had. To do that, I created javascript files that exports an object and I get it with the following task: plugins/index.js module.exports = (on, config) => {
on('task', {
fixture (fixtures) {
const result = {}
if (Array.isArray(fixtures)) {
fixtures.forEach(fixture => {
result[fixture] = require('../fixtures/elements/' + fixture + '.js')
})
} else {
result[fixtures] = require('../fixtures/elements/' + fixtures + '.js')
}
return result
}
})
return config
} So in your tests you can use it like this // Getting one fixture
cy.task('fixture', 'user').then(f => {
console.log(f) // outputs {user: {}}
})
// Getting multiple fixtures
cy.task('fixture', ['user', 'product']).then(f => {
console.log(f) // outputs { user: {}, product: {]}
}) This way you can also use libraries like faker in your |
I could not get the task option to work, as my .js fixture files had ES6 imports that were constantly failing. In the end, I just did a standard import of each fixture file at the top of each spec file and then cloned the data in a beforeEach. import props from '../../../fixtures/Models/Helpers/props';
import _ from 'lodash';
....
beforeEach(function() {
cy.then(function() {
return _.cloneDeep(props);
}).as('props');
}); The fixture was then available in each test as this.props. |
Took me an hour to find :| |
Yep, same here. I actually resorted to having a import {response} from "__fixtures__/my-response.js";
cy.route({
method: "GET", // Route all GET requests
url: "https://api.my-app.com/**",
response: response.body,
}); But, I am not really sure will this break something in the future, I haven't researched it fully yet. Does anyone use response mocks like this? |
What's the recommended way to import mock data into tests which rendered by triggering a function? Could I just create a TS file that exports these functions that create user mocks and import and execute the function inside cypress tests? |
Yes you can import or require these functions and call them to generate mock data
…Sent from my iPhone
On May 18, 2020, at 22:23, Luca Ban ***@***.***> wrote:
What's the recommended way to import mock data into tests which rendered by triggering a function?
Eg. mockUser() or new Array(100).fill(null).map(mockUser)
Could I just create a TS file that exports these functions that create user mocks and import and execute the function inside cypress tests?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
@bahmutov thanks for your guidance! |
@mesqueeb
|
@OneHatRepo Does the beforeEach() have to be inside the describe closure or is there any other advice you could possibly give? Any help is very much appreciated! |
Hello! Any news about this bug? I will much appreciate the effort in a fix, our tests are getting bigger and bigger and are hard to maintain without this functionality. |
This is killing me. |
Hi, Is there any update on this? I have a third party script that controls features within my application and I don't control how the external script works, it invokes a global method within the application itself (yuck - I know). The script is loaded by the main app and I'd like to I'd like to be able to do it something like this: cy.intercept('https://third-party.com/js/foo.js', {
fixture: 'third-party-com/js/foo.js',
}).as('3rd-party-foo')
...
cy.wait('@3rd-party-foo') Is there an alternative way to achieve this? |
It looks like this works, not ideal but might help people out. cy.readFile('fixtures/3rd-party-scripts/3rdparty/js/foo.js', 'utf8' ).then((stubResponse) => {
cy.intercept('https://3rdparty.com/js/foo.js', (req) => {
req.reply(stubResponse)
}).as('3rd-party-foo')
})
...
cy.wait('@3rd-party-foo')
I added a command to do this on the project I'm working on: Cypress.Commands.add('mockThirdPartyJS', (url, fixturePath, _as) => {
return cy.readFile(
`fixtures/${fixturePath}`,
'utf8'
).then((stubResponse) => {
cy.intercept(url, (req) => {
req.reply(stubResponse)
}).as(_as);
})
}) Then usage is: cy.mockThirdPartyJS(
'https://some-provider.com/a-script.js',
'some-provider/a-mocked-script.js',
'some-provider_a-script')
)
...
cy.wait('@some-provider_a-script') |
Any update on this? |
Seems like it would help a ton of people if there was a mechanism to load a fixture as-is without doing whatever special magic Cypress is attempting to do with Like so: cy.intercept("/myjs.js", {
fixture: "stubjs.js",
raw: true,
headers: {
"content-type": "application/javascript",
},
}); |
any updates on this? |
Hey Any update on the estimated timeline or roadmap to fix this? Thanks in advance ❤️ |
There was some error when I tried this so here is my version (tested on [email protected]): plugins/index.js: module.exports = (on, config) => {
on('task', {
fixture({ name, address }) {
const result = require(`../fixtures/${address}`);
return { result, name };
}
});
return config;
}; How to use it: cy.task('fixture', {
name: 'someName',
address: 'someWhere/file.js'
}).then(function({ result, name }) {
this[name] = result;
}); Finally: cy.get('@something').should('contain.text', this.someName.x); |
(Taking a stab at) adding documentation on `.js` fixture files. Current documentation mentions that `.js` fixture files are possible, but doesn't describe how to use them, leading to issues like cypress-io/cypress#1271 . I do think the current `.js` fixture support should get a good rethink (as mentioned 4 years ago in that issue) , but in the meantime it should have some documentation on how to use it (or fully remove any mention of it from the documentation, making it "unsupported").
I wanna import a JSON file outside fixtures via a JavaScript code. I tried requiring it into an array but it doesn't work. is that even possible? |
I was able to get factory.ts & faker working within a fixture with the following: // fixtures/someFile.ts
const MyFactory = Factory.Sync.makeFactory<--- some TS type --->({
id: faker.datatype.string(),
name: faker.random.arrayElement<string>(--- some array ---),
types: faker.random.arrayElements<string>(--- some array ---, 2),
});
export const myFixture: <--- some TS type ---> = {
types: faker.random.arrayElements<string>(--- some array ---, 2),
data: [
MyFactory.build(),
MyFactory.build(),
MyFactory.build(),
MyFactory.build(),
],
}; then in my spec file: import { myFixture } from '../fixtures';
describe('Some Module', () => {
beforeEach(() => {
cy.intercept({ method: 'POST', path: '/some/api/endpoint' }, myFixture).as('someAlias');
})
...
}) Hope this helps someone. 👍 |
This is my solution: export const interceptFingerprintJS = () => {
const replaceAndIntercept = (script) => {
script = script.replace(/%fingerprintId%/, fingerprintId);
cy.intercept(`/assets/vendor/f/f.min.js`, { body: script }).as('fingerprintJs');
};
global.myCypressCache = global.myCypressCache || {};
let cachedFile = global.myCypressCache.fingerprint;
if (!cachedFile) {
cy.readFile('cypress/fixtures/fingerprint.js').then((script) => {
global.myCypressCache.fingerprint = script;
replaceAndIntercept(script);
});
} else {
replaceAndIntercept(cachedFile);
}
}; Primitive caching included, the downside is using global scope, but should be fine. Alternative solution is to embed script in test: cy.intercept(`/assets/vendor/file.js`, {
body: `alert('my script lives here')`,
}).as('fileJs'); The downside is no formatting/linting/etc. |
Current behavior:
Any attempt to use valid ES5 (e.g.
var
,require
) let alone ES6 (import
,export
,const
) results in syntax errors, e.g.:The only "javascripty" construct that seems to be allowed is
module.exports =
.Desired behavior:
.js
fixtures should support valid JS syntax (ES6, preferably).How to reproduce:
Create a fixture containing valid ES6 syntax
Then use it:
Result:
Create a fixture using valid ES5 code
Result:
The text was updated successfully, but these errors were encountered: