-
Notifications
You must be signed in to change notification settings - Fork 3.3k
internal: (studio) fix studio and runner states during opening, closing, and refreshing #32153
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
Changes from 9 commits
807b949
9a0521e
967300c
e94f9be
4df5587
071e1a4
62a2550
ed87881
d516243
b541855
95faad5
8bc82a7
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 | ||||
---|---|---|---|---|---|---|
|
@@ -737,6 +737,27 @@ describe('studio functionality', () => { | |||||
cy.location().its('hash').and('not.contain', 'testId=').and('not.contain', 'studio=') | ||||||
}) | ||||||
|
||||||
it('does not prompt for URL when creating a new test in studio', () => { | ||||||
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.
Suggested change
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. I think I need to re-word this a different way. The issue was that when the user opens the studio panel to "new test" mode, we were already prompting for a URL in the address bar, even when the spec file was currently running and the AUT was at a URL already. We only want to prompt for a URL once the test is actually created and it doesn't visit anything yet
astone123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
launchStudio({ specName: 'spec-w-visit.cy.js', createNewTestFromSuite: true }) | ||||||
cy.location().its('hash').should('contain', 'suiteId=r2').and('contain', 'studio=') | ||||||
cy.waitForSpecToFinish() | ||||||
|
||||||
cy.findByTestId('aut-url-input').should('have.value', 'http://localhost:4455/cypress/e2e/index.html') | ||||||
}) | ||||||
|
||||||
it('does not reload the page if we didnt open a test in studio', () => { | ||||||
launchStudio({ specName: 'spec-w-visit.cy.js', createNewTestFromSuite: true }) | ||||||
|
||||||
// set a property on the window to see if the page reloads | ||||||
cy.window().then((w) => w['beforeReload'] = true) | ||||||
|
||||||
// close new test mode | ||||||
cy.findByTestId('studio-header-studio-button').click() | ||||||
|
||||||
// if this property is still set on the window, then the page didn't reload | ||||||
cy.window().then((w) => expect(w['beforeReload']).to.be.true) | ||||||
}) | ||||||
|
||||||
it('removes the studio url parameters when closing studio new test', () => { | ||||||
launchStudio({ specName: 'spec-w-visit.cy.js', createNewTestFromSuite: true }) | ||||||
|
||||||
|
@@ -747,6 +768,68 @@ describe('studio functionality', () => { | |||||
cy.location().its('hash').and('not.contain', 'suiteId=').and('not.contain', 'studio=') | ||||||
}) | ||||||
|
||||||
it('stays in new test mode when studio panel is opened when the spec is running', () => { | ||||||
loadProjectAndRunSpec() | ||||||
|
||||||
cy.waitForSpecToFinish() | ||||||
|
||||||
cy.findByTestId('studio-button').click() | ||||||
cy.findByTestId('studio-panel').should('be.visible') | ||||||
cy.findByTestId('new-test-button').should('be.visible') | ||||||
|
||||||
// Verify we're initially in new test mode | ||||||
cy.location().its('hash').should('contain', 'suiteId=r1').and('not.contain', 'testId=') | ||||||
|
||||||
// Now restart the spec, which will call interceptTest with the running test | ||||||
// This is where the bug would manifest - it would incorrectly switch from | ||||||
// "new test" mode to "edit the running test" mode | ||||||
cy.get('button.restart').click() | ||||||
|
||||||
cy.get('.test').should('have.length', 1) | ||||||
cy.get('.test').first().should('have.class', 'runnable-active') | ||||||
|
||||||
// verify we're still in new test mode | ||||||
cy.findByTestId('studio-panel').should('be.visible') | ||||||
cy.findByTestId('new-test-button').should('be.visible') | ||||||
|
||||||
// these should not exist if we stayed in new test mode | ||||||
cy.findByTestId('studio-single-test-title').should('not.exist') | ||||||
cy.findByTestId('record-button-recording').should('not.exist') | ||||||
|
||||||
// verify URL still shows suite mode, not edit test mode | ||||||
cy.location().its('hash').should('contain', 'suiteId=r1').and('not.contain', 'testId=') | ||||||
}) | ||||||
|
||||||
it('shows test body sections correctly when studio panel is open and page is refreshed', () => { | ||||||
loadProjectAndRunSpec() | ||||||
|
||||||
cy.waitForSpecToFinish() | ||||||
|
||||||
cy.findByTestId('studio-button').click() | ||||||
cy.findByTestId('studio-panel').should('be.visible') | ||||||
cy.findByTestId('new-test-button').should('be.visible') | ||||||
|
||||||
cy.reload() | ||||||
|
||||||
cy.waitForSpecToFinish() | ||||||
|
||||||
cy.findByTestId('studio-panel').should('be.visible') | ||||||
cy.findByTestId('new-test-button').should('be.visible') | ||||||
|
||||||
// verify test body section is visible after refresh | ||||||
cy.get('.runnable-instruments').should('be.visible') | ||||||
cy.get('.runnable-commands-region').should('be.visible') | ||||||
|
||||||
// verify the test body hook is present | ||||||
cy.get('.hook-item').contains('test body').should('be.visible') | ||||||
|
||||||
// verify commands are visible within the test body | ||||||
cy.get('.command-name-visit').should('be.visible') | ||||||
|
||||||
// Verify URL parameters show suite mode, not test mode | ||||||
cy.location().its('hash').should('contain', 'suiteId=r1').and('not.contain', 'testId=') | ||||||
}) | ||||||
|
||||||
describe('prompt for a new url', () => { | ||||||
const autUrl = 'http://localhost:4455/cypress/e2e/index.html' | ||||||
const visitUrl = 'cypress/e2e/index.html' | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -307,16 +307,25 @@ export class EventManager { | |
studioInitSuite({ suiteId }) | ||
}) | ||
|
||
const maybeCleanUpProtocol = () => { | ||
const needsReload = this.studioStore.needsProtocolCleanup() | ||
|
||
this.studioStore.cancel() | ||
|
||
// only reload the page if Studio has actually been used for recording | ||
if (needsReload) { | ||
window.location.reload() | ||
} | ||
} | ||
|
||
this.reporterBus.on('studio:cancel', () => { | ||
this.ws.emit('studio:destroy', ({ error }) => { | ||
if (error) { | ||
// eslint-disable-next-line no-console | ||
console.error(error) | ||
} | ||
|
||
this.studioStore.cancel() | ||
// Reloading for now. This is the easiest way to clear out the protocol code from the front end | ||
window.location.reload() | ||
maybeCleanUpProtocol() | ||
}) | ||
}) | ||
|
||
|
@@ -366,9 +375,7 @@ export class EventManager { | |
console.error(error) | ||
} | ||
|
||
this.studioStore.cancel() | ||
// Reloading for now. This is the easiest way to clear out the protocol code from the front end | ||
window.location.reload() | ||
maybeCleanUpProtocol() | ||
}) | ||
}) | ||
|
||
|
@@ -857,7 +864,8 @@ export class EventManager { | |
performance.measure('run', 'run-s', 'run-e') | ||
}) | ||
|
||
const hasRunnableId = !!this.studioStore.testId || !!this.studioStore.suiteId | ||
const hasActiveStudio = !!this.studioStore.testId || | ||
!!this.studioStore.newTestLineNumber | ||
|
||
const studioSingleTestActive = this.studioStore.newTestLineNumber != null || !!this.studioStore.testId | ||
|
||
|
@@ -869,7 +877,7 @@ export class EventManager { | |
autoScrollingEnabled: runState.autoScrollingEnabled, | ||
isSpecsListOpen: runState.isSpecsListOpen, | ||
scrollTop: runState.scrollTop, | ||
studioActive: hasRunnableId, | ||
studioActive: hasActiveStudio, | ||
studioSingleTestActive, | ||
} as ReporterStartInfo) | ||
} | ||
|
@@ -928,7 +936,9 @@ export class EventManager { | |
} | ||
|
||
_interceptStudio (displayProps) { | ||
if (this.studioStore.isActive) { | ||
// Only intercept logs when Studio is actually recording a specific test | ||
// Don't intercept when Studio is just open in "new test" mode | ||
if (this.studioStore.isActive && this.studioStore.testId) { | ||
Comment on lines
+939
to
+941
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. Is this function still needed? We don't even display logs anymore. 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 this still gets called - we don't display anything but it seems like if the logs are intercepted here, they don't get displayed in the command log. So I need to update this because otherwise when we refresh the page and studio is open to "new test", the test body section doesn't get displayed in the left panel. |
||
displayProps.hookId = this.studioStore.hookId | ||
|
||
if (displayProps.name === 'visit' && displayProps.state === 'failed') { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -175,6 +175,11 @@ export const useStudioStore = defineStore('studioRecorder', { | |
this.newTestLineNumber = undefined | ||
}, | ||
|
||
needsProtocolCleanup () { | ||
// Protocol cleanup (page reload) is only needed if Studio has actually been used for recording | ||
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. I don't think this comment is accurate anymore. 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. I think it is... we only want to refresh the page when studio closes if we've actually entered recording mode (like, we've made it past the "new test" screen and actually created a test or opened an existing test in studio) 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. ok, so by 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, exactly - I'll update the comment to make that more clear
astone123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return this._hasStarted || this.testId || this._isStudioCreatedTest | ||
}, | ||
|
||
openInstructionModal () { | ||
this.instructionModalIsOpen = true | ||
}, | ||
|
@@ -246,7 +251,7 @@ export const useStudioStore = defineStore('studioRecorder', { | |
|
||
interceptTest (test) { | ||
// if this test is the one we created, we can just set the test id | ||
if ((this.newTestLineNumber && test.invocationDetails?.line === this.newTestLineNumber) || this.suiteId) { | ||
if ((this.newTestLineNumber && test.invocationDetails?.line === this.newTestLineNumber) || (this.suiteId && this._hasStarted)) { | ||
this._isStudioCreatedTest = true | ||
this.setTestId(test.id) | ||
getCypress().runner.setIsStudioCreatedTest(true) | ||
|
@@ -848,7 +853,7 @@ export const useStudioStore = defineStore('studioRecorder', { | |
}, | ||
|
||
needsUrl: (state) => { | ||
return state.isActive && !state.url && !state.isFailed | ||
return state.isActive && !state.url && !state.isFailed && state._hasStarted | ||
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 was causing the AUT URL to get removed whenever the panel was open at all, even if it was just the new test screen |
||
}, | ||
|
||
testError: (state) => { | ||
|
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 should add a couple tests to verify this new behavior.
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.
added tests for both of these 👍🏻