Skip to content

Commit be99a9d

Browse files
committed
build: coverage check with spectron and send to coveralls
1 parent fbcb3aa commit be99a9d

34 files changed

+2561
-824
lines changed

.babelrc

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
"plugins": [
88
["@babel/transform-runtime", {
99
"regenerator": true
10+
}],
11+
["istanbul", {
12+
"exclude": [
13+
"**/*.spec.js"
14+
]
1015
}]
1116
]
1217
}

.github/workflows/coverage.yml

+44-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ on: ['push', 'pull_request']
33
name: Test Coveralls
44

55
jobs:
6-
build:
7-
name: build
6+
react-test:
87
runs-on: ubuntu-latest
98
steps:
109
- name: check out git repository
@@ -24,3 +23,46 @@ jobs:
2423
uses: coverallsapp/github-action@master
2524
with:
2625
github-token: ${{ secrets.GITHUB_TOKEN }}
26+
flag-name: run-react-test
27+
parallel: true
28+
29+
spectron:
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: check out git repository
33+
uses: actions/checkout@v1
34+
35+
- name: install node.js, NPM and Yarn
36+
uses: actions/setup-node@v1
37+
with:
38+
node-version: 12
39+
40+
- name: yarn
41+
run: yarn install --network-timeout 1000000 # allows to run without network error
42+
43+
- name: build application
44+
run: yarn build:github
45+
env:
46+
REACT_APP_GRAASP_API_HOST: ${{secrets.REACT_APP_GRAASP_API_HOST}}
47+
REACT_APP_GRAASP_HOST: ${{secrets.REACT_APP_GRAASP_HOST}}
48+
REACT_APP_SHOW_NOTIFICATIONS: false
49+
50+
- name: spectron
51+
run: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' yarn mocha:coverage
52+
53+
- name: coveralls
54+
uses: coverallsapp/github-action@master
55+
with:
56+
github-token: ${{ secrets.GITHUB_TOKEN }}
57+
flag-name: run-spectron
58+
parallel: true
59+
60+
finish:
61+
needs: [spectron, react-test]
62+
runs-on: ubuntu-latest
63+
steps:
64+
- name: Coveralls Finished
65+
uses: coverallsapp/github-action@master
66+
with:
67+
github-token: ${{ secrets.GITHUB_TOKEN }}
68+
parallel-finished: true

.github/workflows/release.yml

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jobs:
4141
LOGGING_LEVEL: ${{secrets.LOGGING_LEVEL}}
4242
SENTRY_DSN: ${{secrets.SENTRY_DSN}}
4343
SENTRY_SUBMIT_URL: ${{secrets.SENTRY_SUBMIT_URL}}
44+
REACT_APP_SHOW_NOTIFICATIONS: toastr
4445
with:
4546
build_script_name: build:github
4647
# GitHub token, automatically provided to the action

package.json

+12-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@
6767
"report": "cat ./coverage/lcov.info | env-cmd -f ./.env.test codacy-coverage",
6868
"report:ci": "cat ./coverage/lcov.info | codacy-coverage",
6969
"version": "git add CHANGELOG.md && standard-version -a",
70-
"mocha:run": "mocha --require @babel/register --retries 3 'test/**/*.test.js'",
71-
"mocha": "mkdirp test/tmp && concurrently \"env-cmd -f ./.env.test react-scripts start\" \"wait-on http://localhost:3000 && yarn mocha:run\""
70+
"mocha:run": "mocha --exit --require @babel/register --retries 3 'test/**/*.test.js'",
71+
"mocha": "mkdirp test/tmp && concurrently \"env-cmd -f ./.env.test react-scripts start\" \"wait-on http://localhost:3000 && yarn mocha:run\"",
72+
"mocha:coverage": "nyc --reporter=lcov yarn mocha:run"
7273
},
7374
"dependencies": {
7475
"@material-ui/core": "4.11.4",
@@ -143,6 +144,8 @@
143144
"@babel/register": "7.13.16",
144145
"@commitlint/cli": "12.1.1",
145146
"@commitlint/config-conventional": "12.1.1",
147+
"@istanbuljs/nyc-config-babel": "3.0.0",
148+
"babel-plugin-istanbul": "6.0.0",
146149
"codacy-coverage": "3.4.0",
147150
"concurrently": "6.0.2",
148151
"cross-env": "7.0.3",
@@ -155,6 +158,7 @@
155158
"eslint-plugin-mocha": "8.1.0",
156159
"husky": "6.0.0",
157160
"npm-run-all": "4.1.5",
161+
"nyc": "15.1.0",
158162
"prettier": "2.2.1",
159163
"pretty-quick": "3.1.0",
160164
"react-scripts": "4.0.3",
@@ -228,6 +232,12 @@
228232
"jest": {
229233
"snapshotSerializers": [
230234
"enzyme-to-json/serializer"
235+
],
236+
"collectCoverageFrom": [
237+
"src/**/*.js",
238+
"!src/registerServiceWorker.js",
239+
"!src/index.js",
240+
"!src/store/*.js"
231241
]
232242
}
233243
}

public/app/preload.js

+16
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
11
// eslint-disable-next-line import/no-extraneous-dependencies
22
window.ipcRenderer = require('electron').ipcRenderer;
3+
4+
// mock fetch to provide local space definitions
5+
if (process.env.CI || process.env.NODE_ENV === 'test') {
6+
const spaces = JSON.parse(process.env?.API_DATABASE) || [];
7+
8+
// mock GET spaces calls
9+
window.fetch = async (url) => {
10+
const objectIdRegex = new RegExp(/[a-f\d]{24}/i);
11+
const id = url.match(objectIdRegex)?.[0];
12+
const content = spaces.find(({ id: sId }) => sId === id);
13+
const myBlob = new Blob([JSON.stringify(content)], {
14+
type: 'application/json',
15+
});
16+
return new Response(myBlob);
17+
};
18+
}

public/electron.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ if (process.env.NODE_ENV === 'test') {
176176
let mainWindow;
177177

178178
// only set up sentry if dsn is provided
179-
const { SENTRY_DSN, GOOGLE_ANALYTICS_ID } = process.env;
179+
const { SENTRY_DSN, GOOGLE_ANALYTICS_ID, CI } = process.env;
180180
if (SENTRY_DSN) {
181181
Sentry.init({ dsn: SENTRY_DSN });
182182
}
@@ -202,7 +202,7 @@ const createWindow = () => {
202202
});
203203

204204
mainWindow.loadURL(
205-
isDev || process.env.NODE_ENV === 'test'
205+
CI !== 'true' && (isDev || process.env.NODE_ENV === 'test')
206206
? 'http://localhost:3000'
207207
: `file://${path.join(__dirname, './index.html')}`
208208
);

scripts/setup.js

+2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ const {
99
GOOGLE_API_KEY = '',
1010
GOOGLE_ANALYTICS_ID = '',
1111
LOGGING_LEVEL = 'info',
12+
SHOW_NOTIFICATIONS = false,
1213
} = process.env;
1314

1415
const env = JSON.stringify({
1516
SENTRY_DSN,
1617
GOOGLE_API_KEY,
1718
GOOGLE_ANALYTICS_ID,
1819
LOGGING_LEVEL,
20+
SHOW_NOTIFICATIONS,
1921
});
2022

2123
fs.writeFileSync(path.join(DEFAULT_PATH, NAME), env, { encoding: 'utf8' });

src/config/constants.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
export const PRODUCT_NAME = 'Graasp';
22

3+
export const NOTIFICATIONS_TYPES = {
4+
TOASTR: 'toastr',
5+
};
6+
7+
export const SHOW_NOTIFICATIONS =
8+
process?.env?.REACT_APP_SHOW_NOTIFICATIONS || false;
9+
310
// phase item types
411
export const TEXT = 'text/html';
512
export const PDF = 'application/pdf';
@@ -64,11 +71,11 @@ export const SYNC_CHANGES = {
6471
UPDATED: 'updated',
6572
};
6673

67-
const DIFF_COLORS = {
74+
export const DIFF_COLORS = {
6875
[SYNC_CHANGES.ADDED]: '#ddffde',
6976
[SYNC_CHANGES.REMOVED]: '#fddedb',
7077
[SYNC_CHANGES.UPDATED]: '#f9edc5',
71-
[SYNC_CHANGES.MOVED]: 'lightgrey',
78+
[SYNC_CHANGES.MOVED]: '#d3d3d3',
7279
};
7380

7481
export const DIFF_STYLES = {

src/index.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'react-quill/dist/quill.core.css';
1515
import App from './App';
1616
import configureStore from './store/configure';
1717
import { ROOT_ID } from './config/selectors';
18+
import { NOTIFICATIONS_TYPES, SHOW_NOTIFICATIONS } from './config/constants';
1819

1920
// bind katex to the window object
2021
window.katex = katex;
@@ -42,11 +43,13 @@ ReactDOM.render(
4243
<Detector
4344
render={({ online }) => (
4445
<>
45-
<ReduxToastr
46-
transitionIn="fadeIn"
47-
preventDuplicates
48-
transitionOut="fadeOut"
49-
/>
46+
{SHOW_NOTIFICATIONS === NOTIFICATIONS_TYPES.TOASTR && (
47+
<ReduxToastr
48+
transitionIn="fadeIn"
49+
preventDuplicates
50+
transitionOut="fadeOut"
51+
/>
52+
)}
5053
<App connexionStatus={online} />
5154
</>
5255
)}

test/application.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import electronPath from 'electron'; // Require Electron from the binaries inclu
33
import path from 'path';
44
import fse from 'fs-extra';
55
import extract from 'extract-zip';
6-
import { buildSignedInUserForDatabase } from './utils';
6+
import { buildSignedInUserForDatabase, prepareSpaceForApi } from './utils';
77

88
const getFormattedTime = () => {
99
const today = new Date();
@@ -71,6 +71,7 @@ const createApplication = async ({
7171
showOpenDialogResponse: undefined,
7272
showTours: 0,
7373
},
74+
api = [],
7475
} = {}) => {
7576
const {
7677
showMessageDialogResponse,
@@ -92,9 +93,21 @@ const createApplication = async ({
9293
env.SHOW_OPEN_DIALOG_RESPONSE = showOpenDialogResponse;
9394
}
9495

96+
// mock spaces fetch using the api
97+
// when not defined, provide default api database
98+
env.API_DATABASE = JSON.stringify(
99+
api.map((space) => prepareSpaceForApi(space))
100+
);
101+
95102
// set up database
96103
const tmpDatabasePath = await setUpDatabase(database);
97104

105+
// locally use the public electron application
106+
// for CI use the build application
107+
const applicationPath = process.env.CI
108+
? path.join(__dirname, '../build/electron.js')
109+
: path.join(__dirname, '../public/electron.js');
110+
98111
const app = new Application({
99112
// Your electron path can be any binary
100113
// i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp'
@@ -114,7 +127,7 @@ const createApplication = async ({
114127

115128
// The following line tells spectron to look and use the main.js file
116129
// and the package.json located 1 level above.
117-
args: [path.join(__dirname, '../public/electron.js')],
130+
args: [applicationPath],
118131
// use a specific application folder and var folder to save data
119132
chromeDriverArgs: [`--user-data-dir=${tmpDatabasePath}`],
120133
env,

test/classrooms.test.js

-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import {
5959
DELETE_CLASSROOM_PAUSE,
6060
DELETE_USER_IN_CLASSROOM_PAUSE,
6161
OPEN_CLASSROOM_PAUSE,
62-
TOOLTIP_FADE_OUT_PAUSE,
6362
LOAD_SELECTION_SPACE_PAUSE,
6463
} from './constants';
6564
import {
@@ -561,7 +560,6 @@ describe('Classrooms Scenarios', function () {
561560
// delete user in first classroom
562561
await openClassroom(client, name);
563562
await deleteUserInClassroom(client, newName);
564-
await client.pause(TOOLTIP_FADE_OUT_PAUSE);
565563
await hasStudentsTableLayout(
566564
client,
567565
[],

test/constants.js

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const APPS_FOLDER = 'apps';
55

66
export const DEFAULT_GLOBAL_TIMEOUT = 270000;
77
export const SAVE_USER_INPUT_TIMEOUT = 370000;
8-
export const TOOLTIP_FADE_OUT_PAUSE = 10000;
98
export const INPUT_TYPE_PAUSE = 2000;
109
export const VISIT_SPACE_PAUSE = 5000;
1110
export const OPEN_SAVED_SPACE_PAUSE = 2000;

0 commit comments

Comments
 (0)