Skip to content

Commit

Permalink
test: cypress setup (#4)
Browse files Browse the repository at this point in the history
* chore: setup cypress

* test: add basic visual testing

* chore: add cypress script

* test: spacing and saturation testing

* test: github action for cypress

* chore: clean up comments

* test: cypress gitaction

* test: run cypress on ubuntu

* chore: clean up gitaction branches

* fix: cypress testing wait on main.js to load before proceeding

* doc: custom command origin
  • Loading branch information
cherylchen2 authored Apr 10, 2023
1 parent c9aea74 commit 1dd795d
Show file tree
Hide file tree
Showing 12 changed files with 978 additions and 25 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: e2e Tests
on:
push:
branches:
- main
pull_request:
paths:
- .github/workflows/cypress.yml
- projects/**/*

jobs:
test:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install yarn packages
run: |
yarn install
- name: Run Cypress for environment
uses: cypress-io/github-action@v2
with:
start: |
yarn start:demo
wait-on: "http://localhost:8000"
wait-on-timeout: 300
browser: chrome
config-file: cypress.config.ts
21 changes: 21 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from "cypress";

export default defineConfig({
component: {
devServer: {
framework: "angular",
bundler: "webpack",
},
specPattern: "**/*.cy.ts",
},

env: {
baseUrl: "http://localhost:8000",
},

e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
103 changes: 103 additions & 0 deletions cypress/e2e/astral-accessibility.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
describe('template spec', () => {
it('passes', () => {
cy.visit(Cypress.env('baseUrl'));
cy.waitForResource('main.js')

const textElements = 'p,h1,h2,h3,h4,h5,h6,div,a,button,label';

const ally = cy.document().find('astral-accessibility');
ally.click();
ally.find('.astral-modal').should('have.class', 'active');

const contrastComponent = cy.document().find('astral-contrast');
// inverted
contrastComponent.click();
cy.document().find('html').should('have.class', 'astral_inverted');

// high contrast
contrastComponent.click();
cy.document().find('html').should('not.have.class', 'astral_inverted');
cy.document()
.find('html')
.find('.card')
.should('have.css', 'background-color', 'rgba(0, 0, 0, 0)')
.and('have.css', 'color', 'rgb(0, 0, 0)');

// dakr high contrast
contrastComponent.click();
cy.document()
.find('html')
.find('.card')
.should('have.css', 'background-color', 'rgb(0, 0, 0)')
.and('have.css', 'color', 'rgb(255, 255, 255)')
.and('have.css', 'font-weight', '700');

// revert
contrastComponent.click();
cy.document()
.find('html')
.find('.card')
.should('have.css', 'background-color', 'rgba(255, 255, 255, 0.7)')
.and('have.css', 'color', 'rgb(0, 0, 0)');

const saturationComponent = cy.document().find('astral-saturate');

// Low Saturation
saturationComponent.click();
cy.document().find('html').should('have.class', 'astral_low_saturation');

// High Saturated
saturationComponent.click();
cy.document()
.find('html')
.should('have.class', 'astral_high_saturation')
.and('not.have.class', 'astral_low_saturation')
.and('not.have.class', 'astral_desaturated');

// Desaturated
saturationComponent.click();
cy.document()
.find('html')
.should('have.class', 'astral_desaturated')
.and('not.have.class', 'astral_high_saturation')
.and('not.have.class', 'astral_low_saturation');

// reset saturation
saturationComponent.click();
const defaultFontSize = 16;
cy.document()
.find('html')
.should('not.have.class', 'astral_desaturated')
.and('not.have.class', 'astral_high_saturation')
.and('not.have.class', 'astral_low_saturation');

const spacingComponent = cy.document().find('astral-text-spacing');
// light spacing
spacingComponent.click();
cy.document()
.get(textElements)
.should('have.css', 'word-spacing', `${defaultFontSize * 0.16}px`)
.and('have.css', 'letter-spacing', `${defaultFontSize * 0.12}px`);

// medium spacing
spacingComponent.click();
cy.document()
.get(textElements)
.should('have.css', 'word-spacing', `${defaultFontSize * 0.32}px`)
.and('have.css', 'letter-spacing', `${defaultFontSize * 0.24}px`);

// heavy spacing
spacingComponent.click();
cy.document()
.get(textElements)
.should('have.css', 'word-spacing', `${defaultFontSize * 0.48}px`)
.and('have.css', 'letter-spacing', `${defaultFontSize * 0.36}px`);

// revert spacing
spacingComponent.click();
cy.document()
.get(textElements)
.should('have.css', 'word-spacing', `0px`)
.and('have.css', 'letter-spacing', `0`);
});
});
5 changes: 5 additions & 0 deletions cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
9 changes: 9 additions & 0 deletions cypress/integrations/contrast.component.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ContrastComponent } from 'projects/astral-accessibility/src/lib/controls/contrast.component';

describe('My First Test', () => {
it('Contrast component', () => {
it('mounts', () => {
cy.mount(ContrastComponent);
});
});
});
70 changes: 70 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts 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
// ***********************************************

// https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/testing-dom__wait-for-resource
Cypress.Commands.add('waitForResource', (name, options = {}) => {
if (Cypress.browser.family === 'firefox') {
cy.log('Skip waitForResource in Firefox')

return
}

cy.log(`Waiting for resource ${name}`)

const log = false // let's not log inner commands
const timeout = options.timeout || Cypress.config('defaultCommandTimeout')

cy.window({ log }).then(
// note that ".then" method has options first, callback second
// https://on.cypress.io/then
{ log, timeout },
(win) => {
return new Cypress.Promise((resolve, reject) => {
let foundResource

// control how long we should try finding the resource
// and if it is still not found. An explicit "reject"
// allows us to show nice informative message
setTimeout(() => {
if (foundResource) {
// nothing needs to be done, successfully found the resource
return
}

clearInterval(interval)
reject(new Error(`Timed out waiting for resource ${name}`))
}, timeout)

const interval = setInterval(() => {
foundResource = win.performance
.getEntriesByType('resource')
.find((item) => item.name.endsWith(name))

if (!foundResource) {
// resource not found, will try again
return
}

clearInterval(interval)
// because cy.log changes the subject, let's resolve the returned promise
// with log + returned actual result
resolve(
cy.log('✅ success').then(() => {
// let's resolve with the found performance object
// to allow tests to inspect it
return foundResource
})
)
}, 100)
})
}
)
})
12 changes: 12 additions & 0 deletions cypress/support/component-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>
39 changes: 39 additions & 0 deletions cypress/support/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ***********************************************************
// This example support/component.ts 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'

// Alternatively you can use CommonJS syntax:
// require('./commands')

import { mount } from 'cypress/angular'

// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount
}
}
}

Cypress.Commands.add('mount', mount)

// Example use:
// cy.mount(MyComponent)
20 changes: 20 additions & 0 deletions cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.ts 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'

// Alternatively you can use CommonJS syntax:
// require('./commands')
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"cypress": "cypress open",
"build:lib": "ng build --single-bundle --output-hashing=none",
"build:lib:dev": "ng build --watch --configuration=development --single-bundle",
"start:demo-server": "lite-server -c projects/demo/lite-server-config.json",
Expand All @@ -33,6 +34,7 @@
"@angular/compiler-cli": "^14.1.0",
"@types/jasmine": "~4.0.0",
"bootstrap": "^5.2.3",
"cypress": "^12.5.1",
"jasmine-core": "~4.2.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.1.0",
Expand Down
11 changes: 5 additions & 6 deletions projects/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ <h1>Welcome to Astral Accessibility!</h1>
</div>

<div class="introduction">
<p>
Astral accessibility is a widget in Angular application that
provides reading accessibility functionalities like text size, text
line height/spacing, text reader, contrast, invert, saturation. It
is located at the bottom right corner of the application.
</p>
Astral accessibility is a widget in Angular application that provides
reading accessibility functionalities like text size, text line
height/spacing, text reader, contrast, invert, saturation. It is
located at the bottom right corner of the application.

<h4>Screen Reader</h4>
<p>
Screen reader is a tool where it would reads out texts on screen
Expand Down
Loading

0 comments on commit 1dd795d

Please sign in to comment.