From 807b3e38a3cff148d64c8cd4d8ea44cda7dc4845 Mon Sep 17 00:00:00 2001 From: Jess Date: Mon, 31 Jan 2022 16:20:49 -0500 Subject: [PATCH] feat: styling snapshots (#19972) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: adding styled snapshots * fixing type errors * fixing tests * test: make the content of tests visible Co-authored-by: Barthélémy Ledoux Co-authored-by: ElevateBart --- packages/app/cypress/support/fixtures.ts | 5 +- .../app/src/runner/SnapshotButtonGroup.vue | 5 - .../app/src/runner/SnapshotChangeState.vue | 40 ------- .../app/src/runner/SnapshotControls.cy.tsx | 101 +++++++++--------- packages/app/src/runner/SnapshotControls.vue | 96 +++++++++++++---- .../src/runner/SnapshotHighlightControls.vue | 65 +++++------ packages/app/src/runner/SnapshotMessage.vue | 39 ------- packages/app/src/runner/SnapshotToggle.cy.tsx | 52 +++++++++ packages/app/src/runner/SnapshotToggle.vue | 43 ++++++++ packages/app/src/runner/iframe-model.ts | 14 +-- packages/app/src/runner/index.ts | 3 + packages/app/src/runner/snapshot-store.ts | 32 ++---- .../frontend-shared/src/components/Switch.vue | 9 +- .../frontend-shared/src/locales/en-US.json | 11 ++ 14 files changed, 281 insertions(+), 234 deletions(-) delete mode 100644 packages/app/src/runner/SnapshotButtonGroup.vue delete mode 100644 packages/app/src/runner/SnapshotChangeState.vue delete mode 100644 packages/app/src/runner/SnapshotMessage.vue create mode 100644 packages/app/src/runner/SnapshotToggle.cy.tsx create mode 100644 packages/app/src/runner/SnapshotToggle.vue diff --git a/packages/app/cypress/support/fixtures.ts b/packages/app/cypress/support/fixtures.ts index d8effea942ba..1ce19d99fe26 100644 --- a/packages/app/cypress/support/fixtures.ts +++ b/packages/app/cypress/support/fixtures.ts @@ -10,12 +10,13 @@ export const autSnapshot: AutSnapshot = { y: 0, }, highlightAttr: '', - snapshots: [], + // @ts-ignore + snapshots: [{ name: 'Before' }, { name: 'After' }], htmlAttrs: {}, viewportHeight: 500, viewportWidth: 500, url: 'http://localhost:3000', body: { - get: () => null, + get: () => {}, }, } diff --git a/packages/app/src/runner/SnapshotButtonGroup.vue b/packages/app/src/runner/SnapshotButtonGroup.vue deleted file mode 100644 index 141e8635f131..000000000000 --- a/packages/app/src/runner/SnapshotButtonGroup.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/packages/app/src/runner/SnapshotChangeState.vue b/packages/app/src/runner/SnapshotChangeState.vue deleted file mode 100644 index 950392f79d04..000000000000 --- a/packages/app/src/runner/SnapshotChangeState.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/packages/app/src/runner/SnapshotControls.cy.tsx b/packages/app/src/runner/SnapshotControls.cy.tsx index 49c42ba1eef6..54047cb66719 100644 --- a/packages/app/src/runner/SnapshotControls.cy.tsx +++ b/packages/app/src/runner/SnapshotControls.cy.tsx @@ -3,13 +3,17 @@ import { autSnapshot } from '../../cypress/support/fixtures' import { useSnapshotStore } from './snapshot-store' import { createEventManager, createTestAutIframe } from '../../cypress/component/support/ctSupport' -// function createTestAutIframe () { -// return new class { -// removeHighlights () {} -// } -// } +const snapshotWithSnapshots = { ...autSnapshot } +const snapshotPinned = { ...autSnapshot, snapshots: [] } + +const snapshotControlsSelector = '[data-testid=snapshot-controls]' +const unpinButtonSelector = '[data-testid=unpin]' + +describe('SnapshotControls', { viewportHeight: 200, viewportWidth: 500 }, () => { + afterEach(() => { + cy.wait(100).percySnapshot() + }) -describe('SnapshotControls', () => { const mountSnapshotControls = ( eventManager = createEventManager(), autIframe = createTestAutIframe(), @@ -24,82 +28,73 @@ describe('SnapshotControls', () => { it('renders nothing when messageTitle is undefined', () => { mountSnapshotControls() - cy.get('[data-cy="snapshot-highlight-controls"]').should('not.exist') - cy.get('[data-cy="snapshot-message"]').should('not.exist') - cy.get('[data-cy="snapshot-change-state"]').should('not.exist') + cy.get(snapshotControlsSelector).should('not.exist') }) - it('renders snapshot title when one is pinned', () => { + it('renders the "pinned" snapshot title', () => { mountSnapshotControls() const snapshotStore = useSnapshotStore() - snapshotStore.pinSnapshot(autSnapshot) - cy.get('[data-cy="snapshot-message"]').contains('DOM Snapshot') - cy.get('[data-cy="snapshot-message"]').contains('(pinned)') + snapshotStore.pinSnapshot(snapshotPinned) + cy.get('body') + .findByText('Pinned') + .should('be.visible') }) - it('renders snapshot pinned status', () => { + it('pinned snapshots should not be dismissible', () => { mountSnapshotControls() const snapshotStore = useSnapshotStore() - snapshotStore.pinSnapshot(autSnapshot) - cy.get('[data-cy="snapshot-message"]').contains('DOM Snapshot') - cy.get('[data-cy="snapshot-message"]').contains('(pinned)') - .then(() => { - snapshotStore.unpinSnapshot() - cy.get('[data-cy="snapshot-message"]').should('not.contain', '(pinned)') - }) + snapshotStore.pinSnapshot(snapshotPinned) + cy.get('body') + .findByText('Pinned') + .should('be.visible') + .get(unpinButtonSelector) + .should('not.exist') }) it('clears snapshot message', () => { mountSnapshotControls() const snapshotStore = useSnapshotStore() - snapshotStore.pinSnapshot(autSnapshot) - cy.then(() => cy.get('[data-cy="snapshot-message"]').should('exist')) - .then(() => snapshotStore.clearMessage()) - .get('[data-cy="snapshot-message"]').should('not.exist') - }) - - it('shows snapshot with custom message', () => { - mountSnapshotControls() - const message = 'This is a custom message' - const snapshotStore = useSnapshotStore() - - snapshotStore.showSnapshot(message) - cy.get('[data-cy="snapshot-message"]').contains(message) + snapshotStore.pinSnapshot(snapshotWithSnapshots) + cy.get('body') + .findByText('Pinned') + .should('be.visible') + .get(unpinButtonSelector) + .click({ force: true }) + .get('body') + .findByText('Pinned') + .should('not.exist') }) it('does not show highlight controls if no element present on snapshot', () => { mountSnapshotControls() const snapshotStore = useSnapshotStore() - snapshotStore.pinSnapshot(autSnapshot) - cy.get('[data-cy="snapshot-highlight-controls"]').should('not.exist') + snapshotStore.pinSnapshot(snapshotWithSnapshots) + cy.get('body').findByText('Highlights').should('not.exist') }) it('toggles highlight controls if snapshot has an element', () => { const snapshotStore = useSnapshotStore() const eventManager = createEventManager() const autIframe = createTestAutIframe() - const removeHighlights = cy.stub(autIframe, 'removeHighlights') // we don't have an iframe-model since this is a CT test, but we can // simulate it by registering the same unpin:snapshot event it does. - eventManager.on('unpin:snapshot', () => snapshotStore.unpinSnapshot()) - snapshotStore.pinSnapshot({ ...autSnapshot, $el: 'some element' }) + eventManager.on('unpin:snapshot', () => snapshotStore.$reset()) + + // debugger + // console.log('snapshotWithSnapshots', snapshotWithSnapshots) + snapshotStore.pinSnapshot({ ...snapshotWithSnapshots, $el: document.body }) mountSnapshotControls(eventManager, autIframe) - cy.get('[data-cy="snapshot-highlight-controls"]').should('exist') - cy.get('[data-cy="toggle-snapshot-highlights"]').as('toggle') - cy.get('@toggle').should('have.attr', 'title', 'Hide highlights') - cy.get('@toggle').click().then(() => { - expect(removeHighlights).to.have.been.calledOnce - }) - - cy.get('@toggle').should('have.attr', 'title', 'Show highlights') - cy.get('[data-cy="unpin-snapshot"]').click() - cy.get('[data-cy="snapshot-highlight-controls"]').should('not.exist') + cy.get('body') + .findByText('Highlights') + .should('be.visible') + .findByLabelText('Toggle highlights') + .click({ force: true }) }) it('shows running test error', () => { @@ -107,7 +102,9 @@ describe('SnapshotControls', () => { const snapshotStore = useSnapshotStore() snapshotStore.setTestsRunningError() - cy.get('[data-cy="snapshot-message"]').contains('Cannot show Snapshot while tests are running') + cy.get('body') + .findByText('Cannot show Snapshot while tests are running') + .should('be.visible') }) it('shows snapshot missing error', () => { @@ -115,6 +112,8 @@ describe('SnapshotControls', () => { const snapshotStore = useSnapshotStore() snapshotStore.setMissingSnapshotMessage() - cy.get('[data-cy="snapshot-message"]').contains('The snapshot is missing. Displaying current state of the DOM.') + cy.get('body') + .findByText('The snapshot is missing. Displaying current state of the DOM.') + .should('be.visible') }) }) diff --git a/packages/app/src/runner/SnapshotControls.vue b/packages/app/src/runner/SnapshotControls.vue index 4dbb429520fe..a09e07858893 100644 --- a/packages/app/src/runner/SnapshotControls.vue +++ b/packages/app/src/runner/SnapshotControls.vue @@ -1,23 +1,43 @@ @@ -25,11 +45,10 @@ diff --git a/packages/app/src/runner/SnapshotHighlightControls.vue b/packages/app/src/runner/SnapshotHighlightControls.vue index e595ff9d3125..231b868f983b 100644 --- a/packages/app/src/runner/SnapshotHighlightControls.vue +++ b/packages/app/src/runner/SnapshotHighlightControls.vue @@ -1,46 +1,37 @@ - - diff --git a/packages/app/src/runner/SnapshotMessage.vue b/packages/app/src/runner/SnapshotMessage.vue deleted file mode 100644 index 749c6a5a4a77..000000000000 --- a/packages/app/src/runner/SnapshotMessage.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - diff --git a/packages/app/src/runner/SnapshotToggle.cy.tsx b/packages/app/src/runner/SnapshotToggle.cy.tsx new file mode 100644 index 000000000000..d0997833b638 --- /dev/null +++ b/packages/app/src/runner/SnapshotToggle.cy.tsx @@ -0,0 +1,52 @@ +import SnapshotToggle from './SnapshotToggle.vue' + +describe('', () => { + it('renders two segments', () => { + const messages = [{ text: '1', id: '1' }, { text: '2', id: '2' }] + + cy.mount(() => ()) + + cy.percySnapshot() + .get('body') + .findByText('2') + .click() + .parent() + .findByText('1') + .click() + .percySnapshot() + }) + + it('renders longer text', () => { + const messages = [{ text: 'Request', id: '1' }, { text: 'Response', id: '2' }] + + cy.mount(() => ()) + + cy.percySnapshot() + .get('body') + .findByText('Request') + .click() + .parent() + .findByText('Response') + .click() + .percySnapshot() + }) + + it('emits a select event with the active message', () => { + const messages = [{ text: 'Request', id: '1' }, { text: 'Response', id: '2' }] + + const onSelectSpy = cy.spy().as('onSelect') + + cy.mount(() => ()) + + cy.get('body') + .findByText('Request') + .click() + .get('@onSelect') + .should('have.been.calledWith', { message: messages[0], idx: 0 }) + .get('body') + .findByText('Response') + .click() + .get('@onSelect') + .should('have.been.calledWith', { message: messages[1], idx: 1 }) + }) +}) diff --git a/packages/app/src/runner/SnapshotToggle.vue b/packages/app/src/runner/SnapshotToggle.vue new file mode 100644 index 000000000000..947e080bfa5a --- /dev/null +++ b/packages/app/src/runner/SnapshotToggle.vue @@ -0,0 +1,43 @@ + + + diff --git a/packages/app/src/runner/iframe-model.ts b/packages/app/src/runner/iframe-model.ts index a4f4ff41111e..2e2e4fcb13f0 100644 --- a/packages/app/src/runner/iframe-model.ts +++ b/packages/app/src/runner/iframe-model.ts @@ -1,6 +1,7 @@ import { useSnapshotStore } from './snapshot-store' import { useAutStore } from '../store' import type { EventManager } from './event-manager' +import { defaultMessages } from '@cy/i18n' export interface AutSnapshot { id?: number @@ -73,7 +74,6 @@ export class IframeModel { } _beforeRun = () => { - const snapshotStore = useSnapshotStore() const autStore = useAutStore() autStore.setIsLoading(false) @@ -82,7 +82,6 @@ export class IframeModel { this.studio.selectorPlaygroundModel.setEnabled(false) this._reset() - snapshotStore.clearMessage() } _afterRun = () => { @@ -236,17 +235,14 @@ export class IframeModel { } _unpinSnapshot = () => { - const snapshotStore = useSnapshotStore() - - snapshotStore.unpinSnapshot() + useSnapshotStore().$reset() } _studioOpenError () { const snapshotStore = useSnapshotStore() snapshotStore.setMessage( - 'Cannot show Snapshot while creating commands in Studio', - 'warning', + defaultMessages.runner.snapshot.studioActiveError, ) } @@ -278,8 +274,6 @@ export class IframeModel { this.intervalId = undefined this.originalState = undefined - const snapshotStore = useSnapshotStore() - - snapshotStore.setSnapshotPinned(false) + useSnapshotStore().$reset() } } diff --git a/packages/app/src/runner/index.ts b/packages/app/src/runner/index.ts index a92b9ee78757..35b26688d817 100644 --- a/packages/app/src/runner/index.ts +++ b/packages/app/src/runner/index.ts @@ -26,6 +26,7 @@ import { EventManager } from './event-manager' import { client } from '@packages/socket/lib/browser' import { decodeBase64Unicode } from '@packages/frontend-shared/src/utils/base64' import type { AutomationElementId } from '@packages/types/src' +import { useSnapshotStore } from './snapshot-store' let _eventManager: EventManager | undefined @@ -162,6 +163,8 @@ function getSpecUrl (namespace: string, specSrc: string) { * or re-running the current spec. */ function teardownSpec () { + useSnapshotStore().$reset() + return getEventManager().teardown(getMobxRunnerStore()) } diff --git a/packages/app/src/runner/snapshot-store.ts b/packages/app/src/runner/snapshot-store.ts index a1bd16856ac1..ad5542f90d68 100644 --- a/packages/app/src/runner/snapshot-store.ts +++ b/packages/app/src/runner/snapshot-store.ts @@ -1,13 +1,10 @@ import { defineStore } from 'pinia' import type { AutSnapshot } from './iframe-model' import type { AutIframe } from './aut-iframe' - -export type SnapshotMessageType = 'info' | 'warning' | 'pinned' +import { defaultMessages } from '@cy/i18n' interface SnapshotStoreState { messageTitle?: string - messageDescription?: 'pinned' | string - messageType?: SnapshotMessageType snapshotProps?: AutSnapshot isSnapshotPinned: boolean snapshot?: { @@ -21,7 +18,6 @@ export const useSnapshotStore = defineStore({ state: (): SnapshotStoreState => { return { messageTitle: undefined, - messageDescription: undefined, isSnapshotPinned: false, snapshot: undefined, snapshotProps: undefined, @@ -33,9 +29,7 @@ export const useSnapshotStore = defineStore({ }, pinSnapshot (snapshotProps: AutSnapshot) { - this.messageTitle = 'DOM Snapshot' - this.messageDescription = 'pinned' - this.messageType = 'info' + this.messageTitle = defaultMessages.runner.snapshot.pinnedTitle this.isSnapshotPinned = true this.snapshotProps = snapshotProps this.snapshot = { @@ -46,20 +40,14 @@ export const useSnapshotStore = defineStore({ clearMessage () { this.messageTitle = undefined - this.messageDescription = undefined - this.messageType = undefined }, unpinSnapshot () { - this.isSnapshotPinned = false - this.messageTitle = 'DOM Snapshot' - this.messageDescription = undefined + this.$reset() }, - showSnapshot (messageDescription?: string) { - this.messageTitle = 'DOM Snapshot' - this.messageDescription = messageDescription - this.messageType = undefined + showSnapshot (messageDescription: string = defaultMessages.runner.snapshot.defaultTitle) { + this.messageTitle = messageDescription }, toggleHighlights (autIframe: AutIframe) { @@ -104,19 +92,15 @@ export const useSnapshotStore = defineStore({ }, setTestsRunningError () { - this.messageTitle = 'Cannot show Snapshot while tests are running' - this.messageType = 'warning' + this.messageTitle = defaultMessages.runner.snapshot.testsRunningError }, - setMessage (messageTitle: string, messageType: SnapshotMessageType) { + setMessage (messageTitle: string) { this.messageTitle = messageTitle - this.messageType = messageType }, setMissingSnapshotMessage () { - this.messageTitle = 'The snapshot is missing. Displaying current state of the DOM.' - this.messageDescription = undefined - this.messageType = 'warning' + this.messageTitle = defaultMessages.runner.snapshot.snapshotMissingError }, }, }) diff --git a/packages/frontend-shared/src/components/Switch.vue b/packages/frontend-shared/src/components/Switch.vue index f2cb274e7ca9..7d8f99e988d7 100644 --- a/packages/frontend-shared/src/components/Switch.vue +++ b/packages/frontend-shared/src/components/Switch.vue @@ -1,14 +1,16 @@