Skip to content

Commit

Permalink
feat: Add Cypress (#16)
Browse files Browse the repository at this point in the history
Fixes #10 

- Adds Cypress
- Adds Cypress to CircleCI testing
- Tests all examples
	- some changes were made to the themes in order to test those
	- tests ensure that all elements are showing correctly in the examples. the functionality around the theme options isn't tested yet
  • Loading branch information
LekoArts committed Aug 2, 2019
1 parent 0a23b52 commit ca0ed29
Show file tree
Hide file tree
Showing 27 changed files with 965 additions and 56 deletions.
63 changes: 60 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ executors:
TERM: xterm

aliases:
e2e-executor: &e2e-executor
docker:
- image: cypress/browsers:chrome69
environment:
TERM: xterm

restore_cache: &restore_cache
restore_cache:
name: Restore Yarn Package Cache
keys:
- v{{ .Environment.versionCache }}-deps-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }}
- v{{ .Environment.versionCache }}-deps-{{ .Branch }}-{{ checksum "yarn.lock" }}

install_node_modules: &install_node_modules
run:
Expand All @@ -24,7 +30,7 @@ aliases:
save_cache: &save_cache
save_cache:
name: Save Yarn Package Cache
key: v{{ .Environment.versionCache }}-deps-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }}
key: v{{ .Environment.versionCache }}-deps-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- /home/circleci/.cache

Expand All @@ -36,6 +42,33 @@ aliases:
store_artifacts:
path: results

e2e-test-workflow: &e2e-test-workflow
filters:
branches:
ignore:
- /docs.+/
- /www.+/

commands:
e2e-test:
parameters:
example-name:
type: string
steps:
- checkout
- <<: *restore_cache
- <<: *install_node_modules
- <<: *save_cache
- run:
name: Execute E2E script
command: bash ./scripts/e2e-build.sh "<< parameters.example-name >>"
- <<: *store_results
- <<: *store_results_artifacts
- store_artifacts:
path: cypress/videos
- store_artifacts:
path: cypress/screenshots

version: 2.1

jobs:
Expand All @@ -52,8 +85,32 @@ jobs:
- <<: *store_results
- <<: *store_results_artifacts

e2e-test-emma:
<<: *e2e-executor
steps:
- e2e-test:
example-name: emma

e2e-test-cara:
<<: *e2e-executor
steps:
- e2e-test:
example-name: cara

e2e-test-status-dashboard:
<<: *e2e-executor
steps:
- e2e-test:
example-name: status-dashboard

workflows:
version: 2
lint-test:
jobs:
- lint
- lint
- e2e-test-emma:
<<: *e2e-test-workflow
- e2e-test-cara:
<<: *e2e-test-workflow
- e2e-test-status-dashboard:
<<: *e2e-test-workflow
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
typings.d.ts
index.d.ts
www/src/webgl/uniforms.js
cypress/e2e/build
logs
*.log
npm-debug.log*
Expand Down
7 changes: 6 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ module.exports = {
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true,
}
},
project: './tsconfig.json'
},
env: {
browser: true,
jest: true,
node: true,
},
globals: {
cy: true,
Cypress: true,
},
rules: {
"@typescript-eslint/no-unused-vars": [
1,
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ public

.idea
.vscode
.DS_Store
.DS_Store

cypress/e2e/build
results
cypress/videos
cypress/screenshots
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,25 @@ yarn workspace [examples/name] develop

In the case of `examples/emma` this command would be `yarn workspace emma develop`. Now you can make changes to the respective theme and see them via Hot-Reloading.

Commit your changes to a feature branch of your fork and open up a PR against this repository.
Commit your changes to a feature branch of your fork and open up a PR against this repository. The PR will have checks in place (unit and end-to-end tests) which you can also run on your machine in preparation for the PR.

### Testing

#### Cypress

The Cypress tests are written in TypeScript, too, and hence need to be compiled before usage. Run the following script for development:

```sh
bash ./scripts/e2e-dev.sh "example-name"
```

In the case of `examples/emma` the "example-name" would be "emma".

The script starts `tsc` in _watch_ mode (for the files in `cypress/e2e`) and outputs them to `cypress/e2e/build` + starts `start-server-and-test` with Gatsby's development server and Cypress. Once the Cypress GUI opens select the fitting test (the others won't work, only the respective test + `smoke.js`!).

CircleCI will run the `e2e-build.sh` script — you can use it to run the tests headless.

You can skip the e2e tests if you use `docs` or `www` in your branch name, e.g. `docs/improve-readme` or `www/add-new-entry`.

## 🤩 Newsletter

Expand Down
6 changes: 6 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"baseUrl": "http://localhost:8000",
"integrationFolder": "cypress/e2e/build",
"viewportHeight": 900,
"viewportWidth": 1440
}
32 changes: 32 additions & 0 deletions cypress/e2e/cara.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// <reference types="../support/index" />
/// <reference types="cypress" />
/// <reference types="@testing-library/cypress/typings" />

describe(`gatsby-theme-cara`, () => {
beforeEach(() => {
cy.visit(`/`).waitForRouteChange()
})
it(`should render hero content`, () => {
cy.getByText(/hi, i'm jane doe/i)
})
it(`should render project content`, () => {
cy.getByText(/freiheit/i).getByText(/this project is my entry to adobe's #challengeyourperspective contest./i)
})
it(`should render project cards with links`, () => {
cy.getByText(/freiheit/i)
.parent()
.should(`have.attr`, `href`, `https://www.behance.net/gallery/58937147/Freiheit`)
})
it(`should render about content`, () => {
cy.getByText(/winky face./i)
})
it(`should render contact content`, () => {
cy.getByText(/Dribbble/i)
})
it(`should render the light/dark mode toggle`, () => {
cy.getByLabelText(/toggle dark mode/i)
})
it(`should render the footer`, () => {
cy.getByText(/theme by lekoarts/i)
})
})
48 changes: 48 additions & 0 deletions cypress/e2e/emma.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// <reference types="../support/index" />
/// <reference types="cypress" />
/// <reference types="@testing-library/cypress/typings" />

describe(`gatsby-theme-emma`, () => {
beforeEach(() => {
cy.visit(`/`).waitForRouteChange()
})
it(`should render the site title`, () => {
cy.getByLabelText(/emma, back to homepage/i)
})
it(`should render additional page in navigation`, () => {
cy.getByText(/about/i)
})
it(`should render the light/dark mode toggle`, () => {
cy.getByLabelText(/toggle dark mode/i)
})
it(`should render social media icons in header`, () => {
cy.getByLabelText(/instagram/i).getByLabelText(/dribbble/i)
})
it(`should render the footer`, () => {
cy.getByText(/theme by lekoarts/i)
})
it(`should have item with all information`, () => {
cy.getByLabelText(/view detail page of hermione granger/i).within(() => {
cy.getByText(/hogwarts/i).getByText(/witchcraft/i)
})
})
it(`should link and display the project page`, () => {
cy.getByLabelText(/view detail page of hermione granger/i)
.click()
.waitForRouteChange()
.assertRoute(`/hermione-granger`)
.get(`h1`)
.within(() => {
cy.getByText(/hermione granger/i)
})
.getByText(/hogwarts/i)
.getByText(/10.06.2019/i)
.getByText(/witchcraft/i)
})
it(`should link and display the about page`, () => {
cy.getByText(/about/i)
.click()
.waitForRouteChange()
.assertRoute(`/about`)
})
})
9 changes: 9 additions & 0 deletions cypress/e2e/smoke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference types="../support/index" />
/// <reference types="cypress" />
/// <reference types="@testing-library/cypress/typings" />

describe(`app`, () => {
it(`should work`, () => {
cy.visit(`/`).assertRoute(`/`)
})
})
38 changes: 38 additions & 0 deletions cypress/e2e/status-dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/// <reference types="../support/index" />
/// <reference types="cypress" />
/// <reference types="@testing-library/cypress/typings" />

describe(`gatsby-theme-status-dashboard`, () => {
beforeEach(() => {
cy.visit(`/`).waitForRouteChange()
})
it(`should render the title`, () => {
cy.get(`h1`).within(() => {
cy.getByText(/status dashboard - lekoarts/i)
})
})
it(`should render the description`, () => {
cy.getByText(/showing the statuses of my netlify deploys & circleci tests./i)
})
it(`should render the info`, () => {
cy.getByText(/circleci projects/i)
})
it(`should render the repository title`, () => {
cy.getByText(/gatsby-themes-by-lekoarts/i)
})
it(`should render the circleci icon`, () => {
cy.getByLabelText(/view gatsby-themes-by-lekoarts on circleci/i)
})
it(`should render the github icon`, () => {
cy.getByLabelText(/view gatsby-themes-by-lekoarts source on github/i)
})
it(`should render the netlify status badge`, () => {
cy.getByAltText(/netlify deploy status of gatsby-themes-by-lekoarts/i)
})
it(`should render the circleci status badge`, () => {
cy.getByAltText(/circleci status of gatsby-themes-by-lekoarts/i)
})
it(`should render the footer`, () => {
cy.getByText(/theme by lekoarts/i)
})
})
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"
}
17 changes: 17 additions & 0 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
29 changes: 29 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ***********************************************
// 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 is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

Cypress.Commands.add(`assertRoute`, route => {
cy.url().should(`equal`, `${window.location.origin}${route}`)
})
17 changes: 17 additions & 0 deletions cypress/support/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/// <reference types="cypress" />

declare namespace Cypress {
interface Chainable<Subject> {
/**
* Assert the current URL
* @param route
* @example cy.assertRoute('/page-2')
*/
assertRoute(route: string): Chainable<any>

/**
* Waits for Gatsby to finish the route change, in order to ensure event handlers are properly setup
*/
waitForRouteChange(): Chainable<any>
}
}
Loading

0 comments on commit ca0ed29

Please sign in to comment.