Skip to content

Commit

Permalink
Add Cypress tests (#80)
Browse files Browse the repository at this point in the history
* add tests

* fix lint errors

* fix cypress and jest conflicting types

* fix ts config excluding spec types

* add message

* yarn lint

* add message check

* raw cypress run

* fix lint

* test cypress ci

* use rebuild

* using build tag

* remove node_modules when building cypress

* test using npm

* remove screenshot

* ignore screenshots

* remote testing dep

* remove testing dep

* rebuild with yarn

* rebuild with npm

* update binary flag

* install canvas

* separate task

* capure cypress

* upload downloads

* use global font-family and update baseline pdfs

* build examples, increase tolerance

* update examples and reduce tolerance and threshold

* update ci

* empty message

* undefined
  • Loading branch information
ivmarcos authored Sep 7, 2023
1 parent 79d4272 commit 42f19fa
Show file tree
Hide file tree
Showing 23 changed files with 997 additions and 83 deletions.
28 changes: 25 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,39 @@ jobs:

strategy:
matrix:
node-version: [16.x, 18.x]
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v3

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"
- run: yarn install
- run: yarn build
- run: yarn lint
- run: yarn test

- name: Run tests
run: |
yarn lint
yarn test
yarn start &
yarn cypress run
- name: Upload Cypress Screenshots
uses: actions/upload-artifact@v1
# Only capture images on failure
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots

- name: Upload Cypress Downloads
uses: actions/upload-artifact@v1
# Only capture logs on failure
if: failure()
with:
name: cypress-downloads
path: cypress/downloads
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ lib
package-lock.json
yarn-error.log
umd
.parcel-cache/
.parcel-cache/
cypress/downloads
cypress/baseline/diff
cypress/baseline/png
cypress/screenshots
4 changes: 3 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ package-lock.json
yarn-error.log
.parcel-cache/
dist/
example/
examples/
cypress/
cypress.config.js
50 changes: 50 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import path from "path";
import { defineConfig } from "cypress";
import ComparePdf, { ComparePdfConfig } from "compare-pdf";

const comparePDFConfig: ComparePdfConfig = {
paths: {
actualPdfRootFolder: path.join(process.cwd(), "cypress", "downloads"),
baselinePdfRootFolder: path.join(process.cwd(), "cypress", "baseline"),
actualPngRootFolder: path.join(
process.cwd(),
"cypress",
"downloads",
"png"
),
baselinePngRootFolder: path.join(
process.cwd(),
"cypress",
"baseline",
"png"
),
diffPngRootFolder: path.join(process.cwd(), "cypress", "baseline", "diff"),
},
settings: {
imageEngine: "native",
density: 150,
quality: 80,
tolerance: 0,
threshold: 0.1,
cleanPngPaths: false,
matchPageCount: true,
disableFontFace: true,
verbosity: 0,
},
};

export default defineConfig({
e2e: {
setupNodeEvents(on) {
on("task", {
async compareFile(filename: string) {
const comparisonResults = await new ComparePdf(comparePDFConfig)
.actualPdfFile(filename)
.baselinePdfFile(filename)
.compare();
return comparisonResults;
},
});
},
},
});
Binary file added cypress/baseline/advanced-example.pdf
Binary file not shown.
Binary file added cypress/baseline/function-example.pdf
Binary file not shown.
Binary file added cypress/baseline/multipage-example.pdf
Binary file not shown.
Binary file added cypress/baseline/usepdf-example.pdf
Binary file not shown.
57 changes: 57 additions & 0 deletions cypress/e2e/spec.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { slugify } from "../../examples/utils";

const getLink = (example: ExampleTest) =>
cy.get(`a[id='example-${slugify(example.title)}'`);
const getButton = (example: ExampleTest) => getLink(example).find("button");

interface ExampleTest {
title: string;
filename: string;
}

interface ComparisonResult {
status: "passed" | "failed";
message?: string;
}

export const examples: ExampleTest[] = [
{
title: "Using usePDF hook",
filename: "usepdf-example.pdf",
},
{
title: "Using default function",
filename: "function-example.pdf",
},
{
title: "Multipage support",
filename: "multipage-example.pdf",
},
{
title: "Advanced options",
filename: "advanced-example.pdf",
},
];

describe("template spec", () => {
before(() => {
cy.visit("http://localhost:1234");
});

it("pdfs must mach baseline", () => {
examples.forEach((example) => {
getLink(example).should("be.visible");
getButton(example).should("be.visible");
getButton(example).click();
});
cy.wait(10000);
examples.forEach((example) => {
cy.task("compareFile", example.filename).then(
(result: ComparisonResult) => {
expect(result.message).to.be.undefined;
expect(result.status).to.equal("passed");
}
);
});
});
});
37 changes: 37 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <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
// ***********************************************
//
//
// -- 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) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
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')
33 changes: 3 additions & 30 deletions examples/App.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,8 @@
import React from "react";
import { ExampleUsePDF } from "./ExampleUsePDF";
import { ExampleFunction } from "./ExampleFunction";
import { ExampleMultipage } from "./ExampleMultipage";
import { ExampleAdvanced } from "./ExampleAdvanced";
import "./app.css";

interface Example {
title: string;
component: React.FC;
}

const slugify = (text: string) => text.toLowerCase().replace(/\s/g, "-");

const examples: Example[] = [
{
title: "Using usePDF hook",
component: ExampleUsePDF,
},
{
title: "Using default function",
component: ExampleFunction,
},
{
title: "Multipage support",
component: ExampleMultipage,
},
{
title: "Advanced options",
component: ExampleAdvanced,
},
];
import "./app.css";
import { examples } from "./examples";
import { slugify } from "./utils";

export const App = () => {
return (
Expand Down
5 changes: 3 additions & 2 deletions examples/ExampleAdvanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { Button } from "./Button";
import { Container } from "./Container";

const options: Options = {
filename: "advanced-example.pdf",
// default is `save`
method: "open",
method: "save",
// default is Resolution.MEDIUM = 3, which should be enough, higher values
// increases the image quality but also the size of the PDF, so be careful
// using values higher than 10 when having multiple pages generated, it
Expand Down Expand Up @@ -44,7 +45,7 @@ export const ExampleAdvanced = () => {
};
return (
<Container>
<Button onClick={openPDF}>Open PDF</Button>
<Button onClick={openPDF}>Download PDF</Button>
<div id="wrapper">
<Card imageId={17} title="Using advanced options" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion examples/ExampleMultipage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ExampleMultipage = () => {
<Container>
<Button onClick={toPDF}>Download PDF</Button>
<div ref={targetRef}>
{Array(10)
{Array(5)
.fill(0)
.map((_, index) => (
<Card
Expand Down
5 changes: 2 additions & 3 deletions examples/app.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
h1,
h3 {
font-family: Arial, Helvetica, sans-serif;
body {
font-family: Helvetica, sans-serif;
}

h3 {
Expand Down
1 change: 0 additions & 1 deletion examples/button.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.button {
font-family: Arial, Helvetica, sans-serif !important;
background-color: #f9f9f9;
transition: all ease 300ms;
border: 1px solid #ccc;
Expand Down
4 changes: 0 additions & 4 deletions examples/card.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.card-container > * {
font-family: Arial, Helvetica, sans-serif !important;
}

.card-container {
text-align: center;
border: 1px solid #ccc;
Expand Down
28 changes: 28 additions & 0 deletions examples/examples.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ExampleUsePDF } from "./ExampleUsePDF";
import { ExampleFunction } from "./ExampleFunction";
import { ExampleMultipage } from "./ExampleMultipage";
import { ExampleAdvanced } from "./ExampleAdvanced";

export interface Example {
title: string;
component: React.FC;
}

export const examples: Example[] = [
{
title: "Using usePDF hook",
component: ExampleUsePDF,
},
{
title: "Using default function",
component: ExampleFunction,
},
{
title: "Multipage support",
component: ExampleMultipage,
},
{
title: "Advanced options",
component: ExampleAdvanced,
},
];
1 change: 1 addition & 0 deletions examples/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const slugify = (text: string) => text.toLowerCase().replace(/\s/g, "-");
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"docs": "typedoc --plugin typedoc-plugin-markdown --out docs src/index.ts src/types.ts src/constants.ts",
"test": "npm run lint && jest",
"lint": "eslint . && prettier -c .",
"format": "prettier --write src examples README.md CHANGELOG.md *.json"
"format": "prettier --write src examples README.md CHANGELOG.md *.json *.ts cypress .github"
},
"devDependencies": {
"@babel/preset-env": "^7.20.2",
Expand All @@ -37,7 +37,6 @@
"@parcel/packager-ts": "2.8.3",
"@parcel/transformer-typescript-types": "2.8.3",
"@release-it/keep-a-changelog": "^4.0.0",
"@testing-library/react-hooks": "^8.0.1",
"@types/jest": "^29.5.1",
"@types/jsdom": "^21.1.1",
"@types/react": "^18.0.28",
Expand All @@ -46,6 +45,8 @@
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"canvas": "^2.11.0",
"compare-pdf": "^1.1.8",
"cypress": "^13.1.0",
"eslint": "^8.39.0",
"eslint-plugin-react": "^7.32.2",
"jest": "^29.5.0",
Expand Down
1 change: 1 addition & 0 deletions src/converter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* @jest-environment jsdom
*/

import { test, expect } from "@jest/globals";
import { Margin, Resolution } from "./constants";
import Converter from "./converter";
import { Options } from "./types";
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"experimentalDecorators": true,
"lib": ["es2015", "DOM"],
"jsx": "react",
"esModuleInterop": true
"esModuleInterop": true,
"types": ["cypress", "node", "jest"]
}
}
Loading

0 comments on commit 42f19fa

Please sign in to comment.