Skip to content
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

Merged
merged 8 commits into from
Dec 1, 2022

Conversation

ZachJW34
Copy link
Contributor

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 the e2e config. Run yarn watch and yarn 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

  • Have tests been added/updated?
  • Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • Has a PR for user-facing changes been opened in cypress-documentation?
  • Have API changes been updated in the type definitions?

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Nov 28, 2022

Thanks for taking the time to open a PR!

}
`

const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window
Copy link
Contributor

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?

Copy link
Contributor Author

@ZachJW34 ZachJW34 Nov 29, 2022

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', () => {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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,
Copy link
Contributor

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)?

Copy link
Contributor Author

@ZachJW34 ZachJW34 Nov 29, 2022

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

Copy link
Contributor

@lmiller1990 lmiller1990 left a 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.

@ZachJW34 ZachJW34 marked this pull request as ready for review November 29, 2022 20:31
@cypress
Copy link

cypress bot commented Nov 29, 2022

Copy link
Contributor

@lmiller1990 lmiller1990 left a 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.

packages/app/cypress/e2e/run-all-specs.cy.ts Outdated Show resolved Hide resolved
packages/app/src/pages/Specs/Runner.vue Show resolved Hide resolved
packages/app/src/pages/Specs/Runner.vue Outdated Show resolved Hide resolved
@@ -207,18 +190,43 @@ describe('InlineSpecList', () => {
})

describe('Run all Specs', () => {
const hoverRunAllSpecs = (directory?: string, specNumber?: number) => {
Copy link
Contributor

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', () => {
Copy link
Contributor

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?

@lmiller1990
Copy link
Contributor

lmiller1990 commented Nov 30, 2022

According to the issue linked, the label should be "Run N Specs" when using the filter. Eg:

image

This should be "Run 2 specs". Did that requirement change? I might have missed it.

The actual feature is working as expected. :100

@astone123
Copy link
Contributor

Worked well for me, just waiting on the answer to Lachlan's comment - seems like a missing requirement

Copy link
Contributor

@mike-plummer mike-plummer left a 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) }}
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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()
Copy link
Contributor

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()

Copy link
Contributor

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.

Copy link
Contributor

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'
Copy link
Contributor

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

packages/app/src/store/run-all-specs-store.ts Outdated Show resolved Hide resolved
allSpecs.push(id)

Object.keys(directoryChildren).forEach((dir) => {
if (id.startsWith(dir) && id.replace(dir, '').startsWith(separator)) {
Copy link
Contributor

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}`) {

packages/app/src/store/run-all-specs-store.ts Outdated Show resolved Hide resolved
@@ -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"
Copy link
Contributor

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.

Copy link
Contributor

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

@lmiller1990
Copy link
Contributor

lmiller1990 commented Dec 1, 2022

@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

@marktnoonan
Copy link
Contributor

There were a couple of failures in CI, I've pushed f263211 and 3e0a325 to update the tests. Both pass for me locally now so hopefully CI will be all good now.

Copy link
Contributor

@mike-plummer mike-plummer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@marktnoonan
Copy link
Contributor

I've noticed one of my changes is coincidentally reverting one of Lachlan's changes, seems harmless but commented here just in case.

@ZachJW34 ZachJW34 merged commit 3f0d150 into develop Dec 1, 2022
@ZachJW34 ZachJW34 deleted the zachw/top-level-run-all-backup branch December 1, 2022 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow running all specs without root directory
5 participants