Skip to content

Commit de9db3e

Browse files
authored
Moving to Vite from Create-React-App and configuring ESLint and Jest (#317)
* Moving to Vite from Create-React-App and configuring ESLint and Jest * Update dependencies that have minor or patch version available within the currently used major * Finally can test with Jest * Update Typescript and configure chunks for build * Everything can be typescript * Use ESLint to autofix and ignore png in Jest at the correct config location * Use Cypress plugin for ESLint to help validating its use and reduce false positive issues * ESLint should not lint everything, just the files under version control * Use type imports to clarify usage * ServiceWorker was not used * Test in units, not the whole app * Mention about the different test/spec files * Run tests at GitHub Actions * Node.js v16 marked * Save library chunking for later, and use smaller and specific docker images * Simplify Docker instructions plenty since the kids are asleep * Reduce linter errors * Cypress upgrade against the upgraded agent-cypress * Prettier run separately
1 parent f96d95d commit de9db3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+21771
-15345
lines changed

.eslintrc.cjs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module.exports = {
2+
extends: [
3+
// By extending from a plugin config, we can get recommended rules without having to add them manually.
4+
"eslint:recommended",
5+
"plugin:react/recommended",
6+
"plugin:import/recommended",
7+
"plugin:jsx-a11y/recommended",
8+
"plugin:@typescript-eslint/recommended",
9+
"plugin:cypress/recommended",
10+
// This disables the formatting rules in ESLint that Prettier is going to be responsible for handling.
11+
// Make sure it's always the last config, so it gets the chance to override other configs.
12+
"eslint-config-prettier",
13+
],
14+
settings: {
15+
react: {
16+
// Tells eslint-plugin-react to automatically detect the version of React to use.
17+
version: "detect",
18+
},
19+
// Tells eslint how to resolve imports
20+
"import/resolver": {
21+
node: {
22+
paths: ["src"],
23+
extensions: [".js", ".jsx", ".ts", ".tsx"],
24+
},
25+
},
26+
},
27+
rules: {
28+
// Add your own rules here to override ones from the extended configs.
29+
"@typescript-eslint/no-non-null-assertion": "warn"
30+
},
31+
};

.github/workflows/workflow.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ jobs:
1313
steps:
1414
- uses: actions/checkout@v3
1515

16+
- name: Setup Node.js environment
17+
uses: actions/setup-node@v3
18+
with:
19+
node-version: 16
20+
21+
- name: Install npm dependencies
22+
run: npm ci
23+
24+
- name: Unit tests
25+
run: npm test -- --coverage
26+
1627
- id: get-branch-name
1728
run: echo "::set-output name=branch_name::$(git symbolic-ref --short HEAD)"
1829
shell: bash

Dockerfile

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,35 @@
11
### STAGE 1: Build ###
2-
FROM node:12 AS builder
2+
# This image is around 50 megabytes
3+
FROM node:18-alpine3.18 AS builder
4+
5+
# Environment variable generation script needs bash
6+
RUN apk add --no-cache bash
37

48
# Create app directory
59
WORKDIR /app
610

7-
# A wildcard is used to ensure both package.json AND package-lock.json are copied
8-
COPY package*.json ./
11+
# Copy all files from the repo to /app
12+
COPY . .
913

1014
# Install app dependencies
11-
RUN npm install
12-
13-
COPY . .
15+
RUN npm ci --verbose
1416

17+
# Build the ui
1518
RUN npm run build
1619

17-
### STAGE 2: Run ###
18-
FROM nginx:alpine
20+
# Create environment variable js file
21+
RUN chmod +x env.sh && ./env.sh
1922

20-
RUN apk add --no-cache bash
23+
### STAGE 2: Run ###
24+
# This image is around 5 megabytes
25+
FROM nginx:1.25-alpine3.17-slim
2126

2227
COPY /nginx /etc/nginx/conf.d
23-
RUN chown -R nginx /etc/nginx /var/run /run
2428

2529
EXPOSE 8080
2630
EXPOSE 443
2731

2832
COPY --from=builder /app/build /usr/share/nginx/html
33+
COPY --from=builder /app/env-config.js /usr/share/nginx/html/
2934

30-
# Copy .env file and shell script to container
31-
WORKDIR /usr/share/nginx/html
32-
COPY .env .
33-
COPY ./env.sh .
34-
RUN chmod +x env.sh
35-
36-
RUN adduser -D app
37-
RUN chown -R app:app . && \
38-
chown -R app:app /var/cache/nginx && \
39-
chown -R app:app /var/log/nginx && \
40-
chown -R app:app /etc/nginx/conf.d
41-
RUN touch /var/run/nginx.pid && \
42-
chown -R app:app /var/run/nginx.pid
43-
USER app
44-
45-
# Start Nginx server
46-
CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]
35+
# Nginx server will now start automatically.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- Update `.env`
1010
- `npm run start`
1111

12+
The testing related `.spec.tsx` files are used with Cypress for browser tests, and the `.test.tsx` files with Jest for unit tests.
13+
1214
## Image download
1315

1416
- If you want to use image download feature in test runs, you have to have the files in backend imageUploads folder to a folder in this project under public/static/imageUploads. This can be achieved via manual copy, docker volume mapping to this project folder etc.

cypress.config.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {defineConfig} from "cypress";
2+
import viteConfig from "./vite.config";
3+
import {addVisualRegressionTrackerPlugin} from '@visual-regression-tracker/agent-cypress/dist/plugin';
4+
5+
export function setupNodeEvents(on : Cypress.PluginEvents, config : Cypress.PluginConfigOptions) { // react component tests
6+
7+
addVisualRegressionTrackerPlugin(on, config);
8+
9+
on("before:browser:launch", (browser, launchOptions) => {
10+
if (browser.name === "chrome" && browser.isHeadless) {
11+
launchOptions.args.push(`--window-size=${
12+
config.viewportWidth
13+
},${
14+
config.viewportHeight
15+
}`);
16+
return launchOptions;
17+
}
18+
});
19+
20+
return config;
21+
}
22+
23+
export default defineConfig({
24+
fixturesFolder: false,
25+
screenshotOnRunFailure: false,
26+
retries: 0,
27+
viewportWidth: 1280,
28+
viewportHeight: 800,
29+
video: false,
30+
31+
component: {
32+
setupNodeEvents,
33+
specPattern: "**/*.spec.*",
34+
devServer: {
35+
framework: "react",
36+
bundler: "vite",
37+
viteConfig
38+
}
39+
}
40+
});

cypress.json

Lines changed: 0 additions & 10 deletions
This file was deleted.

cypress/plugins/index.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

cypress/support/commands.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

cypress/support/component-index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
7+
<title>Components App</title>
8+
</head>
9+
<body>
10+
<div data-cy-root></div>
11+
</body>
12+
</html>

cypress/support/component.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// https://docs.cypress.io/guides/component-testing/react/api
2+
import {mount} from 'cypress/react';
3+
import {addVrtTrackCommand, addVrtStartCommand, addVrtStopCommand} from "@visual-regression-tracker/agent-cypress/dist/commands";
4+
5+
addVrtStartCommand();
6+
addVrtStopCommand();
7+
addVrtTrackCommand();
8+
9+
before(() => {
10+
cy.vrtStart();
11+
});
12+
13+
after(() => {
14+
cy.vrtStop();
15+
});
16+
17+
18+
// Augment the Cypress namespace to include type definitions for
19+
// your custom command.
20+
// Alternatively, can be defined in cypress/support/component.d.ts
21+
// with a <reference path="./component" /> at the top of your spec.
22+
declare global {
23+
namespace Cypress {
24+
interface Chainable {
25+
mount: typeof mount
26+
}
27+
}
28+
}
29+
30+
Cypress.Commands.add('mount', mount)
31+
32+
// Example use:
33+
// cy.mount(<MyComponent />)

cypress/support/index.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

docker-compose.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "3.7"
1+
version: "3.8"
22
services:
33
ui:
44
build:
@@ -7,8 +7,8 @@ services:
77
ports:
88
- "${PORT}:8080"
99
- "443:443"
10-
volumes:
10+
volumes:
1111
- ./secrets:/etc/nginx/secrets
12-
environment:
12+
environment:
1313
REACT_APP_API_URL: ${REACT_APP_API_URL}
1414
VRT_VERSION: ${VRT_VERSION}

index.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="/favicon.png" />
6+
<link
7+
rel="stylesheet"
8+
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
9+
/>
10+
<link
11+
rel="stylesheet"
12+
href="https://fonts.googleapis.com/icon?family=Material+Icons"
13+
/>
14+
15+
<meta name="viewport" content="width=device-width, initial-scale=1" />
16+
<meta name="theme-color" content="#000000" />
17+
18+
<title>Visual Regression Tracker</title>
19+
20+
<script src="/env-config.js"></script>
21+
</head>
22+
<body>
23+
<noscript>You need to enable JavaScript to run this app.</noscript>
24+
<div id="root"></div>
25+
<script type="module" src="/src/index.tsx"></script>
26+
</body>
27+
</html>

0 commit comments

Comments
 (0)