chore(e2e): Add Cypress for link checking and end-to-end tests. Fix broken links revealed by tests.
- Adds Cypress and a few basic tests for the global topnav, the home page, and link-checking. - For link-checking, pass a comma-delimited list of URLs in an exported cypress_test_subjects environment variable. For examples, see the convenience commands in package.jsonpull/5816/head
parent
3be6e79a76
commit
ef106dd3a1
|
@ -0,0 +1,29 @@
|
|||
const { defineConfig } = require('cypress');
|
||||
|
||||
module.exports = defineConfig({
|
||||
e2e: {
|
||||
// Automatically prefix cy.visit() and cy.request() commands with a baseUrl.
|
||||
baseUrl: 'http://localhost:1313',
|
||||
projectId: 'influxdata-docs',
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
on('task', {
|
||||
// Fetch the product list configured in /data/products.yml
|
||||
getData(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const yq = require('js-yaml');
|
||||
const fs = require('fs');
|
||||
const cwd = process.cwd();
|
||||
try {
|
||||
resolve(
|
||||
yq.load(fs.readFileSync(`${cwd}/data/${filename}.yml`, 'utf8'))
|
||||
);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Article links', () => {
|
||||
const subjects = Cypress.env('test_subjects').split(',');
|
||||
|
||||
subjects.forEach((subject) => {
|
||||
it('contains valid internal links', function () {
|
||||
cy.visit(`${subject}`);
|
||||
cy.get('article a[href^="/"]') //.filter('[href^="/"]')
|
||||
.each(($a) => {
|
||||
cy.log(`** Testing internal link ${$a.attr('href')} **`);
|
||||
// cy.request doesn't show in your browser's Developer Tools
|
||||
// because the request comes from Node, not from the browser.
|
||||
cy.request($a.attr('href')).its('status').should('eq', 200);
|
||||
});
|
||||
});
|
||||
it('contains valid external links', function () {
|
||||
cy.visit(`${subject}`);
|
||||
cy.get('article a[href^="http"]')
|
||||
.each(($a) => {
|
||||
// cy.request doesn't show in your browser's Developer Tools
|
||||
cy.log(`** Testing external link ${$a.attr('href')} **`);
|
||||
// because the request comes from Node, not from the browser.
|
||||
cy.request($a.attr('href')).its('status').should('eq', 200);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
/// <reference types="cypress" />
|
||||
|
||||
describe('Docs home', function() {
|
||||
beforeEach(() => cy.visit('/'));
|
||||
|
||||
it('has metadata', function() {
|
||||
cy.title().should('eq', 'InfluxData Documentation');
|
||||
});
|
||||
|
||||
it('can search with mispellings', function() {
|
||||
cy.get('.sidebar--search').within(() => {
|
||||
cy.get('input#algolia-search-input').type('sql uery');
|
||||
cy.get('#algolia-autocomplete-listbox-0')
|
||||
.should('contain', 'Basic query examples')
|
||||
cy.get('input#algolia-search-input')
|
||||
.type('{esc}')
|
||||
cy.get('#algolia-autocomplete-listbox-0')
|
||||
.should('not.be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('main heading', function() {
|
||||
cy.get('h1').should('contain', 'InfluxData Documentation');
|
||||
});
|
||||
|
||||
it('content has links to all products', function() {
|
||||
cy.task('getData', 'products').then((productData) => {
|
||||
Object.values(productData).forEach((p) => {
|
||||
let name = p.altname?.length > p.name.length ? p.altname : p.name;
|
||||
name = name.replace(/\((.*)\)/, '$1');
|
||||
cy.get('.home-content a').filter(`:contains(${name})`).first().click();
|
||||
const urlFrag = p.latest.replace(/(v\d+)\.\w+/, '$1');
|
||||
cy.url().should('include', urlFrag);
|
||||
cy.go('back');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
describe('global top navigation', function () {
|
||||
beforeEach(function () {
|
||||
// Visit the Docs home page
|
||||
cy.visit('/');
|
||||
cy.get('.notification').filter(':visible').find('.close-notification').click({ force: true });
|
||||
});
|
||||
|
||||
describe('theme switcher', function () {
|
||||
it('switches light to dark', function () {
|
||||
// Default is light theme
|
||||
cy.get('body.home').should('have.css', 'background-color', 'rgb(243, 244, 251)');
|
||||
cy.get('#theme-switch-dark').click();
|
||||
cy.get('body.home').should('have.css', 'background-color', 'rgb(7, 7, 14)');
|
||||
cy.get('#theme-switch-light').click();
|
||||
cy.get('body.home').should('have.css', 'background-color', 'rgb(243, 244, 251)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('product dropdown', function () {
|
||||
it('has links to all products', function () {
|
||||
cy.get('#product-dropdown .selected').contains('Select product').click({ force: true });
|
||||
cy.task('getData', 'products').then((productData) => {
|
||||
Object.values(productData).forEach((p) => {
|
||||
cy.get('#dropdown-items a').should('be.visible');
|
||||
let name = p.altname?.length > p.name.length ? p.altname : p.name;
|
||||
name = name.replace(/\((.*)\)/, '$1');
|
||||
cy.get('#dropdown-items a')
|
||||
.filter(`:contains(${name})`)
|
||||
.first()
|
||||
.click();
|
||||
const urlFrag = p.latest.replace(/(v\d+)\.\w+/, '$1');
|
||||
cy.url().should('include', urlFrag);
|
||||
// Test that the selected option is for the current product.
|
||||
// Reopen the dropdown.
|
||||
cy.get('#product-dropdown .selected').contains(name).click({ force: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 421 KiB |
Binary file not shown.
After Width: | Height: | Size: 476 KiB |
|
@ -0,0 +1,25 @@
|
|||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
|
@ -0,0 +1,17 @@
|
|||
// ***********************************************************
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
|
@ -11,7 +11,9 @@
|
|||
"autoprefixer": ">=10.2.5",
|
||||
"eslint": "^9.18.0",
|
||||
"globals": "^15.14.0",
|
||||
"cypress": "^14.0.1",
|
||||
"hugo-extended": ">=0.101.0",
|
||||
"nightwatch": "^3.11.0",
|
||||
"postcss": ">=8.4.31",
|
||||
"postcss-cli": ">=9.1.0",
|
||||
"prettier": "^3.2.5",
|
||||
|
@ -27,6 +29,10 @@
|
|||
"vanillajs-datepicker": "^1.3.4"
|
||||
},
|
||||
"scripts": {
|
||||
"e2e:chrome": "npx cypress run --browser chrome",
|
||||
"e2e:o": "npx cypress open",
|
||||
"e2e:o:links": "export cypress_test_subjects=\"http://localhost:1313/influxdb3/core/,http://localhost:1313/influxdb3/enterprise/\"; npx cypress open cypress/e2e/article-links.cy.js",
|
||||
"e2e:links": "export cypress_test_subjects=\"http://localhost:1313/influxdb3/core/,http://localhost:1313/influxdb3/enterprise/\"; npx cypress run --spec cypress/e2e/article-links.cy.js",
|
||||
"lint": "LEFTHOOK_EXCLUDE=test lefthook run pre-commit && lefthook run pre-push",
|
||||
"pre-commit": "lefthook run pre-commit",
|
||||
"test-content": "docker compose --profile test up"
|
||||
|
|
Loading…
Reference in New Issue