-
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
fix: add top-level run-all button to allow all specs to be run at once #24846
Conversation
Thanks for taking the time to open a PR!
|
} | ||
` | ||
|
||
const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window |
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.
We've got something like
const isRunMode = window.__CYPRESS_MODE__ === 'run'
In quite a few places - any chance we can move this to a single function?
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.
Can do, I think the window.top === window
is for cy-in-cy? Makes sense to consolidate that as well, going to include that and see if anything breaks.
Addressed in b86fb64
|
||
const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window | ||
|
||
export const useRunAllSpecsStore = defineStore('runAllSpecs', () => { |
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.
Should we be consistent and use the "options" style store that we use for our other stores? Or is there a limitation preventing us from using that style here?
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.
Only way to execute the gql query without having to call an explicit action. I didn't want to convert to using the store but I would have had to refactor the InlineSpecsList to get the communication to work. I'll think on this a bit more as I'm not too happy with the implementation.
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 still not entirely clear why this isn't possible using the options style store, but happy to move forward as is. I also feel this implementation isn't ideal, but I can't really nail down why - other than the fact we had to touch so many files to implement it.
Anyway, we can add this to our mental list of "things to improve" if/when we get a chance to attack some of the technical debt. It would be nice if the stores could be all written in a consistent style, though - what's the blocker on the options style store?
|
||
return { | ||
isRunAllSpecsAllowed, | ||
allSpecs: allSpecsRef, |
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.
Seems allSpecs
is not used outside the store; a private ref - should we not return it here (thus not exposing it)?
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.
You're right! It became unused after a refactor
Edit: Addressed in b86fb64
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.
Did not test it out -- still in draft -- just left a few comments.
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 left some comments, no obvious blocker, mostly style/architectural things.
@@ -207,18 +190,43 @@ describe('InlineSpecList', () => { | |||
}) | |||
|
|||
describe('Run all Specs', () => { | |||
const hoverRunAllSpecs = (directory?: string, specNumber?: number) => { |
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.
This is only called in two places and both directory
and specNumber
are always defined. We can remove the ?
. It also means line 199 is never executed.
|
||
const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window | ||
|
||
export const useRunAllSpecsStore = defineStore('runAllSpecs', () => { |
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 still not entirely clear why this isn't possible using the options style store, but happy to move forward as is. I also feel this implementation isn't ideal, but I can't really nail down why - other than the fact we had to touch so many files to implement it.
Anyway, we can add this to our mental list of "things to improve" if/when we get a chance to attack some of the technical debt. It would be nice if the stores could be all written in a consistent style, though - what's the blocker on the options style store?
Worked well for me, just waiting on the answer to Lachlan's comment - seems like a missing requirement |
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.
Works great! Just one question about expected behavior:
In Inline, if you search for a spec that doesn't exist you can still attempt to do a "Run All" on an empty set of specs. It's gracefully handled (gives the "no tests found" message), but I wonder if it makes more sense to disable the "Run All" control if the inline list is empty
@@ -22,7 +24,7 @@ | |||
class="font-normal text-sm inline-flex" | |||
data-cy="tooltip-content" | |||
> | |||
{{ t('specPage.runAllSpecs', specNumber) }} | |||
{{ specNumber === 'all' ? t('specPage.runAllSpecs') : t('specPage.runSelectedSpecs', specNumber) }} |
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.
Could we just use RUN_ALL_SPECS_KEY
instead of the "all" magic string?
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'll go ahead and make this change - I think it makes sense, and Zach W looks to be out for a day.
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.
Turns out we don't need this anymore, instead we just show the number as recommended by design: "Run N specs".
@@ -80,4 +83,6 @@ const specs = computed<FuzzyFoundSpec[]>(() => { | |||
return fuzzySortSpecs(specs, debouncedSpecFilterModel.value) | |||
}) | |||
|
|||
const runAllSpecsStore = useRunAllSpecsStore() |
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.
nit: Thoughts on just destructuring here to simplify the template expressions above?
const { isRunAllSpecsAllowed, runAllSpecs } = useRunAllSpecsStore()
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.
Reactive get stale when destructured from the pinia store, which is why I've generally avoided doing it. There's a storeToRefs
helper we can use if we want. But I ended up kind of liking that when we use reactive values from the store, it's clear where they are coming from, even if it's a bit verbose.
Docs for reference: https://pinia.vuejs.org/core-concepts/index.html#using-the-store
Could be swayed towards using storeToRefs
if the rest of us like it.
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.
Ah, didn't know that. Thanks for the info 👍
import { defineStore } from 'pinia' | ||
import { computed, ref } from 'vue' | ||
import { useRouter } from 'vue-router' | ||
import { RunAllSpecsDataDocument, RunAllSpecsDocument } from '../generated/graphql-test' |
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.
Should probably be pulling from generated/graphql
, not graphql-test
allSpecs.push(id) | ||
|
||
Object.keys(directoryChildren).forEach((dir) => { | ||
if (id.startsWith(dir) && id.replace(dir, '').startsWith(separator)) { |
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.
nit: Could simplify
if (id.startsWith(`${dir}${separator}`) {
@@ -218,7 +218,8 @@ | |||
"content": "Record a run to see your test results in Cypress Cloud. You can then optimize your test suite, debug failing and flaky tests, and integrate with your favorite tools." | |||
} | |||
}, | |||
"runAllSpecs": "Run {n} spec | Run {n} specs" | |||
"runSelectedSpecs": "Run {n} spec | Run {n} specs", | |||
"runAllSpecs": "Run all specs" |
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'd suggest we do like 9.x, and when there's a filter active, make the wording be "run filtered specs" for clarity about what to expect.
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 did this here 8e12cbb
b59659c
to
8e12cbb
Compare
@mike-plummer @ZachJW34 @astone123 @marktnoonan I pushed a commit addressing the final comments to make sure we finish this in a timely fashion. Please check 8e12cbb Here's a preview. I also disabled the button on the inline spec list if there are 0 specs after filtering as recommended by @mike-plummer. simplescreenrecorder-2022-12-01_14.46.32.mp4 |
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.
LGTM 🚀
I've noticed one of my changes is coincidentally reverting one of Lachlan's changes, seems harmless but commented here just in case. |
User facing changelog
experimentalRunAllSpecs: Allow running all specs regardless of folder structure by adding a top-level run-all button.
Additional details
We only allowed running "all specs" if the user happened to have one root folder e.g. storing all specs under
cypress/e2e
. If they had two root folders containing specs, this wasn't possible.There is now a "top-level" run all button in both the Specs Page SpecsList and the Runner SpecsList.
DRAFT: Need to verify InlineSpecList button with design.
Steps to test
Checkout this branch, choose a project and add
experimentalRunAllSpecs
to thee2e
config. Runyarn watch
andyarn cypress:open
in two separate terminals and then choose your project. Verify the Specs page and the Runner has the top-level "Run All Specs" button and that it functions correctly.How has the user experience changed?
Screen.Recording.2022-11-28.at.12.16.18.PM.mov
PR Tasks
cypress-documentation
?type definitions
?