Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit 1a621f5

Browse files
authored
Merge pull request #760 from skaut/frontend-e2e-tests
Frontend e2e tests
2 parents 14e58f8 + 4d7e0da commit 1a621f5

31 files changed

+18402
-25297
lines changed

.eslintrc.json

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"parserOptions": {
33
"parser": "@typescript-eslint/parser",
4-
"project": "./tsconfig.json",
4+
"project": ["./tsconfig.json", "./cypress/tsconfig.json"],
55
"extraFileExtensions": [".svelte"]
66
},
77
"env": {
88
"browser": true,
99
"node": false
1010
},
11-
"plugins": ["deprecation", "jest", "simple-import-sort", "@typescript-eslint"],
11+
"plugins": ["deprecation", "cypress", "jest", "simple-import-sort", "@typescript-eslint"],
1212
"extends": [
1313
"eslint:recommended",
1414
"plugin:@typescript-eslint/recommended",
@@ -109,6 +109,7 @@
109109
"gulpfile.js",
110110
"backend.webpack.config.js",
111111
"frontend.webpack.config.js",
112+
"test.frontend.webpack.config.js",
112113
".eslintrc.js"
113114
],
114115
"rules": {
@@ -150,7 +151,10 @@
150151
}
151152
},
152153
{
153-
"files": ["__tests__/**/*.test.ts"],
154+
"files": [
155+
"__tests__/**/*.test.ts",
156+
"__tests__/test-utils/gas-stubs.ts"
157+
],
154158
"extends": ["plugin:jest/recommended", "plugin:jest/style"],
155159
"rules": {
156160
"jest/consistent-test-it": ["error", { "withinDescribe": "test" }],
@@ -174,6 +178,18 @@
174178
"jest/require-to-throw-message": "error",
175179
"jest/unbound-method": "error"
176180
}
181+
},
182+
{
183+
"files": [
184+
"__tests__/frontend/**/*.cy.ts",
185+
"__tests__/test-utils/stubEndpoints.ts"
186+
],
187+
"extends": ["plugin:cypress/recommended"],
188+
"rules": {
189+
"cypress/no-force": "error",
190+
"cypress/assertion-before-screenshot": "error",
191+
"cypress/no-pause": "error"
192+
}
177193
}
178194
],
179195
"globals": {

.github/workflows/CI.yml

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ jobs:
6161
run: |
6262
npm run lint
6363
64-
test:
65-
name: "Test"
64+
backend-test:
65+
name: "Backend test"
6666
runs-on: ubuntu-latest
6767
steps:
6868
- name: "Checkout"
@@ -84,7 +84,39 @@ jobs:
8484
8585
- name: "Run tests"
8686
run: |
87-
npm test
87+
npm run test:backend
8888
8989
- name: "Upload coverage results"
9090
uses: codecov/[email protected]
91+
with:
92+
flags: backend
93+
94+
frontend-test:
95+
name: "Frontend test"
96+
runs-on: ubuntu-latest
97+
steps:
98+
- name: "Checkout"
99+
uses: actions/[email protected]
100+
101+
- name: "Cache NPM dependencies"
102+
uses: actions/[email protected]
103+
with:
104+
path: "~/.npm"
105+
key: npm-dependencies-${{ runner.os }}-${{ env.cache-version }}-${{ hashFiles('package.json') }}
106+
restore-keys: |
107+
npm-dependencies-${{ runner.os }}-${{ env.cache-version }}-${{ hashFiles('package.json') }}
108+
npm-dependencies-${{ runner.os }}-${{ env.cache-version }}-
109+
npm-dependencies-${{ runner.os }}-
110+
111+
- name: "Install NPM dependencies"
112+
run: |
113+
npm ci
114+
115+
- name: "Run tests"
116+
run: |
117+
npm run test:frontend
118+
119+
- name: "Upload coverage results"
120+
uses: codecov/[email protected]
121+
with:
122+
flags: frontend

__tests__/frontend/basic.cy.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
const stubs = stubEndpoints({
4+
listFolders: (successHandler) => {
5+
successHandler({ status: "success", response: [] });
6+
},
7+
listSharedDrives: (successHandler) => {
8+
successHandler({ status: "success", response: [] });
9+
},
10+
move: (successHandler) => {
11+
setTimeout(() => {
12+
successHandler({ status: "success", response: { errors: [] } });
13+
}, 100);
14+
},
15+
});
16+
17+
it("works with basic configuration", () => {
18+
cy.visit("http://localhost:8080");
19+
cy.contains("Shared drive mover");
20+
cy.contains("Continue").click();
21+
cy.contains("My Drive").click();
22+
cy.contains("Continue").click();
23+
cy.contains("My Drive").click();
24+
cy.contains("Continue").click();
25+
cy.contains('contents of the folder "My Drive" into the folder "My Drive"');
26+
cy.contains("Move").click();
27+
cy.contains("Done!");
28+
cy.contains("Successfully moved").then(() => {
29+
expect(stubs.move).to.have.been.calledOnceWith(
30+
"root",
31+
"root",
32+
true,
33+
true,
34+
false
35+
);
36+
});
37+
});
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
const stubs = stubEndpoints({
4+
listFolders: (successHandler) => {
5+
successHandler({ status: "success", response: [] });
6+
},
7+
listSharedDrives: (successHandler) => {
8+
successHandler({ status: "success", response: [] });
9+
},
10+
move: (successHandler) => {
11+
setTimeout(() => {
12+
successHandler({ status: "success", response: { errors: [] } });
13+
}, 100);
14+
},
15+
});
16+
17+
it("works with copy configuration", () => {
18+
cy.visit("http://localhost:8080");
19+
cy.contains("Shared drive mover");
20+
cy.contains("Copy comments").click();
21+
cy.contains("Continue").click();
22+
cy.contains("My Drive").click();
23+
cy.contains("Continue").click();
24+
cy.contains("My Drive").click();
25+
cy.contains("Continue").click();
26+
cy.contains('contents of the folder "My Drive" into the folder "My Drive"');
27+
cy.contains("Move").click();
28+
cy.contains("Done!");
29+
cy.contains("Successfully moved").then(() => {
30+
expect(stubs.move).to.have.been.calledOnceWith(
31+
"root",
32+
"root",
33+
false,
34+
true,
35+
false
36+
);
37+
});
38+
});
39+
40+
it("works with merge configuration", () => {
41+
cy.visit("http://localhost:8080");
42+
cy.contains("Shared drive mover");
43+
cy.contains("Copy comments").click();
44+
cy.contains("Continue").click();
45+
cy.contains("My Drive").click();
46+
cy.contains("Continue").click();
47+
cy.contains("My Drive").click();
48+
cy.contains("Continue").click();
49+
cy.contains('contents of the folder "My Drive" into the folder "My Drive"');
50+
cy.contains("Move").click();
51+
cy.contains("Done!");
52+
cy.contains("Successfully moved").then(() => {
53+
expect(stubs.move).to.have.been.calledOnceWith(
54+
"root",
55+
"root",
56+
false,
57+
true,
58+
false
59+
);
60+
});
61+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
stubEndpoints({
4+
listFolders: (successHandler) => {
5+
setTimeout(() => {
6+
successHandler({ status: "error", type: "DriveAPIError" });
7+
}, 100);
8+
},
9+
listSharedDrives: (successHandler) => {
10+
successHandler({
11+
status: "success",
12+
response: [
13+
{ id: "ID_DRIVE_1", name: "DRIVE 1" },
14+
{ id: "ID_DRIVE_2", name: "DRIVE 2" },
15+
],
16+
});
17+
},
18+
});
19+
20+
it("handles raw errors in source folder selection gracefully", () => {
21+
cy.visit("http://localhost:8080");
22+
cy.contains("Shared drive mover");
23+
cy.contains("Continue").click();
24+
cy.contains("DRIVE 1").click();
25+
cy.contains("Continue").click();
26+
cy.contains("DRIVE 2").dblclick();
27+
cy.contains("An error occurred").should("be.visible");
28+
cy.contains("An error occurred in Google Drive").should("be.visible");
29+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
stubEndpoints({
4+
listFolders: (_, failureHandler) => {
5+
setTimeout(() => {
6+
failureHandler(new Error("ERROR MESSAGE"));
7+
}, 100);
8+
},
9+
listSharedDrives: (successHandler) => {
10+
successHandler({
11+
status: "success",
12+
response: [
13+
{ id: "ID_DRIVE_1", name: "DRIVE 1" },
14+
{ id: "ID_DRIVE_2", name: "DRIVE 2" },
15+
],
16+
});
17+
},
18+
});
19+
20+
it("handles raw errors in source folder selection gracefully", () => {
21+
cy.visit("http://localhost:8080");
22+
cy.contains("Shared drive mover");
23+
cy.contains("Continue").click();
24+
cy.contains("DRIVE 1").click();
25+
cy.contains("Continue").click();
26+
cy.contains("DRIVE 2").dblclick();
27+
cy.contains("An error occurred").should("be.visible");
28+
cy.contains("ERROR MESSAGE");
29+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
stubEndpoints({
4+
listFolders: (successHandler) => {
5+
setTimeout(() => {
6+
successHandler({ status: "error", type: "unknown" });
7+
}, 100);
8+
},
9+
listSharedDrives: (successHandler) => {
10+
successHandler({
11+
status: "success",
12+
response: [
13+
{ id: "ID_DRIVE_1", name: "DRIVE 1" },
14+
{ id: "ID_DRIVE_2", name: "DRIVE 2" },
15+
],
16+
});
17+
},
18+
});
19+
20+
it("handles raw errors in source folder selection gracefully", () => {
21+
cy.visit("http://localhost:8080");
22+
cy.contains("Shared drive mover");
23+
cy.contains("Continue").click();
24+
cy.contains("DRIVE 1").click();
25+
cy.contains("Continue").click();
26+
cy.contains("DRIVE 2").dblclick();
27+
cy.contains("An error occurred").should("be.visible");
28+
cy.contains("An unknown error occurred").should("be.visible");
29+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
stubEndpoints({
4+
listFolders: (successHandler) => {
5+
successHandler({ status: "success", response: [] });
6+
},
7+
listSharedDrives: (successHandler) => {
8+
successHandler({ status: "success", response: [] });
9+
},
10+
move: (successHandler) => {
11+
setTimeout(() => {
12+
successHandler({ status: "error", type: "DriveAPIError" });
13+
}, 100);
14+
},
15+
});
16+
17+
it("works with an API error", () => {
18+
cy.visit("http://localhost:8080");
19+
cy.contains("Shared drive mover");
20+
cy.contains("Continue").click();
21+
cy.contains("My Drive").click();
22+
cy.contains("Continue").click();
23+
cy.contains("My Drive").click();
24+
cy.contains("Continue").click();
25+
cy.contains('contents of the folder "My Drive" into the folder "My Drive"');
26+
cy.contains("Move").click();
27+
cy.contains("Confirmation");
28+
cy.contains("An error occurred").should("be.visible");
29+
cy.contains("An error occurred in Google Drive").should("be.visible");
30+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { stubEndpoints } from "../test-utils/stubEndpoints";
2+
3+
stubEndpoints({
4+
listFolders: (successHandler) => {
5+
successHandler({ status: "success", response: [] });
6+
},
7+
listSharedDrives: (successHandler) => {
8+
successHandler({ status: "success", response: [] });
9+
},
10+
move: (successHandler) => {
11+
setTimeout(() => {
12+
successHandler({ status: "error", type: "sourceEqualsDestination" });
13+
}, 100);
14+
},
15+
});
16+
17+
it("works with source and destination folders being equal", () => {
18+
cy.visit("http://localhost:8080");
19+
cy.contains("Shared drive mover");
20+
cy.contains("Continue").click();
21+
cy.contains("My Drive").click();
22+
cy.contains("Continue").click();
23+
cy.contains("My Drive").click();
24+
cy.contains("Continue").click();
25+
cy.contains('contents of the folder "My Drive" into the folder "My Drive"');
26+
cy.contains("Move").click();
27+
cy.contains("Confirmation");
28+
cy.contains("An error occurred").should("be.visible");
29+
cy.contains("The source and destination folders must be different").should(
30+
"be.visible"
31+
);
32+
});

0 commit comments

Comments
 (0)