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
E2e tests overhaul #2024
base: v1.x-2022-07
Are you sure you want to change the base?
E2e tests overhaul #2024
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {beforeAll} from 'vitest'; | ||
import {describe, MINIMAL_TEMPLATE} from '../test-framework'; | ||
|
||
describe( | ||
'basic-route', | ||
({fs}) => { | ||
beforeAll(async () => { | ||
await fs.write(MINIMAL_TEMPLATE); | ||
}); | ||
}, | ||
{ | ||
routes: import.meta.glob('./routes/*.server.*'), | ||
} | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export default function home() { | ||
return <div className="text">Hello world</div>; | ||
} | ||
|
||
export const tests = ({expect, it, browser}) => { | ||
it('Loads hello world', async () => { | ||
await browser.navigate('/'); | ||
|
||
const text = await browser.text('.text'); | ||
|
||
expect(text).toBe('Hello world'); | ||
}); | ||
}; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import {beforeAll, expect} from 'vitest'; | ||
import {describe, MINIMAL_TEMPLATE} from '../test-framework'; | ||
|
||
describe( | ||
'multiple-routes', | ||
({fs, browser, it}) => { | ||
beforeAll(async () => { | ||
await fs.write(MINIMAL_TEMPLATE); | ||
|
||
await fs.write( | ||
'src/routes/index.server.jsx', | ||
` | ||
import {Link} from '@shopify/hydrogen'; | ||
|
||
export default function Home() { | ||
return ( | ||
<> | ||
<h1>Home</h1> | ||
<Link className="btn" to="/about">About</Link> | ||
</> | ||
); | ||
} | ||
` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It kind of stinks that these have to be written as strings, as you lose features such as linting, formatting, typechecking, etc. (especially as part of the CI, which is helpful for keeping external contributions cleaner too) I guess you don't have to create them as strings, though, right? They can be files in the filesystem? These were just done for ease of use? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah these can be files, I also think there is probably a tagged template literal (similar to gql) that may solve some of the issues you identified. Either one exists of we could create something fairly easily. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is my main question as well... what's the benefit of having this as strings over having files? Do we have an example or use-case where this approach is clearly better? 🤔 Maybe we testing multiple routes so that we can colocate tests with the content of the files? |
||
); | ||
await fs.write( | ||
'src/routes/about.server.jsx', | ||
` | ||
import Counter from '../components/Counter.client'; | ||
|
||
export default function About() { | ||
return ( | ||
<> | ||
<h1 className="about">About</h1> | ||
<Counter /> | ||
</> | ||
); | ||
} | ||
` | ||
); | ||
await fs.write( | ||
'src/components/Counter.client.jsx', | ||
` | ||
import {useState} from 'react'; | ||
|
||
export default function Counter() { | ||
const [count, setCount] = useState(0); | ||
|
||
return ( | ||
<div> | ||
<h2 className="count">Count is {count}</h2> | ||
<button className="increase" onClick={() => setCount(count + 1)}> | ||
increase count | ||
</button> | ||
</div> | ||
); | ||
} | ||
` | ||
); | ||
}); | ||
|
||
it('shows the homepage, navigates to about, and increases the count', async () => { | ||
await browser.navigate('/'); | ||
|
||
expect(await browser.text('h1')).toBe('Home'); | ||
|
||
await browser.click('.btn'); | ||
|
||
expect(await browser.url().endsWith('/about')).toBeTruthy(); | ||
expect(await browser.text('.about')).toBe('About'); | ||
expect(await browser.text('.count')).toBe('Count is 0'); | ||
|
||
await browser.click('.increase'); | ||
|
||
expect(await browser.text('.count')).toBe('Count is 1'); | ||
}); | ||
}, | ||
{ | ||
modes: ['node-dev', 'node-prod'], | ||
routes: import.meta.glob('./routes/*.server.*'), | ||
} | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing this now in isolation - I like the colocation of component and test, but I don't like how it feels a little unclear (and magical?) how things are getting rendered and where it's coming from.
For example, it's not very clear that the default export above is getting rendered, or even how it's getting rendered.
Maybe this is an area where I wouldn't mind having to be more explicit, even if it means writing more code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow here, can you show an example of how you would prefer it to work?
The way I understand this, we render route X and we include the tests for route X in the same file... what's missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I'm just thinking about other test frameworks, where you call something like
render(<Home/>)
, and was thinking that I like the explicitness of that.Somewhat related: in the current situation, how would you change the props passed to
<Home/>
to test different code paths? Is that possible?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's possible since these are e2e tests and depends on what the browser sends 🤔 -- might be wrong though