mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-11 01:29:59 -06:00
Merge branch '10.0-release' of https://github.com/cypress-io/cypress into tbiethman/develop-into-10-with-electron
This commit is contained in:
@@ -45,13 +45,11 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
|
||||
cy.get('.command-name-session').contains('blank_session')
|
||||
validateCreateNewSessionGroup()
|
||||
})
|
||||
|
||||
@@ -70,14 +68,11 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
|
||||
cy.get('.command-name-session').contains('blank_session')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
|
||||
cy.contains('Validate Session: valid')
|
||||
@@ -106,14 +101,11 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
|
||||
cy.get('.command-name-session').contains('blank_session')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
|
||||
cy.contains('Validate Session: invalid')
|
||||
@@ -151,13 +143,10 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-pending')
|
||||
.siblings().should('contain', '(saved) user1')
|
||||
|
||||
cy.get('.command-name-session').contains('user1')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
@@ -208,13 +197,10 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-bad')
|
||||
.siblings().should('contain', '(recreated) user1')
|
||||
|
||||
cy.get('.command-name-session').contains('user1')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
@@ -272,13 +258,10 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-bad')
|
||||
.siblings().should('contain', '(recreated) user1')
|
||||
|
||||
cy.get('.command-name-session').contains('user1')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
|
||||
@@ -99,7 +99,7 @@ describe('App: Settings', () => {
|
||||
cy.waitForSpecToFinish()
|
||||
// Wait for the test to pass, so the test is completed
|
||||
cy.get('.passed > .num').should('contain', 1)
|
||||
cy.get(`[href='#/settings']`).click()
|
||||
cy.get('[href="#/settings"]').click()
|
||||
cy.contains('Dashboard Settings').click()
|
||||
// Assert the data is not there before it arrives
|
||||
cy.contains('Record Key').should('not.exist')
|
||||
@@ -114,18 +114,18 @@ describe('App: Settings', () => {
|
||||
o.sinon.spy(ctx.actions.auth, 'logout')
|
||||
})
|
||||
|
||||
cy.get(`[href='#/settings']`).click()
|
||||
cy.get('[href="#/settings"]').click()
|
||||
cy.contains('Dashboard Settings').click()
|
||||
cy.contains('Record Key').should('exist')
|
||||
cy.get(`[href='#/runs']`).click()
|
||||
cy.get('[data-cy="user-avatar-title"]').click()
|
||||
cy.get('[href="#/runs"]').click()
|
||||
cy.findByTestId('user-avatar-title').click()
|
||||
cy.findByRole('button', { name: 'Log Out' }).click()
|
||||
|
||||
cy.withRetryableCtx((ctx, o) => {
|
||||
expect(ctx.actions.auth.logout).to.have.been.calledOnce
|
||||
})
|
||||
|
||||
cy.get(`[href='#/settings']`).click()
|
||||
cy.get('[href="#/settings"]').click()
|
||||
cy.contains('Dashboard Settings').click()
|
||||
cy.contains('Record Key').should('not.exist')
|
||||
})
|
||||
|
||||
@@ -1,6 +1,50 @@
|
||||
import type { SinonStub } from 'sinon'
|
||||
|
||||
describe('Sidebar Navigation', () => {
|
||||
context('accessibility', () => {
|
||||
beforeEach(() => {
|
||||
cy.scaffoldProject('todos')
|
||||
cy.openProject('todos')
|
||||
cy.startAppServer()
|
||||
cy.visitApp()
|
||||
cy.contains('todos')
|
||||
})
|
||||
|
||||
it('can tab through navigation', () => {
|
||||
cy.get('body').focus()
|
||||
.tab().should('have.attr', 'data-cy', 'toggle-sidebar').should('have.prop', 'tagName', 'BUTTON')
|
||||
.tab().should('have.attr', 'data-cy', 'sidebar-header').should('have.attr', 'role', 'button')
|
||||
.tab().should('have.attr', 'href', '#/specs').should('have.prop', 'tagName', 'A')
|
||||
.tab().should('have.attr', 'href', '#/runs').should('have.prop', 'tagName', 'A')
|
||||
.tab().should('have.attr', 'href', '#/settings').should('have.prop', 'tagName', 'A')
|
||||
.tab().should('have.attr', 'data-cy', 'keyboard-modal-trigger').should('have.prop', 'tagName', 'BUTTON')
|
||||
})
|
||||
|
||||
it('has no axe violations', () => {
|
||||
cy.injectAxe()
|
||||
cy.checkA11y('[data-cy="sidebar"]')
|
||||
})
|
||||
|
||||
it('has appropriate aria attributes', () => {
|
||||
cy.findByTestId('toggle-sidebar')
|
||||
.should('have.attr', 'aria-controls', 'sidebar')
|
||||
.should('have.attr', 'aria-expanded', 'true')
|
||||
.should('have.attr', 'aria-label', 'Collapse sidebar')
|
||||
.click()
|
||||
.should('have.attr', 'aria-expanded', 'false')
|
||||
.should('have.attr', 'aria-label', 'Expand sidebar')
|
||||
|
||||
cy.findByTestId('keyboard-modal-trigger')
|
||||
.should('have.attr', 'aria-label', 'Keyboard Shortcuts')
|
||||
|
||||
cy.get('nav')
|
||||
.should('have.attr', 'aria-label', 'Pages')
|
||||
|
||||
cy.findByTestId('sidebar-header')
|
||||
.should('have.attr', 'aria-label', 'todos - Choose a testing type')
|
||||
})
|
||||
})
|
||||
|
||||
context('as e2e testing type with localSettings', () => {
|
||||
it('use saved state for nav size', () => {
|
||||
cy.withCtx(async (ctx) => {
|
||||
@@ -16,7 +60,7 @@ describe('Sidebar Navigation', () => {
|
||||
|
||||
cy.get('.toggle-specs-text').click()
|
||||
|
||||
cy.get('[data-cy="reporter-panel"]').invoke('outerWidth').then(($initialWidth) => {
|
||||
cy.findByTestId('reporter-panel').invoke('outerWidth').then(($initialWidth) => {
|
||||
expect($initialWidth).eq(100)
|
||||
})
|
||||
})
|
||||
@@ -32,66 +76,45 @@ describe('Sidebar Navigation', () => {
|
||||
})
|
||||
|
||||
it('expands the left nav bar by default', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findByTestId('sidebar').should('have.css', 'width', '248px') // assert width to ensure transition has finished
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('highlights indicator on hover showing you can click to expand', () => {
|
||||
const navIndicatorSelector = '[data-testid=sidebar-nav-indicator]'
|
||||
const navExpansionToggleSelector = '[aria-label="toggle navigation"]'
|
||||
const navIndicatorSelector = '[data-cy=sidebar-nav-indicator]'
|
||||
|
||||
cy.get(navIndicatorSelector)
|
||||
.should('not.be.visible')
|
||||
.get(navExpansionToggleSelector)
|
||||
.realHover()
|
||||
.get(navIndicatorSelector)
|
||||
.should('be.visible')
|
||||
.percySnapshot()
|
||||
cy.get(navIndicatorSelector).should('not.be.visible')
|
||||
cy.findByTestId('toggle-sidebar').realHover()
|
||||
cy.get(navIndicatorSelector).should('be.visible')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('closes the left nav bar when clicking the expand button (if expanded)', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findAllByText('todos').eq(1).as('title')
|
||||
cy.get('@title').should('be.visible')
|
||||
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
cy.get('@title').should('not.be.visible')
|
||||
cy.findByTestId('sidebar').contains('todos').should('be.visible')
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar').contains('todos').should('not.be.visible')
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('closes the left nav bar when clicking the expand button and persist the state if browser is refreshed', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findAllByText('todos').eq(1).as('title')
|
||||
cy.get('@title').should('be.visible')
|
||||
cy.findByTestId('sidebar').contains('todos').should('be.visible')
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
cy.get('@title').should('not.be.visible')
|
||||
cy.findByTestId('sidebar').contains('todos').should('not.be.visible')
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
cy.findAllByText('todos').should('not.be.visible')
|
||||
cy.findByTestId('sidebar').contains('todos').should('not.be.visible')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('has unlabeled menu item that shows the keyboard shortcuts modal (unexpanded state)', () => {
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
it('has menu item that shows the keyboard shortcuts modal (unexpanded state)', () => {
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar').should('have.css', 'width', '64px') // assert width to ensure transition has finished
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
|
||||
cy.get('[data-cy="keyboard-shortcuts"]').should('be.visible')
|
||||
cy.get('[data-cy="keyboard-shortcuts"]').click()
|
||||
cy.findByTestId('keyboard-modal-trigger').should('be.visible').click()
|
||||
cy.contains('h2', 'Keyboard Shortcuts').should('be.visible')
|
||||
cy.get('li p').contains('Re-run tests').should('be.visible')
|
||||
cy.get('li p').contains('Stop tests').should('be.visible')
|
||||
@@ -106,52 +129,38 @@ describe('Sidebar Navigation', () => {
|
||||
})
|
||||
|
||||
it('shows a tooltip when hovering over menu item', () => {
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar').should('have.css', 'width', '64px') // assert width to ensure transition has finished
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
|
||||
cy.get('[data-cy="sidebar-header"').trigger('mouseenter')
|
||||
cy.findByTestId('sidebar-header').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'todos')
|
||||
cy.percySnapshot()
|
||||
cy.get('[data-cy="sidebar-header"]').trigger('mouseout')
|
||||
cy.findByTestId('sidebar-header').trigger('mouseout')
|
||||
|
||||
cy.get('[data-e2e-href="/runs"]').trigger('mouseenter')
|
||||
cy.get('[href="#/runs"]').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'Runs')
|
||||
cy.get('[data-e2e-href="/runs"]').trigger('mouseout')
|
||||
cy.get('[href="#/runs"]').trigger('mouseout')
|
||||
|
||||
cy.get('[data-e2e-href="/specs"]').trigger('mouseenter')
|
||||
cy.get('[href="#/specs"]').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'Specs')
|
||||
cy.get('[data-e2e-href="/specs"]').trigger('mouseout')
|
||||
cy.get('[href="#/specs"]').trigger('mouseout')
|
||||
|
||||
cy.get('[data-e2e-href="/settings"]').trigger('mouseenter')
|
||||
cy.get('[href="#/settings"]').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'Settings')
|
||||
cy.get('[data-e2e-href="/settings"]').trigger('mouseout')
|
||||
cy.get('[href="#/settings"]').trigger('mouseout')
|
||||
})
|
||||
|
||||
it('opens the left nav bar when clicking the expand button (if unexpanded)', () => {
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.findAllByText('todos').eq(1).should('not.be.visible')
|
||||
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findAllByText('todos').eq(1).should('be.visible')
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar').contains('todos').should('not.be.visible')
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar').contains('todos').should('be.visible')
|
||||
})
|
||||
|
||||
it('displays the project name and opens a modal to switch testing type', () => {
|
||||
cy.visitApp()
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
cy.get('[data-cy="sidebar-header"]').within(() => {
|
||||
cy.get('[data-cy="testing-type-e2e"]').should('be.visible')
|
||||
cy.findByText('todos').should('be.visible')
|
||||
cy.findByTestId('sidebar-header').within(() => {
|
||||
cy.findByTestId('testing-type-e2e').should('be.visible')
|
||||
cy.contains('todos').should('be.visible')
|
||||
}).as('switchTestingType').click()
|
||||
|
||||
cy.findByRole('dialog', {
|
||||
@@ -192,20 +201,13 @@ describe('Sidebar Navigation', () => {
|
||||
|
||||
cy.get('[aria-label="Close"]').click()
|
||||
cy.findByText('Choose a testing type').should('not.exist')
|
||||
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.get('[data-cy="sidebar-header"]').click()
|
||||
cy.findByTestId('toggle-sidebar').click()
|
||||
cy.findByTestId('sidebar-header').click()
|
||||
cy.findByText('Choose a testing type').should('be.visible')
|
||||
})
|
||||
|
||||
it('has unlabeled menu item that shows the keyboard shortcuts modal (expanded state)', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
cy.get('[data-cy="keyboard-shortcuts"]').should('be.visible')
|
||||
cy.get('[data-cy="keyboard-shortcuts"]').click()
|
||||
it('has menu item that shows the keyboard shortcuts modal (expanded state)', () => {
|
||||
cy.findByTestId('keyboard-modal-trigger').should('be.visible').click()
|
||||
cy.contains('h2', 'Keyboard Shortcuts').should('be.visible')
|
||||
cy.get('li p').contains('Re-run tests').should('be.visible')
|
||||
cy.get('li p').contains('Stop tests').should('be.visible')
|
||||
@@ -218,20 +220,15 @@ describe('Sidebar Navigation', () => {
|
||||
})
|
||||
|
||||
it('has a menu item labeled "Runs" which takes you to the Runs page', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
cy.get('[data-cy="app-header-bar"]').findByText('Runs').should('not.exist')
|
||||
cy.findByText('Runs').should('be.visible')
|
||||
cy.findByText('Runs').click()
|
||||
cy.findByText('Runs').should('be.visible').click()
|
||||
cy.get('[data-cy="app-header-bar"]').findByText('Runs').should('be.visible')
|
||||
cy.get('.router-link-active').findByText('Runs').should('be.visible')
|
||||
})
|
||||
|
||||
it('has a menu item labeled "Specs" which takes you to the Spec List page', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findByLabelText('Sidebar').within(() => {
|
||||
cy.findByText('Specs').should('be.visible')
|
||||
cy.findByText('Specs').click()
|
||||
cy.findByTestId('sidebar').within(() => {
|
||||
cy.findByText('Specs').should('be.visible').click()
|
||||
})
|
||||
|
||||
cy.get('[data-cy="app-header-bar"]').findByText('Specs').should('be.visible')
|
||||
@@ -239,18 +236,15 @@ describe('Sidebar Navigation', () => {
|
||||
})
|
||||
|
||||
it('has a menu item labeled "Settings" which takes you to the Settings page', () => {
|
||||
cy.findByLabelText('Sidebar').closest('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
|
||||
cy.get('[data-cy="app-header-bar"]').findByText('Settings').should('not.exist')
|
||||
cy.findByTestId('app-header-bar').findByText('Settings').should('not.exist')
|
||||
cy.findByText('Settings').should('be.visible')
|
||||
cy.findByText('Settings').click()
|
||||
cy.get('[data-cy="app-header-bar"]').findByText('Settings').should('be.visible')
|
||||
cy.findByTestId('app-header-bar').findByText('Settings').should('be.visible')
|
||||
cy.get('.router-link-active').findByText('Settings').should('be.visible')
|
||||
})
|
||||
|
||||
it('resize nav sends the correct value on the mutation', () => {
|
||||
cy.contains('fixture.js').click()
|
||||
|
||||
cy.withCtx((ctx, o) => {
|
||||
o.sinon.stub(ctx.actions.localSettings, 'setPreferences').resolves()
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('App: Spec List (E2E)', () => {
|
||||
})
|
||||
|
||||
it('shows the "Specs" navigation as highlighted in the lefthand nav bar', () => {
|
||||
cy.findByLabelText('Sidebar').within(() => {
|
||||
cy.findByTestId('sidebar').within(() => {
|
||||
cy.findByText('Specs').should('be.visible')
|
||||
cy.findByText('Specs').click()
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('specChange subscription', () => {
|
||||
|
||||
describe('on config page', () => {
|
||||
it('responds to configChange event when viewport is changed', () => {
|
||||
cy.get('a').contains('Settings').click()
|
||||
cy.contains('a', 'Settings').click()
|
||||
cy.get('[data-cy="collapsible-header"]').contains('Project Settings').click()
|
||||
cy.contains(`projectId: 'abc123'`)
|
||||
updateProjectIdInCypressConfig('foo456')
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('KeyboardBindingsModal', () => {
|
||||
return <KeyboardBindingsModal show />
|
||||
})
|
||||
|
||||
const expectedContent = defaultMessages.sideBar.keyboardShortcuts
|
||||
const expectedContent = defaultMessages.sidebar.keyboardShortcuts
|
||||
|
||||
Object.values(expectedContent).forEach((text) => {
|
||||
cy.contains(text).should('be.visible')
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<StandardModal
|
||||
class="transition transition-all duration-200"
|
||||
variant="bare"
|
||||
:title="t('sideBar.keyboardShortcuts.title')"
|
||||
:title="t('sidebar.keyboardShortcuts.title')"
|
||||
:model-value="show"
|
||||
data-cy="switch-modal"
|
||||
data-cy="keyboard-modal"
|
||||
help-link=""
|
||||
@update:model-value="emits('close')"
|
||||
>
|
||||
@@ -46,15 +46,15 @@ const emits = defineEmits<{
|
||||
const keyBindings = [
|
||||
{
|
||||
key: ['r'],
|
||||
description: t('sideBar.keyboardShortcuts.rerun'),
|
||||
description: t('sidebar.keyboardShortcuts.rerun'),
|
||||
},
|
||||
{
|
||||
key: ['s'],
|
||||
description: t('sideBar.keyboardShortcuts.stop'),
|
||||
description: t('sidebar.keyboardShortcuts.stop'),
|
||||
},
|
||||
{
|
||||
key: ['f'],
|
||||
description: t('sideBar.keyboardShortcuts.toggle'),
|
||||
description: t('sidebar.keyboardShortcuts.toggle'),
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import SidebarNavigation from './SidebarNavigation.vue'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
|
||||
function mountComponent (initialNavExpandedVal = true) {
|
||||
cy.mount(() => {
|
||||
@@ -16,32 +17,42 @@ describe('SidebarNavigation', () => {
|
||||
it('expands the bar when clicking the expand button', () => {
|
||||
mountComponent()
|
||||
|
||||
cy.get('[aria-expanded]').should('have.attr', 'aria-expanded', 'false')
|
||||
cy.findByText('test-project').should('not.be.visible')
|
||||
cy.findByLabelText('toggle navigation', {
|
||||
cy.findByLabelText(defaultMessages.sidebar.toggleLabel.collapsed, {
|
||||
selector: 'button',
|
||||
}).click()
|
||||
|
||||
cy.get('[aria-expanded]').should('have.attr', 'aria-expanded', 'true')
|
||||
cy.findByLabelText(defaultMessages.sidebar.toggleLabel.expanded, {
|
||||
selector: 'button',
|
||||
})
|
||||
|
||||
cy.findByText('test-project').should('be.visible')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('shows tooltips on hover', () => {
|
||||
mountComponent(false)
|
||||
cy.get('[data-cy="sidebar-header"').trigger('mouseenter')
|
||||
cy.findByTestId('sidebar-header').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'test-project').should('be.visible')
|
||||
cy.get('[data-cy="sidebar-header"]').trigger('mouseout')
|
||||
cy.findByTestId('sidebar-header').trigger('mouseout')
|
||||
|
||||
cy.get('[data-e2e-href="/runs"]').trigger('mouseenter')
|
||||
cy.get('[href="#/runs"]').trigger('mouseenter')
|
||||
cy.contains('.v-popper--some-open--tooltip', 'Runs').should('be.visible')
|
||||
cy.get('[data-e2e-href="/runs"]').trigger('mouseout')
|
||||
cy.get('[href="#/runs"]').trigger('mouseout')
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('opens a modal to switch testing type', { viewportWidth: 1280 }, () => {
|
||||
mountComponent()
|
||||
cy.get('[data-cy="sidebar-header"]').click()
|
||||
cy.findByTestId('sidebar-header').click()
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('opens a modal to show keyboard shortcuts', () => {
|
||||
mountComponent()
|
||||
cy.findByTestId('keyboard-modal').should('not.exist')
|
||||
cy.findByTestId('keyboard-modal-trigger').focus().type('{enter}')
|
||||
cy.findByTestId('keyboard-modal').should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
<template>
|
||||
<HideDuringScreenshot
|
||||
id="sidebar"
|
||||
data-cy="sidebar"
|
||||
:aria-expanded="isNavBarExpanded"
|
||||
class="flex flex-col bg-gray-1000 transition-all duration-300 relative"
|
||||
:class="isNavBarExpanded ? 'w-248px' : 'w-64px'"
|
||||
>
|
||||
<button
|
||||
v-if="navIsAlwaysCollapsed"
|
||||
class="cursor-pointer left-full top-0 bottom-0 w-16px z-1 absolute group hocus:outline-transparent"
|
||||
role="button"
|
||||
aria-label="toggle navigation"
|
||||
type="button"
|
||||
:aria-label="isNavBarExpanded ? t('sidebar.toggleLabel.expanded') : t('sidebar.toggleLabel.collapsed')"
|
||||
data-cy="toggle-sidebar"
|
||||
:aria-expanded="isNavBarExpanded"
|
||||
aria-controls="sidebar"
|
||||
@click="toggleNavbarIfAllowed"
|
||||
>
|
||||
<div
|
||||
data-testid="sidebar-nav-indicator"
|
||||
data-cy="sidebar-nav-indicator"
|
||||
class="flex h-full transform origin-left transition-transform w-16px scale-x-0 duration-300 items-center group-hocus:scale-x-100"
|
||||
>
|
||||
<div class="h-full bg-indigo-400 w-3px" />
|
||||
@@ -31,7 +34,7 @@
|
||||
/>
|
||||
<nav
|
||||
class="space-y-1 bg-gray-1000 flex-1"
|
||||
aria-label="Sidebar"
|
||||
:aria-label="t('sidebar.nav.ariaLabel')"
|
||||
>
|
||||
<RouterLink
|
||||
v-for="item in navigation"
|
||||
@@ -40,7 +43,6 @@
|
||||
:to="item.href"
|
||||
>
|
||||
<SidebarNavigationRow
|
||||
:data-e2e-href="item.href"
|
||||
:active="isActive"
|
||||
:icon="item.icon"
|
||||
:name="item.name"
|
||||
@@ -54,22 +56,22 @@
|
||||
:distance="8"
|
||||
:skidding="-16"
|
||||
>
|
||||
<div
|
||||
<button
|
||||
data-cy="keyboard-modal-trigger"
|
||||
type="button"
|
||||
class="border border-transparent rounded
|
||||
cursor-pointer h-32px m-16px
|
||||
p-7px transform transition-all
|
||||
right-0 bottom-0 w-32px duration-300
|
||||
inline-block absolute hover:border-gray-500"
|
||||
:class="{ '-translate-y-48px': !isNavBarExpanded }"
|
||||
:aria-label="t('sidebar.keyboardShortcuts.title')"
|
||||
@click="bindingsOpen = true"
|
||||
>
|
||||
<i-cy-command-key_x16
|
||||
class="h-16px w-16px icon-dark-gray-500"
|
||||
data-cy="keyboard-shortcuts"
|
||||
/>
|
||||
</div>
|
||||
<i-cy-command-key_x16 class="h-16px w-16px icon-dark-gray-500" />
|
||||
</button>
|
||||
<template #popper>
|
||||
{{ t('sideBar.keyboardShortcuts.title') }}
|
||||
{{ t('sidebar.keyboardShortcuts.title') }}
|
||||
</template>
|
||||
</Tooltip>
|
||||
<KeyboardBindingsModal
|
||||
@@ -79,6 +81,7 @@
|
||||
<img
|
||||
:src="CypressLogo"
|
||||
class="h-32px m-16px w-32px"
|
||||
alt="Cypress"
|
||||
>
|
||||
</div>
|
||||
</HideDuringScreenshot>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
:distance="8"
|
||||
>
|
||||
<div
|
||||
role="button"
|
||||
:aria-label="`${props.gql.currentProject?.title ?? 'Cypress'} - ${t('testingType.modalTitle')}`"
|
||||
class="border-b cursor-pointer flex border-gray-900 flex-shrink-0 h-64px pl-20px transition-all duration-300 items-center hover:bg-gray-900"
|
||||
:popper-top-offset="4"
|
||||
popper-class="h-56px"
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
:data-selected="active"
|
||||
>
|
||||
<component
|
||||
:is="
|
||||
icon"
|
||||
:is="icon"
|
||||
:class="active ? 'icon-dark-indigo-300 icon-light-indigo-700' : 'icon-dark-gray-500 icon-light-gray-900 group-hover:(icon-dark-gray-300 icon-light-gray-800) group-focus:(icon-dark-gray-300 icon-light-gray-800)'"
|
||||
class="flex-shrink-0 h-24px m-12px w-24px
|
||||
children:transition children:duration-300"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
:disabled="isDisabled"
|
||||
class="rounded-none border-gray-100 border-r-1px mr-12px"
|
||||
variant="text"
|
||||
:aria-label="t('runner.selectorPlayground.toggle')"
|
||||
@click="togglePlayground"
|
||||
>
|
||||
<i-cy-crosshairs_x16 class="icon-dark-gray-600" />
|
||||
@@ -35,6 +36,7 @@
|
||||
:disabled="isDisabled"
|
||||
class="border-gray-100 mr-12px"
|
||||
variant="outline"
|
||||
:aria-label="t('runner.selectorPlayground.toggle')"
|
||||
@click="togglePlayground"
|
||||
>
|
||||
<i-cy-crosshairs_x16 class="icon-dark-gray-600" />
|
||||
@@ -49,6 +51,7 @@
|
||||
<img
|
||||
class="min-w-16px w-16px"
|
||||
:src="allBrowsersIcons[selectedBrowser.displayName]"
|
||||
:alt="selectedBrowser.displayName"
|
||||
>
|
||||
{{ selectedBrowser.displayName }} {{ selectedBrowser.majorVersion }}
|
||||
</template>
|
||||
|
||||
@@ -25,7 +25,8 @@ export class AutIframe {
|
||||
|
||||
create (): JQuery<HTMLIFrameElement> {
|
||||
const $iframe = this.$('<iframe>', {
|
||||
id: `Your App: '${this.projectName}'`,
|
||||
id: `Your project: '${this.projectName}'`,
|
||||
title: `Your project: '${this.projectName}'`,
|
||||
class: 'aut-iframe',
|
||||
})
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
"*.d.ts",
|
||||
"../frontend-shared/src/**/*.vue",
|
||||
"../frontend-shared/src/**/*.tsx",
|
||||
"../frontend-shared/cypress/**/*.ts",
|
||||
"*.d.ts"
|
||||
"../frontend-shared/cypress/**/*.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"noImplicitThis": true,
|
||||
|
||||
@@ -131,13 +131,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[2].get()
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
@@ -145,29 +139,29 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.contain({
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get()).to.contain({
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
|
||||
it('creates new session instrument with session details', () => {
|
||||
const sessionInfo = logs[1].get('sessionInfo')
|
||||
const sessionInfo = logs[0].get('sessionInfo')
|
||||
|
||||
expect(sessionInfo).to.deep.eq({
|
||||
id: 'session-1',
|
||||
@@ -176,10 +170,11 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
})
|
||||
|
||||
it('has session details in the consoleProps', () => {
|
||||
const consoleProps = logs[1].get('consoleProps')()
|
||||
const consoleProps = logs[0].get('consoleProps')()
|
||||
|
||||
expect(consoleProps).to.deep.eq({
|
||||
Command: 'session',
|
||||
Snapshot: 'The snapshot is missing. Displaying current state of the DOM.',
|
||||
id: 'session-1',
|
||||
table: [],
|
||||
})
|
||||
@@ -213,13 +208,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[2].get()
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
@@ -227,34 +216,34 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.contain({
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[6].get()
|
||||
const validateSessionGroup = logs[5].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[7].get()).to.deep.contain({
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.contain({
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
@@ -282,13 +271,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[2].get()
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
@@ -296,22 +279,22 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.contain({
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[6].get()
|
||||
const validateSessionGroup = logs[5].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
@@ -359,13 +342,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(saved) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const restoreSavedSessionGroup = logs[2].get()
|
||||
const restoreSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
@@ -373,12 +350,12 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: restoreSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.contain({
|
||||
expect(logs[3].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
@@ -417,13 +394,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(saved) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const restoreSavedSessionGroup = logs[2].get()
|
||||
const restoreSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
@@ -431,24 +402,24 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: restoreSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get()).to.contain({
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
@@ -492,13 +463,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(recreated) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const recreatedSavedSessionGroup = logs[2].get()
|
||||
const recreatedSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(recreatedSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
@@ -506,31 +471,31 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: recreatedSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
showError: true,
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
expect(logs[5].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
|
||||
const createNewSessionGroup = logs[7].get()
|
||||
const createNewSessionGroup = logs[6].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
@@ -538,34 +503,34 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.contain({
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[9].get()).to.deep.contain({
|
||||
expect(logs[8].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[10].get()).to.contain({
|
||||
expect(logs[9].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const secondValidateSessionGroup = logs[11].get()
|
||||
const secondValidateSessionGroup = logs[10].get()
|
||||
|
||||
expect(secondValidateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[12].get()).to.deep.contain({
|
||||
expect(logs[11].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: secondValidateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[13].get()).to.contain({
|
||||
expect(logs[12].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
@@ -599,13 +564,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
message: '(recreated) session-1',
|
||||
})
|
||||
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'session',
|
||||
message: 'session-1',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const recreatedSavedSessionGroup = logs[2].get()
|
||||
const recreatedSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(recreatedSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
@@ -613,31 +572,31 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: recreatedSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
showError: true,
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[6].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
expect(logs[5].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
|
||||
const createNewSessionGroup = logs[7].get()
|
||||
const createNewSessionGroup = logs[6].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
@@ -645,29 +604,29 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.contain({
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[9].get()).to.deep.contain({
|
||||
expect(logs[8].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[10].get()).to.contain({
|
||||
expect(logs[9].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const secondValidateSessionGroup = logs[11].get()
|
||||
const secondValidateSessionGroup = logs[10].get()
|
||||
|
||||
expect(secondValidateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[12].get()).to.deep.contain({
|
||||
expect(logs[11].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: secondValidateSessionGroup.id,
|
||||
})
|
||||
|
||||
@@ -121,13 +121,8 @@ export default function (Commands, Cypress, cy) {
|
||||
name: 'session',
|
||||
message: `${existingSession.id.length > 50 ? `${existingSession.id.substr(0, 47)}...` : existingSession.id}`,
|
||||
groupStart: true,
|
||||
snapshot: false,
|
||||
})
|
||||
|
||||
const dataLog = Cypress.log({
|
||||
name: 'session',
|
||||
sessionInfo: getSessionDetails(existingSession),
|
||||
message: `${existingSession.id.length > 50 ? `${existingSession.id.substr(0, 47)}...` : existingSession.id}`,
|
||||
snapshot: false,
|
||||
})
|
||||
|
||||
function createSession (existingSession, recreateSession = false) {
|
||||
@@ -172,9 +167,7 @@ export default function (Commands, Cypress, cy) {
|
||||
|
||||
sessionsManager.setActiveSession({ [existingSession.id]: existingSession })
|
||||
|
||||
dataLog.set({
|
||||
consoleProps: () => getConsoleProps(existingSession),
|
||||
})
|
||||
_log.set({ consoleProps: () => getConsoleProps(existingSession) })
|
||||
|
||||
// persist the session to the server. Only matters in openMode OR if there's a top navigation on a future test.
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -197,6 +190,7 @@ export default function (Commands, Cypress, cy) {
|
||||
await navigateAboutBlank()
|
||||
|
||||
_log.set({
|
||||
consoleProps: () => getConsoleProps(existingSession),
|
||||
renderProps: () => {
|
||||
return {
|
||||
indicator: 'pending',
|
||||
@@ -205,10 +199,6 @@ export default function (Commands, Cypress, cy) {
|
||||
},
|
||||
})
|
||||
|
||||
dataLog.set({
|
||||
consoleProps: () => getConsoleProps(existingSession),
|
||||
})
|
||||
|
||||
await sessions.setSessionData(existingSession)
|
||||
Cypress.log({ groupEnd: true, emitOnly: true })
|
||||
})
|
||||
|
||||
@@ -14,6 +14,8 @@ import type { E2ETaskMap } from '../e2ePluginSetup'
|
||||
import type { SinonStub } from 'sinon'
|
||||
import type sinon from 'sinon'
|
||||
import type pDefer from 'p-defer'
|
||||
import 'cypress-plugin-tab'
|
||||
import 'cypress-axe'
|
||||
import type { Response } from 'cross-fetch'
|
||||
|
||||
configure({ testIdAttribute: 'data-cy' })
|
||||
@@ -497,7 +499,6 @@ function validateExternalLink (subject, options: ValidateExternalLinkOptions | s
|
||||
|
||||
function tabUntil (fn: (el: JQuery<HTMLElement>) => boolean, limit: number = 10) {
|
||||
function _tabUntil (step: number) {
|
||||
// @ts-expect-error
|
||||
return cy.tab().focused({ log: false }).then((el) => {
|
||||
const pass = fn(el)
|
||||
|
||||
|
||||
@@ -38,8 +38,11 @@
|
||||
"@vue/compiler-sfc": "3.2.31",
|
||||
"@vueuse/core": "7.2.2",
|
||||
"@windicss/plugin-interaction-variants": "1.0.0",
|
||||
"axe-core": "4.4.1",
|
||||
"combine-properties": "0.1.0",
|
||||
"cross-env": "6.0.3",
|
||||
"cypress-axe": "0.14.0",
|
||||
"cypress-plugin-tab": "1.0.5",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"dayjs": "^1.9.3",
|
||||
"fake-uuid": "^1.0.0",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
<img
|
||||
class="w-16px filter group-hocus:grayscale-0"
|
||||
data-cy="top-nav-active-browser-icon"
|
||||
:alt="props.gql?.currentProject?.activeBrowser?.displayName"
|
||||
:class="open ? 'grayscale-0' : 'grayscale'"
|
||||
:src="allBrowsersIcons[props.gql?.currentProject?.activeBrowser?.displayName] || allBrowsersIcons.generic"
|
||||
>
|
||||
|
||||
@@ -134,12 +134,19 @@
|
||||
"defaultMessage": "No results matched your search:",
|
||||
"clearSearch": "Clear Search"
|
||||
},
|
||||
"sideBar": {
|
||||
"sidebar": {
|
||||
"keyboardShortcuts": {
|
||||
"title": "Keyboard Shortcuts",
|
||||
"rerun": "Re-run tests",
|
||||
"stop": "Stop tests",
|
||||
"toggle": "Toggle specs list"
|
||||
},
|
||||
"toggleLabel": {
|
||||
"expanded": "Collapse sidebar",
|
||||
"collapsed": "Expand sidebar"
|
||||
},
|
||||
"nav": {
|
||||
"ariaLabel": "Pages"
|
||||
}
|
||||
},
|
||||
"topNav": {
|
||||
@@ -662,7 +669,8 @@
|
||||
"printTooltip": "Print to console",
|
||||
"printTooltipAction": "Printed!",
|
||||
"invalidSelector": "Invalid",
|
||||
"selectorMethodsLabel": "Selector Methods"
|
||||
"selectorMethodsLabel": "Selector Methods",
|
||||
"toggle": "Toggle playground"
|
||||
},
|
||||
"automation": {
|
||||
"disconnected": {
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
"@intlify/vite-plugin-vue-i18n/client",
|
||||
"@testing-library/cypress",
|
||||
"cypress-real-events",
|
||||
"cypress"
|
||||
"cypress",
|
||||
"cypress-axe"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
"classnames": "2.3.1",
|
||||
"concurrently": "^6.2.0",
|
||||
"cross-env": "6.0.3",
|
||||
"cypress-plugin-tab": "1.0.5",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"dedent": "^0.7.0",
|
||||
"disparity": "^3.0.0",
|
||||
|
||||
@@ -29,3 +29,9 @@ yarn workspace @packages/proxy test
|
||||
```
|
||||
|
||||
Additionally, the `server` package contains tests that use the `proxy`.
|
||||
|
||||
## Debug Logs
|
||||
|
||||
High level logs are available in the `DEBUG=cypress:proxy:*` namespace.
|
||||
|
||||
Detailed per-request logs are available in `DEBUG=cypress-verbose:proxy:http`.
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import debugModule from 'debug'
|
||||
import * as errors from '@packages/server/lib/errors'
|
||||
|
||||
import type { HttpMiddleware } from '.'
|
||||
import type { Readable } from 'stream'
|
||||
import { InterceptError } from '@packages/net-stubbing'
|
||||
import type { Request } from '@cypress/request'
|
||||
const debug = debugModule('cypress:proxy:http:error-middleware')
|
||||
|
||||
// do not use a debug namespace in this file - use the per-request `this.debug` instead
|
||||
// available as cypress-verbose:proxy:http
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const debug = null
|
||||
|
||||
export type ErrorMiddleware = HttpMiddleware<{
|
||||
error: Error
|
||||
@@ -14,7 +17,7 @@ export type ErrorMiddleware = HttpMiddleware<{
|
||||
}>
|
||||
|
||||
const LogError: ErrorMiddleware = function () {
|
||||
debug('error proxying request %o', {
|
||||
this.debug('error proxying request %o', {
|
||||
error: this.error,
|
||||
url: this.req.url,
|
||||
headers: this.req.headers,
|
||||
@@ -36,7 +39,7 @@ const SendToDriver: ErrorMiddleware = function () {
|
||||
|
||||
export const AbortRequest: ErrorMiddleware = function () {
|
||||
if (this.outgoingReq) {
|
||||
debug('aborting outgoingReq')
|
||||
this.debug('aborting outgoingReq')
|
||||
this.outgoingReq.abort()
|
||||
}
|
||||
|
||||
@@ -45,7 +48,7 @@ export const AbortRequest: ErrorMiddleware = function () {
|
||||
|
||||
export const UnpipeResponse: ErrorMiddleware = function () {
|
||||
if (this.incomingResStream) {
|
||||
debug('unpiping resStream from response')
|
||||
this.debug('unpiping resStream from response')
|
||||
this.incomingResStream.unpipe()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
BrowserPreRequest,
|
||||
} from '@packages/proxy'
|
||||
import Debug from 'debug'
|
||||
import chalk from 'chalk'
|
||||
import ErrorMiddleware from './error-middleware'
|
||||
import { HttpBuffers } from './util/buffers'
|
||||
import { GetPreRequestCb, PreRequests } from './util/prerequests'
|
||||
@@ -21,6 +22,12 @@ import { DeferredSourceMapCache } from '@packages/rewriter'
|
||||
import type { Browser } from '@packages/server/lib/browsers/types'
|
||||
import type { RemoteStates } from '@packages/server/lib/remote_states'
|
||||
|
||||
function getRandomColorFn () {
|
||||
return chalk.hex(`#${Number(
|
||||
Math.floor(Math.random() * 0xFFFFFF),
|
||||
).toString(16).padStart(6, 'F').toUpperCase()}`)
|
||||
}
|
||||
|
||||
export const debugVerbose = Debug('cypress-verbose:proxy:http')
|
||||
|
||||
export enum HttpStages {
|
||||
@@ -231,7 +238,12 @@ export class Http {
|
||||
}
|
||||
}
|
||||
|
||||
handle (req: Request, res: Response) {
|
||||
handle (req: CypressIncomingRequest, res: CypressOutgoingResponse) {
|
||||
const colorFn = debugVerbose.enabled ? getRandomColorFn() : undefined
|
||||
const debugUrl = debugVerbose.enabled ?
|
||||
(req.proxiedUrl.length > 80 ? `${req.proxiedUrl.slice(0, 80)}...` : req.proxiedUrl)
|
||||
: undefined
|
||||
|
||||
const ctx: HttpMiddlewareCtx<any> = {
|
||||
req,
|
||||
res,
|
||||
@@ -247,7 +259,9 @@ export class Http {
|
||||
socket: this.socket,
|
||||
serverBus: this.serverBus,
|
||||
debug: (formatter, ...args) => {
|
||||
debugVerbose(`%s %s %s ${formatter}`, ctx.req.method, ctx.req.proxiedUrl, ctx.stage, ...args)
|
||||
if (!debugVerbose.enabled) return
|
||||
|
||||
debugVerbose(`${colorFn!(`%s %s`)} %s ${formatter}`, req.method, debugUrl, chalk.grey(ctx.stage), ...args)
|
||||
},
|
||||
deferSourceMapRewrite: (opts) => {
|
||||
this.deferredSourceMapCache.defer({
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import _ from 'lodash'
|
||||
import { blocked, cors } from '@packages/network'
|
||||
import { InterceptRequest } from '@packages/net-stubbing'
|
||||
import debugModule from 'debug'
|
||||
import type { HttpMiddleware } from './'
|
||||
|
||||
// do not use a debug namespace in this file - use the per-request `this.debug` instead
|
||||
// available as cypress-verbose:proxy:http
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const debug = null
|
||||
|
||||
export type RequestMiddleware = HttpMiddleware<{
|
||||
outgoingReq: any
|
||||
}>
|
||||
|
||||
const debug = debugModule('cypress:proxy:http:request-middleware')
|
||||
|
||||
const LogRequest: RequestMiddleware = function () {
|
||||
debug('proxying request %o', {
|
||||
this.debug('proxying request %o', {
|
||||
req: _.pick(this.req, 'method', 'proxiedUrl', 'headers'),
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import _ from 'lodash'
|
||||
import charset from 'charset'
|
||||
import type Debug from 'debug'
|
||||
import type { CookieOptions } from 'express'
|
||||
import { cors, concatStream, httpUtils, uri } from '@packages/network'
|
||||
import type { CypressIncomingRequest, CypressOutgoingResponse } from '@packages/proxy'
|
||||
import debugModule from 'debug'
|
||||
import type { HttpMiddleware, HttpMiddlewareThis } from '.'
|
||||
import iconv from 'iconv-lite'
|
||||
import type { IncomingMessage, IncomingHttpHeaders } from 'http'
|
||||
@@ -29,7 +29,10 @@ interface ResponseMiddlewareProps {
|
||||
|
||||
export type ResponseMiddleware = HttpMiddleware<ResponseMiddlewareProps>
|
||||
|
||||
const debug = debugModule('cypress:proxy:http:response-middleware')
|
||||
// do not use a debug namespace in this file - use the per-request `this.debug` instead
|
||||
// available as cypress-verbose:proxy:http
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const debug = null
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/1756
|
||||
const zlibOptions = {
|
||||
@@ -38,7 +41,7 @@ const zlibOptions = {
|
||||
}
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/1543
|
||||
function getNodeCharsetFromResponse (headers: IncomingHttpHeaders, body: Buffer) {
|
||||
function getNodeCharsetFromResponse (headers: IncomingHttpHeaders, body: Buffer, debug: Debug.Debugger) {
|
||||
const httpCharset = (charset(headers, body, 1024) || '').toLowerCase()
|
||||
|
||||
debug('inferred charset from response %o', { httpCharset })
|
||||
@@ -133,7 +136,7 @@ const stringifyFeaturePolicy = (policy: any): string => {
|
||||
}
|
||||
|
||||
const LogResponse: ResponseMiddleware = function () {
|
||||
debug('received response %o', {
|
||||
this.debug('received response %o', {
|
||||
req: _.pick(this.req, 'method', 'proxiedUrl', 'headers'),
|
||||
incomingRes: _.pick(this.incomingRes, 'headers', 'statusCode'),
|
||||
})
|
||||
@@ -143,10 +146,10 @@ const LogResponse: ResponseMiddleware = function () {
|
||||
|
||||
const AttachPlainTextStreamFn: ResponseMiddleware = function () {
|
||||
this.makeResStreamPlainText = function () {
|
||||
debug('ensuring resStream is plaintext')
|
||||
this.debug('ensuring resStream is plaintext')
|
||||
|
||||
if (!this.isGunzipped && resIsGzipped(this.incomingRes)) {
|
||||
debug('gunzipping response body')
|
||||
this.debug('gunzipping response body')
|
||||
|
||||
const gunzip = zlib.createGunzip(zlibOptions)
|
||||
|
||||
@@ -193,6 +196,8 @@ const PatchExpressSetHeader: ResponseMiddleware = function () {
|
||||
|
||||
let kOutHeaders
|
||||
|
||||
const ctxDebug = this.debug
|
||||
|
||||
this.res.setHeader = function (name, value) {
|
||||
// express.Response.setHeader does all kinds of silly/nasty stuff to the content-type...
|
||||
// but we don't want to change it at all!
|
||||
@@ -209,7 +214,7 @@ const PatchExpressSetHeader: ResponseMiddleware = function () {
|
||||
throw err
|
||||
}
|
||||
|
||||
debug('setHeader error ignored %o', { name, value, code: err.code, err })
|
||||
ctxDebug('setHeader error ignored %o', { name, value, code: err.code, err })
|
||||
|
||||
if (!kOutHeaders) {
|
||||
kOutHeaders = getKOutHeadersSymbol()
|
||||
@@ -334,7 +339,7 @@ const SetInjectionLevel: ResponseMiddleware = function () {
|
||||
|| resContentTypeIsJavaScript(this.incomingRes)
|
||||
)
|
||||
|
||||
debug('injection levels: %o', _.pick(this.res, 'isInitial', 'wantsInjection', 'wantsSecurityRemoved'))
|
||||
this.debug('injection levels: %o', _.pick(this.res, 'isInitial', 'wantsInjection', 'wantsSecurityRemoved'))
|
||||
|
||||
this.next()
|
||||
}
|
||||
@@ -410,20 +415,21 @@ interface EnsureSameSiteNoneProps {
|
||||
browser: Browser | { family: string | null }
|
||||
isLocalhost: boolean
|
||||
url: URL
|
||||
ctxDebug: Debug.Debugger
|
||||
}
|
||||
|
||||
const cookieSameSiteRegex = /SameSite=(\w+)/i
|
||||
const cookieSecureRegex = /(^|\W)Secure(\W|$)/i
|
||||
const cookieSecureSemicolonRegex = /;\s*Secure/i
|
||||
|
||||
const ensureSameSiteNone = ({ cookie, browser, isLocalhost, url }: EnsureSameSiteNoneProps) => {
|
||||
debug('original cookie: %s', cookie)
|
||||
const ensureSameSiteNone = ({ cookie, browser, isLocalhost, url, ctxDebug }: EnsureSameSiteNoneProps) => {
|
||||
ctxDebug('original cookie: %s', cookie)
|
||||
|
||||
if (cookieSameSiteRegex.test(cookie)) {
|
||||
debug('change cookie to SameSite=None')
|
||||
ctxDebug('change cookie to SameSite=None')
|
||||
cookie = cookie.replace(cookieSameSiteRegex, 'SameSite=None')
|
||||
} else {
|
||||
debug('add SameSite=None to cookie')
|
||||
ctxDebug('add SameSite=None to cookie')
|
||||
cookie += '; SameSite=None'
|
||||
}
|
||||
|
||||
@@ -439,15 +445,15 @@ const ensureSameSiteNone = ({ cookie, browser, isLocalhost, url }: EnsureSameSit
|
||||
// remove Secure from http://localhost cookies in Firefox.
|
||||
if (cookieSecureRegex.test(cookie)) {
|
||||
if (isFirefox && isLocalhost && url.protocol === 'http:') {
|
||||
debug('remove Secure from cookie')
|
||||
ctxDebug('remove Secure from cookie')
|
||||
cookie = cookie.replace(cookieSecureSemicolonRegex, '')
|
||||
}
|
||||
} else if (!isFirefox || url.protocol === 'https:') {
|
||||
debug('add Secure to cookie')
|
||||
ctxDebug('add Secure to cookie')
|
||||
cookie += '; Secure'
|
||||
}
|
||||
|
||||
debug('resulting cookie: %s', cookie)
|
||||
ctxDebug('resulting cookie: %s', cookie)
|
||||
|
||||
return cookie
|
||||
}
|
||||
@@ -464,17 +470,17 @@ const CopyCookiesFromIncomingRes: ResponseMiddleware = function () {
|
||||
const url = new URL(this.req.proxiedUrl)
|
||||
const isLocalhost = uri.isLocalhost(url)
|
||||
|
||||
debug('force SameSite=None?', needsCrossOriginHandling)
|
||||
this.debug('force SameSite=None?', needsCrossOriginHandling)
|
||||
|
||||
;([] as string[]).concat(cookies).forEach((cookie) => {
|
||||
if (needsCrossOriginHandling) {
|
||||
cookie = ensureSameSiteNone({ cookie, browser, isLocalhost, url })
|
||||
cookie = ensureSameSiteNone({ cookie, browser, isLocalhost, url, ctxDebug: this.debug })
|
||||
}
|
||||
|
||||
try {
|
||||
this.res.append('Set-Cookie', cookie)
|
||||
} catch (err) {
|
||||
debug('failed to Set-Cookie, continuing %o', { err, cookie })
|
||||
this.debug('failed to Set-Cookie, continuing %o', { err, cookie })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -495,7 +501,7 @@ const MaybeSendRedirectToClient: ResponseMiddleware = function () {
|
||||
|
||||
setInitialCookie(this.res, this.remoteStates.current(), true)
|
||||
|
||||
debug('redirecting to new url %o', { statusCode, newUrl })
|
||||
this.debug('redirecting to new url %o', { statusCode, newUrl })
|
||||
this.res.redirect(Number(statusCode), newUrl)
|
||||
|
||||
return this.end()
|
||||
@@ -528,12 +534,13 @@ const MaybeInjectHtml: ResponseMiddleware = function () {
|
||||
|
||||
this.skipMiddleware('MaybeRemoveSecurity') // we only want to do one or the other
|
||||
|
||||
debug('injecting into HTML')
|
||||
this.debug('injecting into HTML')
|
||||
|
||||
this.makeResStreamPlainText()
|
||||
|
||||
this.incomingResStream.pipe(concatStream(async (body) => {
|
||||
const nodeCharset = getNodeCharsetFromResponse(this.incomingRes.headers, body)
|
||||
const nodeCharset = getNodeCharsetFromResponse(this.incomingRes.headers, body, this.debug)
|
||||
|
||||
const decodedBody = iconv.decode(body, nodeCharset)
|
||||
const injectedBody = await rewriter.html(decodedBody, {
|
||||
domainName: cors.getDomainNameFromUrl(this.req.proxiedUrl),
|
||||
@@ -561,7 +568,7 @@ const MaybeRemoveSecurity: ResponseMiddleware = function () {
|
||||
return this.next()
|
||||
}
|
||||
|
||||
debug('removing JS framebusting code')
|
||||
this.debug('removing JS framebusting code')
|
||||
|
||||
this.makeResStreamPlainText()
|
||||
|
||||
@@ -578,7 +585,7 @@ const MaybeRemoveSecurity: ResponseMiddleware = function () {
|
||||
|
||||
const GzipBody: ResponseMiddleware = function () {
|
||||
if (this.isGunzipped) {
|
||||
debug('regzipping response body')
|
||||
this.debug('regzipping response body')
|
||||
this.incomingResStream = this.incomingResStream.pipe(zlib.createGzip(zlibOptions)).on('error', this.onError)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": "3.5.3",
|
||||
"chalk": "2.4.2",
|
||||
"charset": "1.0.1",
|
||||
"common-tags": "1.8.0",
|
||||
"debug": "^4.3.2",
|
||||
|
||||
@@ -44,6 +44,7 @@ describe('http', function () {
|
||||
})
|
||||
|
||||
return new Http(httpOpts)
|
||||
// @ts-ignore
|
||||
.handle({}, {})
|
||||
.then(function () {
|
||||
expect(incomingRequest, 'incomingRequest').to.be.calledOnce
|
||||
@@ -61,6 +62,7 @@ describe('http', function () {
|
||||
})
|
||||
|
||||
return new Http(httpOpts)
|
||||
// @ts-ignore
|
||||
.handle({}, {})
|
||||
.then(function () {
|
||||
expect(incomingRequest).to.be.calledOnce
|
||||
@@ -83,6 +85,7 @@ describe('http', function () {
|
||||
})
|
||||
|
||||
return new Http(httpOpts)
|
||||
// @ts-ignore
|
||||
.handle({}, {})
|
||||
.then(function () {
|
||||
expect(incomingRequest).to.be.calledOnce
|
||||
@@ -145,6 +148,7 @@ describe('http', function () {
|
||||
middleware[HttpStages.Error].push(error2)
|
||||
|
||||
return new Http(httpOpts)
|
||||
// @ts-ignore
|
||||
.handle({}, {})
|
||||
.then(function () {
|
||||
[
|
||||
|
||||
@@ -400,7 +400,7 @@ const _isAUTFrame = async (frameId: string) => {
|
||||
}
|
||||
|
||||
const frame = _.find(frameTree?.childFrames || [], ({ frame }) => {
|
||||
return frame?.name?.startsWith('Your App:')
|
||||
return frame?.name?.startsWith('Your project:')
|
||||
}) as HasFrame | undefined
|
||||
|
||||
if (frame) {
|
||||
|
||||
@@ -381,7 +381,7 @@ describe('lib/browsers/chrome', () => {
|
||||
{
|
||||
frame: {
|
||||
id: 'aut-frame-id',
|
||||
name: 'Your App: "FakeBlock"',
|
||||
name: 'Your project: "FakeBlock"',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -10291,6 +10291,11 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
axe-core@4.4.1:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413"
|
||||
integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==
|
||||
|
||||
axios@0.21.2:
|
||||
version "0.21.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.2.tgz#21297d5084b2aeeb422f5d38e7be4fbb82239017"
|
||||
@@ -14915,6 +14920,11 @@ cyclist@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||
|
||||
cypress-axe@0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-0.14.0.tgz#5f5e70fb36b8cb3ba73a8ba01e9262ff1268d5e2"
|
||||
integrity sha512-7Rdjnko0MjggCmndc1wECAkvQBIhuy+DRtjF7bd5YPZRFvubfMNvrxfqD8PWQmxm7MZE0ffS4Xr43V6ZmvLopg==
|
||||
|
||||
"cypress-example-kitchensink@https://github.com/cypress-io/cypress-example-kitchensink.git#b709bad8f1e29eb018e32383014cfd6f9a192691":
|
||||
version "0.0.0-development"
|
||||
resolved "https://github.com/cypress-io/cypress-example-kitchensink.git#b709bad8f1e29eb018e32383014cfd6f9a192691"
|
||||
|
||||
Reference in New Issue
Block a user