mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-01 04:20:23 -05:00
chore: Adding validateExternalLink command to increase e2e coverage of external links (#19462)
* Adding command to validate presence and action of external links. * Updating link validation in other tests * Condensing this a bit * Don't log the wrapping
This commit is contained in:
@@ -20,7 +20,8 @@ describe('Code Generation', () => {
|
||||
cy.findByTestId('new-spec-button').click()
|
||||
cy.findByTestId('create-spec-modal').should('be.visible').within(() => {
|
||||
cy.contains('Create a new spec').should('be.visible')
|
||||
cy.get('[data-cy="external"]').should('have.attr', 'href', 'https://on.cypress.io')
|
||||
|
||||
cy.validateExternalLink({ name: `${defaultMessages.links.needHelp}?`, href: 'https://on.cypress.io' })
|
||||
})
|
||||
|
||||
cy.contains('Create from component').click()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json'
|
||||
import type { Interception } from '@packages/net-stubbing/lib/external-types'
|
||||
|
||||
describe('Navigation', () => {
|
||||
before(() => {
|
||||
@@ -11,11 +10,11 @@ describe('Navigation', () => {
|
||||
cy.startAppServer()
|
||||
cy.visitApp()
|
||||
|
||||
cy.intercept('mutation-ExternalLink_OpenExternal', { 'data': { 'openExternal': true } }).as('OpenExternal')
|
||||
cy.contains('button', defaultMessages.topNav.docsMenu.docsHeading).click()
|
||||
cy.contains('a', defaultMessages.topNav.docsMenu.firstTest).click()
|
||||
cy.wait('@OpenExternal').then((interception: Interception) => {
|
||||
expect(interception.request.body.variables.url).to.equal('https://on.cypress.io/writing-first-test?utm_medium=Docs+Menu&utm_content=First+Test')
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: defaultMessages.topNav.docsMenu.firstTest,
|
||||
href: 'https://on.cypress.io/writing-first-test?utm_medium=Docs+Menu&utm_content=First+Test',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -124,7 +124,10 @@ describe('App Top Nav Workflows', () => {
|
||||
cy.startAppServer()
|
||||
cy.visitApp()
|
||||
|
||||
cy.findByTestId('top-nav-cypress-version-current-link').should('have.attr', 'href', 'https://github.com/cypress-io/cypress/releases/tag/v10.0.0')
|
||||
cy.findByTestId('app-header-bar').validateExternalLink({
|
||||
name: 'v10.0.0',
|
||||
href: 'https://github.com/cypress-io/cypress/releases/tag/v10.0.0',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -158,20 +161,22 @@ describe('App Top Nav Workflows', () => {
|
||||
it('shows dropdown with version info if user version is outdated', () => {
|
||||
cy.findByTestId('top-nav-version-list').contains('v10.0.0 • Upgrade').click()
|
||||
|
||||
cy.findByTestId('update-hint').findByRole('link', { name: '10.1.0' })
|
||||
.should('have.attr', 'href', 'https://github.com/cypress-io/cypress/releases/tag/v10.1.0')
|
||||
|
||||
cy.findByTestId('update-hint').findByText('Latest')
|
||||
cy.findByTestId('update-hint').within(() => {
|
||||
cy.validateExternalLink({ name: '10.1.0', href: 'https://github.com/cypress-io/cypress/releases/tag/v10.1.0' })
|
||||
cy.findByText('Latest').should('be.visible')
|
||||
})
|
||||
|
||||
cy.findByTestId('cypress-update-popover').findByRole('button', { name: 'Update to 10.1.0' })
|
||||
|
||||
cy.findByTestId('current-hint').findByRole('link', { name: '10.0.0' })
|
||||
.should('have.attr', 'href', 'https://github.com/cypress-io/cypress/releases/tag/v10.0.0')
|
||||
cy.findByTestId('current-hint').within(() => {
|
||||
cy.validateExternalLink({ name: '10.0.0', href: 'https://github.com/cypress-io/cypress/releases/tag/v10.0.0' })
|
||||
cy.findByText('Installed').should('be.visible')
|
||||
})
|
||||
|
||||
cy.findByTestId('current-hint').findByText('Installed')
|
||||
|
||||
cy.findByTestId('cypress-update-popover').findByRole('link', { name: 'See all releases' })
|
||||
.should('have.attr', 'href', 'https://github.com/cypress-io/cypress/releases')
|
||||
cy.findByTestId('cypress-update-popover').validateExternalLink({
|
||||
name: 'See all releases',
|
||||
href: 'https://github.com/cypress-io/cypress/releases',
|
||||
})
|
||||
})
|
||||
|
||||
it('hides dropdown when version in header is clicked', () => {
|
||||
@@ -217,15 +222,40 @@ describe('App Top Nav Workflows', () => {
|
||||
cy.findByRole('heading', { name: 'References', level: 2 })
|
||||
cy.findByRole('heading', { name: 'Run in CI/CD', level: 2 })
|
||||
|
||||
cy.findByRole('link', { name: 'Write your first test' }).should('have.attr', 'href', 'https://on.cypress.io/writing-first-test?utm_medium=Docs+Menu&utm_content=First+Test')
|
||||
cy.findByRole('link', { name: 'Testing your app' }).should('have.attr', 'href', 'https://on.cypress.io/testing-your-app?utm_medium=Docs+Menu&utm_content=Testing+Your+App')
|
||||
cy.findByRole('link', { name: 'Organizing Tests' }).should('have.attr', 'href', 'https://on.cypress.io/writing-and-organizing-tests?utm_medium=Docs+Menu&utm_content=Organizing+Tests')
|
||||
cy.validateExternalLink({
|
||||
name: 'Write your first test',
|
||||
href: 'https://on.cypress.io/writing-first-test?utm_medium=Docs+Menu&utm_content=First+Test',
|
||||
})
|
||||
|
||||
cy.findByRole('link', { name: 'Best Practices' }).should('have.attr', 'href', 'https://on.cypress.io/best-practices?utm_medium=Docs+Menu&utm_content=Best+Practices')
|
||||
cy.findByRole('link', { name: 'Configuration' }).should('have.attr', 'href', 'https://on.cypress.io/configuration?utm_medium=Docs+Menu&utm_content=Configuration')
|
||||
cy.findByRole('link', { name: 'API' }).should('have.attr', 'href', 'https://on.cypress.io/api?utm_medium=Docs+Menu&utm_content=API')
|
||||
cy.validateExternalLink({
|
||||
name: 'Testing your app',
|
||||
href: 'https://on.cypress.io/testing-your-app?utm_medium=Docs+Menu&utm_content=Testing+Your+App',
|
||||
})
|
||||
|
||||
cy.findByRole('link', { name: 'Run tests faster' }).should('have.attr', 'href', 'https://on.cypress.io/parallelization?utm_medium=Docs+Menu&utm_content=Parallelization')
|
||||
cy.validateExternalLink({
|
||||
name: 'Organizing Tests',
|
||||
href: 'https://on.cypress.io/writing-and-organizing-tests?utm_medium=Docs+Menu&utm_content=Organizing+Tests',
|
||||
})
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'Best Practices',
|
||||
href: 'https://on.cypress.io/best-practices?utm_medium=Docs+Menu&utm_content=Best+Practices',
|
||||
})
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'Configuration',
|
||||
href: 'https://on.cypress.io/configuration?utm_medium=Docs+Menu&utm_content=Configuration',
|
||||
})
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'API',
|
||||
href: 'https://on.cypress.io/api?utm_medium=Docs+Menu&utm_content=API',
|
||||
})
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'Run tests faster',
|
||||
href: 'https://on.cypress.io/parallelization?utm_medium=Docs+Menu&utm_content=Parallelization',
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Set up CI' }).click()
|
||||
cy.findByText('Configure CI').should('be.visible')
|
||||
@@ -254,7 +284,11 @@ describe('App Top Nav Workflows', () => {
|
||||
|
||||
cy.findByTestId('login-panel').contains('Test User').should('be.visible')
|
||||
cy.findByTestId('login-panel').contains('test@example.com').should('be.visible')
|
||||
cy.findByRole('link', { name: 'Profile Settings' }).should('be.visible').and('have.attr', 'href', 'https://on.cypress.io/dashboard/profile')
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'Profile Settings',
|
||||
href: 'https://on.cypress.io/dashboard/profile',
|
||||
})
|
||||
|
||||
cy.intercept('mutation-Logout').as('logout')
|
||||
|
||||
|
||||
@@ -52,6 +52,18 @@ export interface FindBrowsersOptions {
|
||||
filter?(browser: Browser): boolean
|
||||
}
|
||||
|
||||
export interface ValidateExternalLinkOptions {
|
||||
/**
|
||||
* The user-visible descriptor for the link. If omitted, the href
|
||||
* is assumed to be the name.
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* The href value of the link to be validated.
|
||||
*/
|
||||
href: string
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
@@ -112,6 +124,11 @@ declare global {
|
||||
* Mocks the system browser retrieval to return the desired browsers
|
||||
*/
|
||||
findBrowsers(options?: FindBrowsersOptions): void
|
||||
/**
|
||||
* Finds a link with the provided text and href, either globally or within a chained subject,
|
||||
* and asserts that it triggers the appropriate mutation when clicked.
|
||||
*/
|
||||
validateExternalLink(options: ValidateExternalLinkOptions | string): Chainable<JQuery<HTMLElement>>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,6 +348,33 @@ function logInternal<T> (name: string | Partial<Cypress.LogConfig>, cb: (log: Cy
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a link with the provided text and href, either globally or within a chained subject,
|
||||
* and asserts that it triggers the appropriate mutation when clicked.
|
||||
*/
|
||||
function validateExternalLink (subject, options: ValidateExternalLinkOptions | string): Cypress.Chainable<JQuery<HTMLElement>> {
|
||||
let name
|
||||
let href
|
||||
|
||||
if (Cypress._.isString(options)) {
|
||||
name = href = options
|
||||
} else {
|
||||
({ name, href } = options)
|
||||
}
|
||||
|
||||
cy.intercept('mutation-ExternalLink_OpenExternal', { 'data': { 'openExternal': true } }).as('OpenExternal')
|
||||
|
||||
cy.wrap(subject, { log: false }).findByRole('link', { name: name || href }).as('Link')
|
||||
.should('have.attr', 'href', href)
|
||||
.click()
|
||||
|
||||
cy.wait('@OpenExternal')
|
||||
.its('request.body.variables.url')
|
||||
.should('equal', href)
|
||||
|
||||
return cy.get('@Link')
|
||||
}
|
||||
|
||||
Cypress.Commands.add('scaffoldProject', scaffoldProject)
|
||||
Cypress.Commands.add('addProject', addProject)
|
||||
Cypress.Commands.add('openGlobalMode', openGlobalMode)
|
||||
@@ -342,5 +386,6 @@ Cypress.Commands.add('openProject', openProject)
|
||||
Cypress.Commands.add('withCtx', withCtx)
|
||||
Cypress.Commands.add('remoteGraphQLIntercept', remoteGraphQLIntercept)
|
||||
Cypress.Commands.add('findBrowsers', findBrowsers)
|
||||
Cypress.Commands.add('validateExternalLink', { prevSubject: ['optional', 'element'] }, validateExternalLink)
|
||||
|
||||
installCustomPercyCommand()
|
||||
|
||||
@@ -31,9 +31,17 @@ describe('Choose a Browser Page', () => {
|
||||
cy.get('[data-cy="alert-body"]')
|
||||
.should('contain', 'The specified browser was not found on your system or is not supported by Cypress: doesNotExist')
|
||||
|
||||
cy.get('[data-cy="alert-body"] a').eq(1)
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', 'https://on.cypress.io/troubleshooting-launching-browsers')
|
||||
cy.get('[data-cy="alert-body"]').within(() => {
|
||||
cy.validateExternalLink({
|
||||
name: 'use a custom browser',
|
||||
href: 'https://on.cypress.io/customize-browsers',
|
||||
})
|
||||
|
||||
cy.validateExternalLink({
|
||||
name: 'how to troubleshoot launching browsers',
|
||||
href: 'https://on.cypress.io/troubleshooting-launching-browsers',
|
||||
})
|
||||
})
|
||||
|
||||
// Ensure warning can be dismissed
|
||||
cy.get('[data-cy="alert-suffix-icon"]').click()
|
||||
@@ -51,10 +59,10 @@ describe('Choose a Browser Page', () => {
|
||||
cy.get('[data-cy="alert-body"]')
|
||||
.should('contain', 'We could not identify a known browser at the path you specified: /path/does/not/exist')
|
||||
.should('contain', 'spawn /path/does/not/exist ENOENT')
|
||||
|
||||
cy.get('[data-cy="alert-body"] a')
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', 'https://on.cypress.io/troubleshooting-launching-browsers')
|
||||
.validateExternalLink({
|
||||
name: 'how to troubleshoot launching browsers',
|
||||
href: 'https://on.cypress.io/troubleshooting-launching-browsers',
|
||||
})
|
||||
|
||||
// Ensure warning can be dismissed
|
||||
cy.get('[data-cy="alert-suffix-icon"]').click()
|
||||
|
||||
Reference in New Issue
Block a user