Skip to content

Commit

Permalink
Merge branch 'develop' into issue-21856
Browse files Browse the repository at this point in the history
  • Loading branch information
rachelruderman authored Jul 13, 2022
2 parents ac75f5c + 5bd848c commit cb1b2c8
Show file tree
Hide file tree
Showing 37 changed files with 454 additions and 263 deletions.
15 changes: 10 additions & 5 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,31 @@
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js"
"require": "./index.js",
"types": "./types/index.d.ts"
},
"./vue": {
"import": "./vue/dist/cypress-vue.esm-bundler.js",
"require": "./vue/dist/cypress-vue.cjs.js"
"require": "./vue/dist/cypress-vue.cjs.js",
"types": "./vue/dist/index.d.ts"
},
"./vue2": {
"import": "./vue2/dist/cypress-vue2.esm-bundler.js",
"require": "./vue2/dist/cypress-vue2.cjs.js"
"require": "./vue2/dist/cypress-vue2.cjs.js",
"types": "./vue2/dist/index.d.ts"
},
"./package.json": {
"import": "./package.json",
"require": "./package.json"
},
"./react": {
"import": "./react/dist/cypress-react.esm-bundler.js",
"require": "./react/dist/cypress-react.cjs.js"
"require": "./react/dist/cypress-react.cjs.js",
"types": "./react/dist/index.d.ts"
},
"./mount-utils": {
"require": "./mount-utils/dist/index.js"
"require": "./mount-utils/dist/index.js",
"types": "./mount-utils/dist/index.d.ts"
}
},
"workspaces": {
Expand Down
10 changes: 9 additions & 1 deletion npm/mount-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const getContainerEl = (): HTMLElement => {
return el
}

throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please use the mount utils to mount it properly`)
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`)
}

/**
Expand Down Expand Up @@ -200,6 +200,14 @@ export const injectStylesBeforeElement = (
}

export function setupHooks (optionalCallback?: Function) {
// Consumed by the framework "mount" libs. A user might register their own mount in the scaffolded 'commands.js'
// file that is imported by e2e and component support files by default. We don't want CT side effects to run when e2e
// testing so we early return.
// System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
if (Cypress.testingType !== 'component') {
return
}

// When running component specs, we cannot allow "cy.visit"
// because it will wipe out our preparation work, and does not make much sense
// thus we overwrite "cy.visit" to throw an error
Expand Down
9 changes: 9 additions & 0 deletions npm/react/src/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,15 @@ export declare namespace Cypress {
}
}

// Side effects from "import { mount } from '@cypress/<my-framework>'" are annoying, we should avoid doing this
// by creating an explicit function/import that the user can register in their 'component.js' support file,
// such as:
// import 'cypress/<my-framework>/support'
// or
// import { registerCT } from 'cypress/<my-framework>'
// registerCT()
// Note: This would be a breaking change

// it is required to unmount component in beforeEach hook in order to provide a clean state inside test
// because `mount` can be called after some preparation that can side effect unmount
// @see npm/react/cypress/component/advanced/set-timeout-example/loading-indicator-spec.js
Expand Down
8 changes: 8 additions & 0 deletions npm/vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,4 +306,12 @@ export function mountCallback (
}
}

// Side effects from "import { mount } from '@cypress/<my-framework>'" are annoying, we should avoid doing this
// by creating an explicit function/import that the user can register in their 'component.js' support file,
// such as:
// import 'cypress/<my-framework>/support'
// or
// import { registerCT } from 'cypress/<my-framework>'
// registerCT()
// Note: This would be a breaking change
setupHooks()
8 changes: 8 additions & 0 deletions npm/vue2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,12 @@ export const mountCallback = (
return () => mount(component, options)
}

// Side effects from "import { mount } from '@cypress/<my-framework>'" are annoying, we should avoid doing this
// by creating an explicit function/import that the user can register in their 'component.js' support file,
// such as:
// import 'cypress/<my-framework>/support'
// or
// import { registerCT } from 'cypress/<my-framework>'
// registerCT()
// Note: This would be a breaking change
setupHooks()
3 changes: 0 additions & 3 deletions packages/app/cypress/component/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ import { setActivePinia } from 'pinia'
import type { Pinia } from 'pinia'
import 'cypress-real-events/support'
import { installCustomPercyCommand } from '@packages/ui-components/cypress/support/customPercyCommand'
import { configure } from '@testing-library/cypress'

configure({ testIdAttribute: 'data-cy' })

let pinia: Pinia

Expand Down
8 changes: 2 additions & 6 deletions packages/app/src/runner/ResizablePanels.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
class="flex"
:class="{
'select-none': panel1IsDragging || panel2IsDragging,
'overflow-x-hidden': isFirefox
}"
@mouseup="handleMouseup"
@mousemove="handleMousemove"
Expand All @@ -22,7 +21,7 @@

<div
data-cy="panel1ResizeHandle"
class="cursor-ew-resize h-full top-0 -right-6px w-16px z-30 absolute"
class="cursor-ew-resize h-full top-0 -right-6px w-10px z-30 absolute"
@mousedown="handleMousedown('panel1', $event)"
/>
</div>
Expand All @@ -37,7 +36,7 @@

<div
data-cy="panel2ResizeHandle"
class="cursor-ew-resize h-full top-0 -right-6px w-16px z-30 absolute"
class="cursor-ew-resize h-full top-0 -right-6px w-10px z-30 absolute"
@mousedown="handleMousedown('panel2', $event)"
/>
</div>
Expand Down Expand Up @@ -208,7 +207,4 @@ watchEffect(() => {
}
})
// TODO: UNIFY-1704 - avoid special case for FF
const isFirefox = window.__CYPRESS_BROWSER__?.family === 'firefox'
</script>
5 changes: 5 additions & 0 deletions packages/app/src/runner/useRunnerStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,15 @@ export const useRunnerStyle = () => {
})

const viewportStyle = computed(() => {
// in the below styles, `position: absolute` is required to avoid certain edge cases
// that can happen with overflow (mainly, in Firefox, but not always)
// see this issue for details: https://github.com/cypress-io/cypress/issues/21881

let style = `
width: ${autStore.viewportDimensions.width}px;
height: ${autStore.viewportDimensions.height}px;
transform: scale(${scale.value});
position: absolute;
`

// to keep the AUT iframe centered during scaling, we need to calculate the difference between
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/specs/SpecListGitInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class="h-full truncate"
data-cy="tooltip"
>
<button class="flex h-full gap-9px justify-start items-center">
<button class="flex h-full w-full gap-9px justify-start items-center">
<div>
<component
:is="classes.icon"
Expand Down
21 changes: 20 additions & 1 deletion packages/app/src/specs/SpecsList.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe('<SpecsList />', { keystrokeDelay: 0 }, () => {
cy.get('@showCreateSpecModalSpy').should('have.been.calledOnce')
})

describe('column headers', () => {
describe('responsive behavior', () => {
// Spec name (first) column is handled by type-specific tests below

it('should display last updated column', () => {
Expand Down Expand Up @@ -164,6 +164,25 @@ describe('<SpecsList />', { keystrokeDelay: 0 }, () => {
})
})
})

it('displays the list as expected visually at various widths', () => {
cy.get('[data-cy="spec-list-file"]')
.should('have.length.above', 2)
.should('have.length.below', specs.length)

cy.wait(100) // there's an intentional 50ms delay in the code, lets just wait it out

cy.viewport(500, 850)
cy.percySnapshot('narrowest')
cy.viewport(650, 850)
cy.percySnapshot('narrow')
cy.viewport(800, 850)
cy.percySnapshot('medium')
cy.viewport(1200, 850)
cy.percySnapshot('wide')
cy.viewport(2000, 850)
cy.percySnapshot('widest')
})
})
})

Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/specs/SpecsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
>
<div
v-bind="wrapperProps"
class="divide-y-1 children:h-40px"
class="divide-y-1 border-gray-50 border-y-1 children:border-gray-50 children:h-40px"
>
<SpecsListRowItem
v-for="row in list"
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/specs/SpecsListRowItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div data-cy="specs-list-row">
<component
:is="isLeaf ? 'RouterLink' : 'div'"
class="h-full outline-none border-gray-50 ring-inset grid pr-20px grid-cols-7 group md:grid-cols-9 focus:outline-transparent focus-within:ring-indigo-300 focus-within:ring-1 children:cursor-pointer"
class="h-full outline-none ring-inset grid pr-20px grid-cols-7 group md:grid-cols-9 focus:outline-transparent focus-within:ring-indigo-300 focus-within:ring-1 children:cursor-pointer"
:to="route"
:data-cy="isLeaf ? 'spec-item-link' : 'spec-item-directory'"
@click="emit('toggleRow')"
Expand Down
2 changes: 1 addition & 1 deletion packages/data-context/src/DataContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class DataContext {
}

get isGlobalMode () {
return this.appData.isInGlobalMode
return this.appData.isGlobalMode
}

get modeOptions () {
Expand Down
4 changes: 2 additions & 2 deletions packages/data-context/src/data/coreDataShape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface ConfigChildProcessShape {
}

export interface AppDataShape {
isInGlobalMode: boolean
isGlobalMode: boolean
browsers: ReadonlyArray<FoundBrowser> | null
projects: ProjectShape[]
nodePath: Maybe<string>
Expand Down Expand Up @@ -182,7 +182,7 @@ export function makeCoreData (modeOptions: Partial<AllModeOptions> = {}): CoreDa
refreshState: null,
},
app: {
isInGlobalMode: Boolean(modeOptions.global),
isGlobalMode: Boolean(modeOptions.global),
browsers: null,
projects: [],
nodePath: modeOptions.userNodePath,
Expand Down
25 changes: 13 additions & 12 deletions packages/data-context/test/unit/actions/MigrationActions.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { expect } from 'chai'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { getConfigWithDefaults, getDiff } from '../../../src/actions/MigrationActions'
import fs from 'fs-extra'
import Fixtures from '@tooling/system-tests'
import { createTestDataContext, scaffoldMigrationProject } from '../helper'
import path from 'path'

chai.use(chaiAsPromised)

describe('MigrationActions', () => {
context('getConfigWithDefaults', () => {
it('returns a config with defaults without touching the original', () => {
Expand Down Expand Up @@ -64,37 +67,35 @@ describe('MigrationActions', () => {
fs.writeJsonSync(path.join(mockCypressDir, 'package.json'), mockPkgJson)
}

it('errors when local cypress version is <10', (done) => {
it('errors when local cypress version is <10', () => {
mockLocallyInstalledCypress(currentProject, '9.5.0')
const ctx = createTestDataContext()

ctx.update((coreData) => {
coreData.currentProject = currentProject
coreData.currentTestingType = 'e2e'
coreData.app.isInGlobalMode = true
coreData.app.isGlobalMode = true
})

ctx.actions.migration.initialize({})
.catch((e) => {
expect((e as Error).message).to.include(
return (
expect(ctx.actions.migration.initialize({})).to.eventually.be.rejectedWith(
'You are running Cypress version 10 in global mode, but you are attempting to migrate a project where Cypress version 9.5.0 is installed',
)

done()
})
)
})

it('does not error when local cypress version is 10', (done) => {
it('does not error when local cypress version is 10', () => {
mockLocallyInstalledCypress(currentProject, '10.0.0')
const ctx = createTestDataContext()

ctx.update((coreData) => {
coreData.currentProject = currentProject
coreData.currentTestingType = 'e2e'
coreData.app.isInGlobalMode = true
})

ctx.actions.migration.initialize({}).then(done)
return (
expect(ctx.actions.migration.initialize({})).to.eventually.not.be.rejected
)
})
})
})
20 changes: 12 additions & 8 deletions packages/driver/src/cy/commands/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
}
}

const before = ($el) => {
const before = ($body, $container) => {
return Promise.try(() => {
if (disableTimersAndAnimations) {
return cy.pauseTimers(true)
Expand All @@ -349,11 +349,11 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
// could fail if iframe is cross-origin, so fail gracefully
try {
if (disableTimersAndAnimations) {
$dom.addCssAnimationDisabler($el)
$dom.addCssAnimationDisabler($body)
}

_.each(getBlackout(screenshotConfig), (selector) => {
$dom.addBlackouts($el, selector)
$dom.addBlackouts($body, $container, selector)
})
} catch (err) {
/* eslint-disable no-console */
Expand All @@ -366,14 +366,14 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
})
}

const after = ($el) => {
const after = ($body) => {
// could fail if iframe is cross-origin, so fail gracefully
try {
if (disableTimersAndAnimations) {
$dom.removeCssAnimationDisabler($el)
$dom.removeCssAnimationDisabler($body)
}

$dom.removeBlackouts($el)
$dom.removeBlackouts($body)
} catch (err) {
/* eslint-disable no-console */
console.error('Failed to modify app dom:')
Expand Down Expand Up @@ -417,7 +417,11 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
? subject
: $dom.wrap(state('document').documentElement)

return before($el)
// get the current body of the AUT to accurately calculate screenshot blackouts
// as well as properly enable/disable CSS animations while screenshotting is happening
const $body = Cypress.$('body')

return before($body, $el)
.then(() => {
if (onBeforeScreenshot) {
onBeforeScreenshot.call(state('ctx'), $el)
Expand All @@ -444,7 +448,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho

return props
})
.finally(() => after($el))
.finally(() => after($body))
}

interface InternalScreenshotOptions extends Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.ScreenshotOptions> {
Expand Down
5 changes: 3 additions & 2 deletions packages/driver/src/dom/blackout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ function addBlackoutForElement ($body, $el) {
$(`<div class="__cypress-blackout" style="${style}">`).appendTo($body)
}

function addBlackouts ($body, selector) {
function addBlackouts ($body, $container, selector) {
let $el

try {
$el = $body.find(selector)
// only scope blacked out elements to to screenshotted element, not necessarily the whole body
$el = $container.find(selector)
if (!$el.length) return
} catch (err) {
// if it's an invalid selector, just ignore it
Expand Down
Loading

0 comments on commit cb1b2c8

Please sign in to comment.