Closed alejandroiglesias closed 3 years ago
mount
returns a svelte component instance, so you can call it's $set
function. Something like:
import { mount } from 'cypress-svelte-unit-test'
mount(MyComponent, { { props: value: 2 } }).then(myComponentInstance => {
setTimeout(() => myComponentInstance.$set({ value: 4 }), 1000)
})
More info here: https://svelte.dev/docs#$set
@JohnnyFun mount
does not return a Svelte component instance. It returns a Cypress.Chainable
instance and when trying to use the promise fulfillment then
method, it returns me a CSS string:
Any other ideas?
@JohnnyFun @bahmutov ok, it seems I found a bug. When calling the mount
function, if I provide the third styleOptions
parameter, then the resolve function returns the stylesheet string as the parameter instead of the component instance. Steps to reproduce:
mount(Button, {}, { cssFile: 'dist/main.css' }).then(buttonInstance => { /* buttonInstance contains Button CSS file */ })
If I don't provide the styleOptions
parameter, then I get the instance correctly:
mount(Button, {}).then(buttonInstance => { /* buttonInstance contains Button component instance */ })
It seems to me that in the case of providing the styleOptions
parameter, the stylesheet should be returned as a second parameter to the resolve function (if need to be returned at all since I don't see a good reason for it).
Take a look at the source code for this repo: https://github.com/bahmutov/cypress-svelte-unit-test/blob/master/lib/index.ts
The svelte component is instantiated and is returned in a cy.wrap
call. So you could console.log what you get back via .then
and/or log the component before it's wrapped and that'll probably track down what's going wrong pretty quickly.
It might also depend on what parameters you're passing to the svelte compiler--they provide different instance methods depending on what you tell it to spit out.
@JohnnyFun I looked into the source code. If I log the instantiated component as you suggested, it is correct. Even if I log the wrapped component and check the resolved promise, it is correct:
console.log(cy.wrap(component).then(console.log))
// Button { ... }
But somehow, if in my test spec I log what I get in the resolved promise of the mount
function, I get the stylesheet:
mount(Button, { props: { active: true } }, { cssFile: 'dist/main.css' }).then(console.log)
/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */
html,
body,
p,
ol,
ul,
li,
dl,
dt,
dd,
blockquote,
figure,
fieldset,
legend,
textarea,
pre,
iframe,
hr,
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
}
/* ...*/
Here is the Rollup config for setting up the Svelte compiler:
module.exports = {
plugins: [
svelte({
// You can restrict which files are compiled
// using `include` and `exclude`
include: 'src/**/*.svelte',
// Emit CSS as "files" for other plugins to process. default is true
emitCss: false,
// You can pass any of the Svelte compiler oiptions
compilerOptions: { dev: true }
}),
commonjs(),
resolve({ browser: true })
]
}
I also tried commenting out the emitCss
and compilerOptions
properties without producing any different results. Any other ideas?
@JohnnyFun @bahmutov did you have any chance to check this? Thanks in advance
Huh, strange. I re-created it. I load my styles into the style
option by reading the css file myself and storing it in a global let
, so I've never ran into that. So that'd be a workaround in the meantime for you.
The issue must have something to do with how it's loading in css files with the cssFile
option. Looks like it just reads all the css files with bluebird promise and plops them into style blocks in the dom. I wonder if cypress does something special with that bluebird promise that wonks up the cy.wrap
. 🤷
I bet cy.readFile(cssFilename, ...
has something to do with it, but I don't know enough about cypress
internals.
Ok, figured it out--just need to await the call to injectStylesBeforeElement
and make the rest follow. I'll make a PR for that in a bit.
I cannot seem to find anywhere how to change component props after mounting the component to test that the component updates correctly. This is how I'm mounting it:
In cypress-react-unit-test it can be done like this:
By the way, is this the correct way to test a component by the way? Or should I test it purely as a user? Besides this, I'm thinking there are some cases that deserved to be tested not only as an end-user since these components will be a part of an application that will trigger props updates and methods, so it may still be useful to do this kind of testing. I appreciate your insights.