aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorLibravatar MCMXC <16797721+mcmxcdev@users.noreply.github.com>2024-02-10 18:37:40 -0700
committerLibravatar Vijay A <vraravam@users.noreply.github.com>2024-02-13 06:59:44 +0530
commite1c47572a6235fd8fd20af888ac3a11c7ae1369d (patch)
tree2dccff36a441916d7014037cef3f7ce84a790cad /tests
parentrefactor: project maintenance (diff)
downloadferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.tar.gz
ferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.tar.zst
ferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.zip
updates
Diffstat (limited to 'tests')
-rw-r--r--tests/bootstrap.ts29
-rw-r--r--tests/config.ts2
-rw-r--r--tests/functional/api/static/announcements.spec.ts26
-rw-r--r--tests/functional/api/static/features.spec.ts24
-rw-r--r--tests/functional/api/static/news.spec.ts14
-rw-r--r--tests/functional/api/static/services.spec.ts14
-rw-r--r--tests/functional/dashboard/account.spec.ts129
-rw-r--r--tests/functional/dashboard/data.spec.ts38
-rw-r--r--tests/functional/dashboard/delete.spec.ts49
-rw-r--r--tests/functional/dashboard/disabled-dashboard.spec.ts82
-rw-r--r--tests/functional/dashboard/export.spec.ts91
-rw-r--r--tests/functional/dashboard/forgot-password.spec.ts64
-rw-r--r--tests/functional/dashboard/import-stubs/services-workspaces.json5
-rw-r--r--tests/functional/dashboard/login.spec.ts62
-rw-r--r--tests/functional/dashboard/logout.spec.ts26
-rw-r--r--tests/functional/dashboard/reset-password.spec.ts84
-rw-r--r--tests/functional/dashboard/transfer.spec.ts200
-rw-r--r--tests/functional/health.spec.ts12
-rw-r--r--tests/functional/static-pages/home.spec.ts12
-rw-r--r--tests/functional/static-pages/privacy.spec.ts12
-rw-r--r--tests/functional/static-pages/terms.spec.ts12
-rw-r--r--tests/utils.ts4
22 files changed, 562 insertions, 429 deletions
diff --git a/tests/bootstrap.ts b/tests/bootstrap.ts
index 1c6bea1..521f718 100644
--- a/tests/bootstrap.ts
+++ b/tests/bootstrap.ts
@@ -5,10 +5,15 @@
5 * file. 5 * file.
6 */ 6 */
7 7
8import type { Config } from '@japa/runner' 8import type { Config } from '@japa/runner';
9import TestUtils from '@ioc:Adonis/Core/TestUtils' 9import TestUtils from '@ioc:Adonis/Core/TestUtils';
10import { assert, runFailedTests, specReporter, apiClient } from '@japa/preset-adonis' 10import {
11import { fakeCsrfField } from './utils.js' 11 assert,
12 runFailedTests,
13 specReporter,
14 apiClient,
15} from '@japa/preset-adonis';
16import { fakeCsrfField } from './utils.js';
12 17
13/* 18/*
14|-------------------------------------------------------------------------- 19|--------------------------------------------------------------------------
@@ -21,7 +26,11 @@ import { fakeCsrfField } from './utils.js'
21| Feel free to remove existing plugins or add more. 26| Feel free to remove existing plugins or add more.
22| 27|
23*/ 28*/
24export const plugins: Config['plugins'] = [assert(), runFailedTests(), apiClient()] 29export const plugins: Config['plugins'] = [
30 assert(),
31 runFailedTests(),
32 apiClient(),
33];
25 34
26/* 35/*
27|-------------------------------------------------------------------------- 36|--------------------------------------------------------------------------
@@ -33,7 +42,7 @@ export const plugins: Config['plugins'] = [assert(), runFailedTests(), apiClient
33| of tests on the terminal. 42| of tests on the terminal.
34| 43|
35*/ 44*/
36export const reporters: Config['reporters'] = [specReporter()] 45export const reporters: Config['reporters'] = [specReporter()];
37 46
38/* 47/*
39|-------------------------------------------------------------------------- 48|--------------------------------------------------------------------------
@@ -54,7 +63,7 @@ export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
54 () => fakeCsrfField(), 63 () => fakeCsrfField(),
55 ], 64 ],
56 teardown: [], 65 teardown: [],
57} 66};
58 67
59/* 68/*
60|-------------------------------------------------------------------------- 69|--------------------------------------------------------------------------
@@ -67,8 +76,8 @@ export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
67| You can use this method to configure suites. For example: Only start 76| You can use this method to configure suites. For example: Only start
68| the HTTP server when it is a functional suite. 77| the HTTP server when it is a functional suite.
69*/ 78*/
70export const configureSuite: Config['configureSuite'] = (suite) => { 79export const configureSuite: Config['configureSuite'] = suite => {
71 if (suite.name === 'functional') { 80 if (suite.name === 'functional') {
72 suite.setup(() => TestUtils.httpServer().start()) 81 suite.setup(() => TestUtils.httpServer().start());
73 } 82 }
74} 83};
diff --git a/tests/config.ts b/tests/config.ts
index f40284e..8cd3511 100644
--- a/tests/config.ts
+++ b/tests/config.ts
@@ -1 +1 @@
export const apiVersion = 'v1' export const apiVersion = 'v1';
diff --git a/tests/functional/api/static/announcements.spec.ts b/tests/functional/api/static/announcements.spec.ts
index 45881ec..8a74ca7 100644
--- a/tests/functional/api/static/announcements.spec.ts
+++ b/tests/functional/api/static/announcements.spec.ts
@@ -1,20 +1,22 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import { apiVersion } from '../../../config.js' 2import { apiVersion } from '../../../config.js';
3 3
4test.group('API / Static / News', () => { 4test.group('API / Static / News', () => {
5 test('returns a 404 response when the requested versions does not exist', async ({ client }) => { 5 test('returns a 404 response when the requested versions does not exist', async ({
6 const response = await client.get(`/${apiVersion}/announcements/illegal`) 6 client,
7 }) => {
8 const response = await client.get(`/${apiVersion}/announcements/illegal`);
7 9
8 response.assertStatus(404) 10 response.assertStatus(404);
9 response.assertTextIncludes('No announcement found.') 11 response.assertTextIncludes('No announcement found.');
10 }) 12 });
11 13
12 test('returns a 200 response with default version file when specifying version as input', async ({ 14 test('returns a 200 response with default version file when specifying version as input', async ({
13 client, 15 client,
14 }) => { 16 }) => {
15 const response = await client.get(`/${apiVersion}/announcements/version`) 17 const response = await client.get(`/${apiVersion}/announcements/version`);
16 18
17 response.assertStatus(200) 19 response.assertStatus(200);
18 response.assertBody({ 20 response.assertBody({
19 main: { 21 main: {
20 headline: 'Example Announcement', 22 headline: 'Example Announcement',
@@ -48,6 +50,6 @@ test.group('API / Static / News', () => {
48 }, 50 },
49 }, 51 },
50 }, 52 },
51 }) 53 });
52 }) 54 });
53}) 55});
diff --git a/tests/functional/api/static/features.spec.ts b/tests/functional/api/static/features.spec.ts
index c31e25f..a7a1e09 100644
--- a/tests/functional/api/static/features.spec.ts
+++ b/tests/functional/api/static/features.spec.ts
@@ -1,5 +1,5 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import { apiVersion } from '../../../config.js' 2import { apiVersion } from '../../../config.js';
3 3
4const defaultResponse = { 4const defaultResponse = {
5 isServiceProxyEnabled: true, 5 isServiceProxyEnabled: true,
@@ -8,22 +8,22 @@ const defaultResponse = {
8 isSettingsWSEnabled: false, 8 isSettingsWSEnabled: false,
9 isMagicBarEnabled: true, 9 isMagicBarEnabled: true,
10 isTodosEnabled: true, 10 isTodosEnabled: true,
11} 11};
12 12
13test.group('API / Static / Features', () => { 13test.group('API / Static / Features', () => {
14 test('returns a 200 response with empty array', async ({ client }) => { 14 test('returns a 200 response with empty array', async ({ client }) => {
15 const response = await client.get(`/${apiVersion}/features`) 15 const response = await client.get(`/${apiVersion}/features`);
16 16
17 response.assertStatus(200) 17 response.assertStatus(200);
18 response.assertBody(defaultResponse) 18 response.assertBody(defaultResponse);
19 }) 19 });
20 20
21 test('returns a 200 response with expected object when calling with :mode', async ({ 21 test('returns a 200 response with expected object when calling with :mode', async ({
22 client, 22 client,
23 }) => { 23 }) => {
24 const response = await client.get(`/${apiVersion}/features/random`) 24 const response = await client.get(`/${apiVersion}/features/random`);
25 25
26 response.assertStatus(200) 26 response.assertStatus(200);
27 response.assertBody(defaultResponse) 27 response.assertBody(defaultResponse);
28 }) 28 });
29}) 29});
diff --git a/tests/functional/api/static/news.spec.ts b/tests/functional/api/static/news.spec.ts
index 71b5797..28ca64e 100644
--- a/tests/functional/api/static/news.spec.ts
+++ b/tests/functional/api/static/news.spec.ts
@@ -1,11 +1,11 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import { apiVersion } from '../../../config.js' 2import { apiVersion } from '../../../config.js';
3 3
4test.group('API / Static / News', () => { 4test.group('API / Static / News', () => {
5 test('returns a 200 response with empty array', async ({ client }) => { 5 test('returns a 200 response with empty array', async ({ client }) => {
6 const response = await client.get(`/${apiVersion}/news`) 6 const response = await client.get(`/${apiVersion}/news`);
7 7
8 response.assertStatus(200) 8 response.assertStatus(200);
9 response.assertBody([]) 9 response.assertBody([]);
10 }) 10 });
11}) 11});
diff --git a/tests/functional/api/static/services.spec.ts b/tests/functional/api/static/services.spec.ts
index 595b8dc..109757e 100644
--- a/tests/functional/api/static/services.spec.ts
+++ b/tests/functional/api/static/services.spec.ts
@@ -1,11 +1,11 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import { apiVersion } from '../../../config.js' 2import { apiVersion } from '../../../config.js';
3 3
4test.group('API / Static / Services', () => { 4test.group('API / Static / Services', () => {
5 test('returns a 200 response with empty array', async ({ client }) => { 5 test('returns a 200 response with empty array', async ({ client }) => {
6 const response = await client.get(`/${apiVersion}/services`) 6 const response = await client.get(`/${apiVersion}/services`);
7 7
8 response.assertStatus(200) 8 response.assertStatus(200);
9 response.assertBody([]) 9 response.assertBody([]);
10 }) 10 });
11}) 11});
diff --git a/tests/functional/dashboard/account.spec.ts b/tests/functional/dashboard/account.spec.ts
index 25de22c..c5ede13 100644
--- a/tests/functional/dashboard/account.spec.ts
+++ b/tests/functional/dashboard/account.spec.ts
@@ -1,109 +1,124 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import User from '#app/Models/User' 2import User from '#app/Models/User';
3import UserFactory from '#database/factories/UserFactory' 3import UserFactory from '#database/factories/UserFactory';
4 4
5test.group('Dashboard / Account page', () => { 5test.group('Dashboard / Account page', () => {
6 test('redirects to /user/login when accessing /user/account as guest', async ({ client }) => { 6 test('redirects to /user/login when accessing /user/account as guest', async ({
7 const response = await client.get('/user/account') 7 client,
8 }) => {
9 const response = await client.get('/user/account');
8 10
9 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 11 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
10 }) 12 });
11 13
12 test('returns a 200 opening the account route while logged in', async ({ client }) => { 14 test('returns a 200 opening the account route while logged in', async ({
13 const user = await UserFactory.create() 15 client,
14 const response = await client.get('/user/account').loginAs(user) 16 }) => {
17 const user = await UserFactory.create();
18 const response = await client.get('/user/account').loginAs(user);
15 19
16 response.assertStatus(200) 20 response.assertStatus(200);
17 response.assertTextIncludes('Your Ferdium account') 21 response.assertTextIncludes('Your Ferdium account');
18 22
19 response.assertTextIncludes(user.email) 23 response.assertTextIncludes(user.email);
20 response.assertTextIncludes(user.username) 24 response.assertTextIncludes(user.username);
21 response.assertTextIncludes(user.lastname) 25 response.assertTextIncludes(user.lastname);
22 }) 26 });
23 27
24 test('returns a validation error for all fields when missing', async ({ client }) => { 28 test('returns a validation error for all fields when missing', async ({
25 const user = await UserFactory.create() 29 client,
26 const response = await client.post('/user/account').loginAs(user) 30 }) => {
31 const user = await UserFactory.create();
32 const response = await client.post('/user/account').loginAs(user);
27 33
28 response.assertTextIncludes( 34 response.assertTextIncludes(
29 'value="required validation failed,required validation failed" placeholder="E-Mail"' 35 'value="required validation failed,required validation failed" placeholder="E-Mail"',
30 ) 36 );
31 response.assertTextIncludes( 37 response.assertTextIncludes(
32 'value="required validation failed,required validation failed" placeholder="Name"' 38 'value="required validation failed,required validation failed" placeholder="Name"',
33 ) 39 );
34 response.assertTextIncludes( 40 response.assertTextIncludes(
35 'value="required validation failed,required validation failed" placeholder="Last Name"' 41 'value="required validation failed,required validation failed" placeholder="Last Name"',
36 ) 42 );
37 }) 43 });
38 44
39 test('returns a validation error for username when there is another user with same username', async ({ 45 test('returns a validation error for username when there is another user with same username', async ({
40 client, 46 client,
41 }) => { 47 }) => {
42 const user = await UserFactory.create() 48 const user = await UserFactory.create();
43 const existingUser = await UserFactory.create() 49 const existingUser = await UserFactory.create();
44 50
45 const response = await client.post('/user/account').loginAs(user).form({ 51 const response = await client.post('/user/account').loginAs(user).form({
46 username: existingUser.username, 52 username: existingUser.username,
47 email: user.email, 53 email: user.email,
48 lastname: user.lastname, 54 lastname: user.lastname,
49 }) 55 });
50 56
51 response.assertTextIncludes('value="unique validation failure" placeholder="Name"') 57 response.assertTextIncludes(
52 }) 58 'value="unique validation failure" placeholder="Name"',
59 );
60 });
53 61
54 test('returns a validation error for email when there is another user with same email', async ({ 62 test('returns a validation error for email when there is another user with same email', async ({
55 client, 63 client,
56 }) => { 64 }) => {
57 const user = await UserFactory.create() 65 const user = await UserFactory.create();
58 const existingUser = await UserFactory.create() 66 const existingUser = await UserFactory.create();
59 67
60 const response = await client.post('/user/account').loginAs(user).form({ 68 const response = await client.post('/user/account').loginAs(user).form({
61 username: user.username, 69 username: user.username,
62 email: existingUser.email, 70 email: existingUser.email,
63 lastname: user.lastname, 71 lastname: user.lastname,
64 }) 72 });
65 73
66 response.assertTextIncludes('value="unique validation failure" placeholder="E-Mail"') 74 response.assertTextIncludes(
67 }) 75 'value="unique validation failure" placeholder="E-Mail"',
76 );
77 });
68 78
69 test('updates user data and ensures the data is persisted', async ({ client, assert }) => { 79 test('updates user data and ensures the data is persisted', async ({
70 const user = await UserFactory.create() 80 client,
81 assert,
82 }) => {
83 const user = await UserFactory.create();
71 const response = await client.post('/user/account').loginAs(user).form({ 84 const response = await client.post('/user/account').loginAs(user).form({
72 username: 'edited-username', 85 username: 'edited-username',
73 email: 'edited-email', 86 email: 'edited-email',
74 lastname: 'edited-lastname', 87 lastname: 'edited-lastname',
75 }) 88 });
76 89
77 response.assertStatus(200) 90 response.assertStatus(200);
78 91
79 // Ensure updated data is displayed on account page 92 // Ensure updated data is displayed on account page
80 response.assertTextIncludes('edited-username') 93 response.assertTextIncludes('edited-username');
81 response.assertTextIncludes('edited-email') 94 response.assertTextIncludes('edited-email');
82 response.assertTextIncludes('edited-lastname') 95 response.assertTextIncludes('edited-lastname');
83 96
84 // Ensure updated data is persisted in database 97 // Ensure updated data is persisted in database
85 const updatedUser = await User.findBy('id', user.id) 98 const updatedUser = await User.findBy('id', user.id);
86 assert.equal(updatedUser?.username, 'edited-username') 99 assert.equal(updatedUser?.username, 'edited-username');
87 assert.equal(updatedUser?.email, 'edited-email') 100 assert.equal(updatedUser?.email, 'edited-email');
88 assert.equal(updatedUser?.lastname, 'edited-lastname') 101 assert.equal(updatedUser?.lastname, 'edited-lastname');
89 }) 102 });
90 103
91 test('updates user password and ensures the user can still login', async ({ client }) => { 104 test('updates user password and ensures the user can still login', async ({
92 const user = await UserFactory.create() 105 client,
106 }) => {
107 const user = await UserFactory.create();
93 const response = await client.post('/user/account').loginAs(user).form({ 108 const response = await client.post('/user/account').loginAs(user).form({
94 username: user.username, 109 username: user.username,
95 email: user.email, 110 email: user.email,
96 lastname: user.lastname, 111 lastname: user.lastname,
97 password: 'modified-password-account-page', 112 password: 'modified-password-account-page',
98 }) 113 });
99 114
100 response.assertStatus(200) 115 response.assertStatus(200);
101 116
102 const loginResponse = await client.post('/user/login').fields({ 117 const loginResponse = await client.post('/user/login').fields({
103 mail: user.email, 118 mail: user.email,
104 password: 'modified-password-account-page', 119 password: 'modified-password-account-page',
105 }) 120 });
106 121
107 loginResponse.assertRedirectsTo('/user/account') 122 loginResponse.assertRedirectsTo('/user/account');
108 }) 123 });
109}) 124});
diff --git a/tests/functional/dashboard/data.spec.ts b/tests/functional/dashboard/data.spec.ts
index 150229a..edca3ec 100644
--- a/tests/functional/dashboard/data.spec.ts
+++ b/tests/functional/dashboard/data.spec.ts
@@ -1,25 +1,31 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import UserFactory from '#database/factories/UserFactory' 2import UserFactory from '#database/factories/UserFactory';
3 3
4test.group('Dashboard / Data page', () => { 4test.group('Dashboard / Data page', () => {
5 test('redirects to /user/login when accessing /user/data as guest', async ({ client }) => { 5 test('redirects to /user/login when accessing /user/data as guest', async ({
6 const response = await client.get('/user/data') 6 client,
7 }) => {
8 const response = await client.get('/user/data');
7 9
8 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 10 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
9 }) 11 });
10 12
11 test('ensure the correct data is shown on the page', async ({ client }) => { 13 test('ensure the correct data is shown on the page', async ({ client }) => {
12 const user = await UserFactory.create() 14 const user = await UserFactory.create();
13 const response = await client.get('/user/data').loginAs(user) 15 const response = await client.get('/user/data').loginAs(user);
14 16
15 response.assertStatus(200) 17 response.assertStatus(200);
16 response.assertTextIncludes(user.email) 18 response.assertTextIncludes(user.email);
17 response.assertTextIncludes(user.username) 19 response.assertTextIncludes(user.username);
18 response.assertTextIncludes(user.lastname) 20 response.assertTextIncludes(user.lastname);
19 response.assertTextIncludes(user.created_at.toFormat('yyyy-MM-dd HH:mm:ss')) 21 response.assertTextIncludes(
20 response.assertTextIncludes(user.updated_at.toFormat('yyyy-MM-dd HH:mm:ss')) 22 user.created_at.toFormat('yyyy-MM-dd HH:mm:ss'),
21 }) 23 );
24 response.assertTextIncludes(
25 user.updated_at.toFormat('yyyy-MM-dd HH:mm:ss'),
26 );
27 });
22 28
23 // TODO: Add test to include services. 29 // TODO: Add test to include services.
24 // TODO: Add test to include workspaces. 30 // TODO: Add test to include workspaces.
25}) 31});
diff --git a/tests/functional/dashboard/delete.spec.ts b/tests/functional/dashboard/delete.spec.ts
index 9bb9f6a..be7fc61 100644
--- a/tests/functional/dashboard/delete.spec.ts
+++ b/tests/functional/dashboard/delete.spec.ts
@@ -1,30 +1,37 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import User from '#app/Models/User' 2import User from '#app/Models/User';
3import UserFactory from '#database/factories/UserFactory' 3import UserFactory from '#database/factories/UserFactory';
4 4
5test.group('Dashboard / Delete account page', () => { 5test.group('Dashboard / Delete account page', () => {
6 test('redirects to /user/login when accessing /user/delete as guest', async ({ client }) => { 6 test('redirects to /user/login when accessing /user/delete as guest', async ({
7 const response = await client.get('/user/delete') 7 client,
8 }) => {
9 const response = await client.get('/user/delete');
8 10
9 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 11 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
10 }) 12 });
11 13
12 test('returns a 200 opening the delete route while logged in', async ({ client }) => { 14 test('returns a 200 opening the delete route while logged in', async ({
13 const user = await UserFactory.create() 15 client,
14 const response = await client.get('/user/delete').loginAs(user) 16 }) => {
17 const user = await UserFactory.create();
18 const response = await client.get('/user/delete').loginAs(user);
15 19
16 response.assertStatus(200) 20 response.assertStatus(200);
17 response.assertTextIncludes('Delete your account') 21 response.assertTextIncludes('Delete your account');
18 }) 22 });
19 23
20 test('returns a 200 opening the delete route while logged in', async ({ client, assert }) => { 24 test('returns a 200 opening the delete route while logged in', async ({
21 const user = await UserFactory.create() 25 client,
22 const response = await client.post('/user/delete').loginAs(user) 26 assert,
27 }) => {
28 const user = await UserFactory.create();
29 const response = await client.post('/user/delete').loginAs(user);
23 30
24 response.assertRedirectsTo('/user/login') 31 response.assertRedirectsTo('/user/login');
25 // This asserts the session is deleted as well 32 // This asserts the session is deleted as well
26 response.assertSessionMissing('auth_web') 33 response.assertSessionMissing('auth_web');
27 34
28 assert.isNull(await User.find(user.id)) 35 assert.isNull(await User.find(user.id));
29 }) 36 });
30}) 37});
diff --git a/tests/functional/dashboard/disabled-dashboard.spec.ts b/tests/functional/dashboard/disabled-dashboard.spec.ts
index fd9600f..cc9052c 100644
--- a/tests/functional/dashboard/disabled-dashboard.spec.ts
+++ b/tests/functional/dashboard/disabled-dashboard.spec.ts
@@ -1,63 +1,71 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import Config from '@ioc:Adonis/Core/Config' 2import Config from '@ioc:Adonis/Core/Config';
3 3
4const disabledDashboardMessage = 4const disabledDashboardMessage =
5 'The user dashboard is disabled on this server\n\nIf you are the server owner, please set IS_DASHBOARD_ENABLED to true to enable the dashboard.' 5 'The user dashboard is disabled on this server\n\nIf you are the server owner, please set IS_DASHBOARD_ENABLED to true to enable the dashboard.';
6 6
7test.group('Dashboard / Disabled dashboard', (group) => { 7test.group('Dashboard / Disabled dashboard', group => {
8 group.setup(() => { 8 group.setup(() => {
9 Config.set('dashboard.enabled', false) 9 Config.set('dashboard.enabled', false);
10 }) 10 });
11 11
12 group.teardown(() => { 12 group.teardown(() => {
13 Config.set('dashboard.enabled', true) 13 Config.set('dashboard.enabled', true);
14 }) 14 });
15 15
16 test('Login page returns disabled dashboard message', async ({ client }) => { 16 test('Login page returns disabled dashboard message', async ({ client }) => {
17 const response = await client.get('/user/login') 17 const response = await client.get('/user/login');
18 18
19 response.assertTextIncludes(disabledDashboardMessage) 19 response.assertTextIncludes(disabledDashboardMessage);
20 }) 20 });
21 21
22 test('Forgot password page returns disabled dashboard message', async ({ client }) => { 22 test('Forgot password page returns disabled dashboard message', async ({
23 const response = await client.get('/user/forgot') 23 client,
24 }) => {
25 const response = await client.get('/user/forgot');
24 26
25 response.assertTextIncludes(disabledDashboardMessage) 27 response.assertTextIncludes(disabledDashboardMessage);
26 }) 28 });
27 29
28 test('Reset password page returns disabled dashboard message', async ({ client }) => { 30 test('Reset password page returns disabled dashboard message', async ({
29 const response = await client.get('/user/reset') 31 client,
32 }) => {
33 const response = await client.get('/user/reset');
30 34
31 response.assertTextIncludes(disabledDashboardMessage) 35 response.assertTextIncludes(disabledDashboardMessage);
32 }) 36 });
33 37
34 test('Account page returns disabled dashboard message', async ({ client }) => { 38 test('Account page returns disabled dashboard message', async ({
35 const response = await client.get('/user/account') 39 client,
40 }) => {
41 const response = await client.get('/user/account');
36 42
37 response.assertTextIncludes(disabledDashboardMessage) 43 response.assertTextIncludes(disabledDashboardMessage);
38 }) 44 });
39 45
40 test('Data page returns disabled dashboard message', async ({ client }) => { 46 test('Data page returns disabled dashboard message', async ({ client }) => {
41 const response = await client.get('/user/data') 47 const response = await client.get('/user/data');
42 48
43 response.assertTextIncludes(disabledDashboardMessage) 49 response.assertTextIncludes(disabledDashboardMessage);
44 }) 50 });
45 51
46 test('Export page returns disabled dashboard message', async ({ client }) => { 52 test('Export page returns disabled dashboard message', async ({ client }) => {
47 const response = await client.get('/user/export') 53 const response = await client.get('/user/export');
48 54
49 response.assertTextIncludes(disabledDashboardMessage) 55 response.assertTextIncludes(disabledDashboardMessage);
50 }) 56 });
51 57
52 test('Transfer page returns disabled dashboard message', async ({ client }) => { 58 test('Transfer page returns disabled dashboard message', async ({
53 const response = await client.get('/user/transfer') 59 client,
60 }) => {
61 const response = await client.get('/user/transfer');
54 62
55 response.assertTextIncludes(disabledDashboardMessage) 63 response.assertTextIncludes(disabledDashboardMessage);
56 }) 64 });
57 65
58 test('Logout page returns disabled dashboard message', async ({ client }) => { 66 test('Logout page returns disabled dashboard message', async ({ client }) => {
59 const response = await client.get('/user/logout') 67 const response = await client.get('/user/logout');
60 68
61 response.assertTextIncludes(disabledDashboardMessage) 69 response.assertTextIncludes(disabledDashboardMessage);
62 }) 70 });
63}) 71});
diff --git a/tests/functional/dashboard/export.spec.ts b/tests/functional/dashboard/export.spec.ts
index f85673e..767f0ef 100644
--- a/tests/functional/dashboard/export.spec.ts
+++ b/tests/functional/dashboard/export.spec.ts
@@ -1,50 +1,61 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import UserFactory from '#database/factories/UserFactory' 2import UserFactory from '#database/factories/UserFactory';
3 3
4test.group('Dashboard / Export page', () => { 4test.group('Dashboard / Export page', () => {
5 test('redirects to /user/login when accessing /user/transfer as guest', async ({ client }) => { 5 test('redirects to /user/login when accessing /user/transfer as guest', async ({
6 const response = await client.get('/user/transfer') 6 client,
7 }) => {
8 const response = await client.get('/user/transfer');
7 9
8 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 10 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
9 }) 11 });
10 12
11 test('returns a correct export with user data', async ({ assert, client }) => { 13 test('returns a correct export with user data', async ({
12 const user = await UserFactory.create() 14 assert,
13 const response = await client.get('/user/export').loginAs(user) 15 client,
16 }) => {
17 const user = await UserFactory.create();
18 const response = await client.get('/user/export').loginAs(user);
14 19
15 response.assertStatus(200) 20 response.assertStatus(200);
16 const exportData = JSON.parse(response.text()) 21 const exportData = JSON.parse(response.text());
17 22
18 assert.equal(exportData.username, user.username) 23 assert.equal(exportData.username, user.username);
19 assert.equal(exportData.lastname, user.lastname) 24 assert.equal(exportData.lastname, user.lastname);
20 assert.equal(exportData.mail, user.email) 25 assert.equal(exportData.mail, user.email);
21 }) 26 });
22 27
23 // TODO: We can improve this test by hard checking the export data 28 // TODO: We can improve this test by hard checking the export data
24 test('returns a correct export with service data', async ({ assert, client }) => { 29 test('returns a correct export with service data', async ({
25 const user = await UserFactory.with('services', 5).create() 30 assert,
26 const response = await client.get('/user/export').loginAs(user) 31 client,
27 32 }) => {
28 response.assertStatus(200) 33 const user = await UserFactory.with('services', 5).create();
29 const exportData = JSON.parse(response.text()) 34 const response = await client.get('/user/export').loginAs(user);
30 35
31 assert.equal(exportData.username, user.username) 36 response.assertStatus(200);
32 assert.equal(exportData.lastname, user.lastname) 37 const exportData = JSON.parse(response.text());
33 assert.equal(exportData.mail, user.email) 38
34 assert.equal(exportData.services.length, user.services.length) 39 assert.equal(exportData.username, user.username);
35 }) 40 assert.equal(exportData.lastname, user.lastname);
41 assert.equal(exportData.mail, user.email);
42 assert.equal(exportData.services.length, user.services.length);
43 });
36 44
37 // TODO: We can improve this test by hard checking the export data 45 // TODO: We can improve this test by hard checking the export data
38 test('returns a correct export with workspace data', async ({ assert, client }) => { 46 test('returns a correct export with workspace data', async ({
39 const user = await UserFactory.with('workspaces', 5).create() 47 assert,
40 const response = await client.get('/user/export').loginAs(user) 48 client,
41 49 }) => {
42 response.assertStatus(200) 50 const user = await UserFactory.with('workspaces', 5).create();
43 const exportData = JSON.parse(response.text()) 51 const response = await client.get('/user/export').loginAs(user);
44 52
45 assert.equal(exportData.username, user.username) 53 response.assertStatus(200);
46 assert.equal(exportData.lastname, user.lastname) 54 const exportData = JSON.parse(response.text());
47 assert.equal(exportData.mail, user.email) 55
48 assert.equal(exportData.workspaces.length, user.workspaces.length) 56 assert.equal(exportData.username, user.username);
49 }) 57 assert.equal(exportData.lastname, user.lastname);
50}) 58 assert.equal(exportData.mail, user.email);
59 assert.equal(exportData.workspaces.length, user.workspaces.length);
60 });
61});
diff --git a/tests/functional/dashboard/forgot-password.spec.ts b/tests/functional/dashboard/forgot-password.spec.ts
index 7c356c8..82004ac 100644
--- a/tests/functional/dashboard/forgot-password.spec.ts
+++ b/tests/functional/dashboard/forgot-password.spec.ts
@@ -1,66 +1,70 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import emitter from '@adonisjs/core/services/emitter' 2import emitter from '@adonisjs/core/services/emitter';
3import UserFactory from '#database/factories/UserFactory' 3import UserFactory from '#database/factories/UserFactory';
4 4
5test.group('Dashboard / Forgot password page', () => { 5test.group('Dashboard / Forgot password page', () => {
6 test('returns a 200 opening the forgot password route', async ({ client }) => { 6 test('returns a 200 opening the forgot password route', async ({
7 const response = await client.get('/user/forgot') 7 client,
8 }) => {
9 const response = await client.get('/user/forgot');
8 10
9 response.assertStatus(200) 11 response.assertStatus(200);
10 response.assertTextIncludes('Forgot Password?') 12 response.assertTextIncludes('Forgot Password?');
11 }) 13 });
12 14
13 test('returns `Please enter a valid email address` when providing invalid email', async ({ 15 test('returns `Please enter a valid email address` when providing invalid email', async ({
14 client, 16 client,
15 }) => { 17 }) => {
16 const response = await client.post('/user/forgot').fields({ 18 const response = await client.post('/user/forgot').fields({
17 mail: 'invalid', 19 mail: 'invalid',
18 }) 20 });
19 21
20 response.assertStatus(200) 22 response.assertStatus(200);
21 response.assertTextIncludes('Please enter a valid email address') 23 response.assertTextIncludes('Please enter a valid email address');
22 }) 24 });
23 25
24 test('returns `email send when exists` without forgot:password event', async ({ 26 test('returns `email send when exists` without forgot:password event', async ({
25 client, 27 client,
26 assert, 28 assert,
27 }) => { 29 }) => {
28 const emitterService = emitter.fake() 30 const emitterService = emitter.fake();
29 31
30 const response = await client.post('/user/forgot').fields({ 32 const response = await client.post('/user/forgot').fields({
31 mail: 'test@ferdium.org', 33 mail: 'test@ferdium.org',
32 }) 34 });
33 35
34 response.assertStatus(200) 36 response.assertStatus(200);
35 response.assertTextIncludes( 37 response.assertTextIncludes(
36 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.' 38 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.',
37 ) 39 );
38 40
39 assert.isFalse(emitterService.exists('forgot:password')) 41 assert.isFalse(emitterService.exists('forgot:password'));
40 }) 42 });
41 43
42 test('returns `email send when exists` and trigger forgot:password event', async ({ 44 test('returns `email send when exists` and trigger forgot:password event', async ({
43 client, 45 client,
44 assert, 46 assert,
45 }) => { 47 }) => {
46 const emitterService = emitter.fake() 48 const emitterService = emitter.fake();
47 const user = await UserFactory.merge({ 49 const user = await UserFactory.merge({
48 email: 'test+forgot_password@ferdium.org', 50 email: 'test+forgot_password@ferdium.org',
49 }).create() 51 }).create();
50 52
51 const response = await client.post('/user/forgot').fields({ 53 const response = await client.post('/user/forgot').fields({
52 mail: 'test+forgot_password@ferdium.org', 54 mail: 'test+forgot_password@ferdium.org',
53 }) 55 });
54 56
55 response.assertStatus(200) 57 response.assertStatus(200);
56 response.assertTextIncludes( 58 response.assertTextIncludes(
57 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.' 59 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.',
58 ) 60 );
59 61
60 assert.isTrue( 62 assert.isTrue(
61 emitterService.exists( 63 emitterService.exists(
62 (event) => event.name === 'forgot:password' && event.data.user.email === user.email 64 event =>
63 ) 65 event.name === 'forgot:password' &&
64 ) 66 event.data.user.email === user.email,
65 }) 67 ),
66}) 68 );
69 });
70});
diff --git a/tests/functional/dashboard/import-stubs/services-workspaces.json b/tests/functional/dashboard/import-stubs/services-workspaces.json
index d1ad0dd..139b32c 100644
--- a/tests/functional/dashboard/import-stubs/services-workspaces.json
+++ b/tests/functional/dashboard/import-stubs/services-workspaces.json
@@ -44,7 +44,10 @@
44 { 44 {
45 "name": "workspace2", 45 "name": "workspace2",
46 "order": 0, 46 "order": 0,
47 "services": ["d6901fff-ec44-4251-93de-d7103ed9c44b", "79769de5-a998-4af1-b7d0-89956a15b0ed"], 47 "services": [
48 "d6901fff-ec44-4251-93de-d7103ed9c44b",
49 "79769de5-a998-4af1-b7d0-89956a15b0ed"
50 ],
48 "data": "{\"name\":\"workspace2\"}" 51 "data": "{\"name\":\"workspace2\"}"
49 }, 52 },
50 { 53 {
diff --git a/tests/functional/dashboard/login.spec.ts b/tests/functional/dashboard/login.spec.ts
index cf482cd..21101da 100644
--- a/tests/functional/dashboard/login.spec.ts
+++ b/tests/functional/dashboard/login.spec.ts
@@ -1,57 +1,65 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import UserFactory from '#database/factories/UserFactory' 2import UserFactory from '#database/factories/UserFactory';
3 3
4test.group('Dashboard / Login page', () => { 4test.group('Dashboard / Login page', () => {
5 test('returns a 200 opening the login route', async ({ client }) => { 5 test('returns a 200 opening the login route', async ({ client }) => {
6 const response = await client.get('/user/login') 6 const response = await client.get('/user/login');
7 7
8 response.assertStatus(200) 8 response.assertStatus(200);
9 }) 9 });
10 10
11 test('returns `invalid mail or password` when validation fails', async ({ client }) => { 11 test('returns `invalid mail or password` when validation fails', async ({
12 client,
13 }) => {
12 const response = await client.post('/user/login').fields({ 14 const response = await client.post('/user/login').fields({
13 mail: 'invalid', 15 mail: 'invalid',
14 password: 'invalid', 16 password: 'invalid',
15 }) 17 });
16 18
17 response.assertRedirectsTo('/user/login') 19 response.assertRedirectsTo('/user/login');
18 response.assertTextIncludes('Invalid mail or password') 20 response.assertTextIncludes('Invalid mail or password');
19 }) 21 });
20 22
21 test('returns `invalid mail or password` when account is not found', async ({ client }) => { 23 test('returns `invalid mail or password` when account is not found', async ({
24 client,
25 }) => {
22 const response = await client.post('/user/login').fields({ 26 const response = await client.post('/user/login').fields({
23 mail: 'test+notexistingpassword@ferdium.org', 27 mail: 'test+notexistingpassword@ferdium.org',
24 password: 'notexistingpassword', 28 password: 'notexistingpassword',
25 }) 29 });
26 30
27 response.assertRedirectsTo('/user/login') 31 response.assertRedirectsTo('/user/login');
28 response.assertTextIncludes('Invalid mail or password') 32 response.assertTextIncludes('Invalid mail or password');
29 }) 33 });
30 34
31 test('returns `invalid mail or password` when password is not valid', async ({ client }) => { 35 test('returns `invalid mail or password` when password is not valid', async ({
36 client,
37 }) => {
32 await UserFactory.merge({ 38 await UserFactory.merge({
33 email: 'test@ferdium.org', 39 email: 'test@ferdium.org',
34 }).create() 40 }).create();
35 41
36 const response = await client.post('/user/login').fields({ 42 const response = await client.post('/user/login').fields({
37 mail: 'test+invalid_password@ferdium.org', 43 mail: 'test+invalid_password@ferdium.org',
38 password: 'invalid_password', 44 password: 'invalid_password',
39 }) 45 });
40 46
41 response.assertRedirectsTo('/user/login') 47 response.assertRedirectsTo('/user/login');
42 response.assertTextIncludes('Invalid mail or password') 48 response.assertTextIncludes('Invalid mail or password');
43 }) 49 });
44 50
45 test('redirects to account page when user is able to login', async ({ client }) => { 51 test('redirects to account page when user is able to login', async ({
52 client,
53 }) => {
46 await UserFactory.merge({ 54 await UserFactory.merge({
47 email: 'test+password@ferdium.org', 55 email: 'test+password@ferdium.org',
48 }).create() 56 }).create();
49 57
50 const response = await client.post('/user/login').fields({ 58 const response = await client.post('/user/login').fields({
51 mail: 'test+password@ferdium.org', 59 mail: 'test+password@ferdium.org',
52 password: 'password', 60 password: 'password',
53 }) 61 });
54 62
55 response.assertRedirectsTo('/user/account') 63 response.assertRedirectsTo('/user/account');
56 }) 64 });
57}) 65});
diff --git a/tests/functional/dashboard/logout.spec.ts b/tests/functional/dashboard/logout.spec.ts
index ad117da..440a054 100644
--- a/tests/functional/dashboard/logout.spec.ts
+++ b/tests/functional/dashboard/logout.spec.ts
@@ -1,19 +1,21 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import UserFactory from '#database/factories/UserFactory' 2import UserFactory from '#database/factories/UserFactory';
3 3
4test.group('Dashboard / Log out page', () => { 4test.group('Dashboard / Log out page', () => {
5 test('redirects to /user/login when accessing /user/logout as guest', async ({ client }) => { 5 test('redirects to /user/login when accessing /user/logout as guest', async ({
6 const response = await client.get('/user/logout') 6 client,
7 }) => {
8 const response = await client.get('/user/logout');
7 9
8 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 10 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
9 }) 11 });
10 12
11 test('logs the user out when opening the page', async ({ client }) => { 13 test('logs the user out when opening the page', async ({ client }) => {
12 const user = await UserFactory.create() 14 const user = await UserFactory.create();
13 const response = await client.get('/user/logout').loginAs(user) 15 const response = await client.get('/user/logout').loginAs(user);
14 16
15 response.assertRedirectsTo('/user/login') 17 response.assertRedirectsTo('/user/login');
16 // This asserts the session is deleted as well 18 // This asserts the session is deleted as well
17 response.assertSessionMissing('auth_web') 19 response.assertSessionMissing('auth_web');
18 }) 20 });
19}) 21});
diff --git a/tests/functional/dashboard/reset-password.spec.ts b/tests/functional/dashboard/reset-password.spec.ts
index 8883665..cde8808 100644
--- a/tests/functional/dashboard/reset-password.spec.ts
+++ b/tests/functional/dashboard/reset-password.spec.ts
@@ -1,22 +1,26 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import Token from '#app/Models/Token' 2import Token from '#app/Models/Token';
3import UserFactory from '#database/factories/UserFactory' 3import UserFactory from '#database/factories/UserFactory';
4import TokenFactory from '#database/factories/TokenFactory' 4import TokenFactory from '#database/factories/TokenFactory';
5 5
6test.group('Dashboard / Reset password page', () => { 6test.group('Dashboard / Reset password page', () => {
7 test('returns a `Invalid token` message when opening without a token', async ({ client }) => { 7 test('returns a `Invalid token` message when opening without a token', async ({
8 const response = await client.get('/user/reset') 8 client,
9 }) => {
10 const response = await client.get('/user/reset');
9 11
10 response.assertStatus(200) 12 response.assertStatus(200);
11 response.assertTextIncludes('Invalid token') 13 response.assertTextIncludes('Invalid token');
12 }) 14 });
13 15
14 test('displays the form when a token is provided', async ({ client }) => { 16 test('displays the form when a token is provided', async ({ client }) => {
15 const response = await client.get('/user/reset?token=randomtokenbutitworks') 17 const response = await client.get(
18 '/user/reset?token=randomtokenbutitworks',
19 );
16 20
17 response.assertStatus(200) 21 response.assertStatus(200);
18 response.assertTextIncludes('Reset Your Password') 22 response.assertTextIncludes('Reset Your Password');
19 }) 23 });
20 24
21 test('returns `passwords do not match` message when passwords do not match', async ({ 25 test('returns `passwords do not match` message when passwords do not match', async ({
22 client, 26 client,
@@ -25,20 +29,22 @@ test.group('Dashboard / Reset password page', () => {
25 token: 'randomnotworkingtoken', 29 token: 'randomnotworkingtoken',
26 password: 'password', 30 password: 'password',
27 password_confirmation: 'not_matching', 31 password_confirmation: 'not_matching',
28 }) 32 });
29 33
30 response.assertTextIncludes('Passwords do not match') 34 response.assertTextIncludes('Passwords do not match');
31 }) 35 });
32 36
33 test('returns `Cannot reset your password` when token does not exist', async ({ client }) => { 37 test('returns `Cannot reset your password` when token does not exist', async ({
38 client,
39 }) => {
34 const response = await client.post('/user/reset').fields({ 40 const response = await client.post('/user/reset').fields({
35 token: 'randomnotworkingtoken', 41 token: 'randomnotworkingtoken',
36 password: 'password', 42 password: 'password',
37 password_confirmation: 'password', 43 password_confirmation: 'password',
38 }) 44 });
39 45
40 response.assertTextIncludes('Cannot reset your password') 46 response.assertTextIncludes('Cannot reset your password');
41 }) 47 });
42 48
43 test('returns `Cannot reset your password` when token is older than 24 hours', async ({ 49 test('returns `Cannot reset your password` when token is older than 24 hours', async ({
44 client, 50 client,
@@ -48,39 +54,41 @@ test.group('Dashboard / Reset password page', () => {
48 user_id: (await UserFactory.create()).id, 54 user_id: (await UserFactory.create()).id,
49 }) 55 })
50 .apply('old_token') 56 .apply('old_token')
51 .create() 57 .create();
52 58
53 const response = await client.post('/user/reset').fields({ 59 const response = await client.post('/user/reset').fields({
54 token: token.token, 60 token: token.token,
55 password: 'password', 61 password: 'password',
56 password_confirmation: 'password', 62 password_confirmation: 'password',
57 }) 63 });
58 64
59 response.assertTextIncludes('Cannot reset your password') 65 response.assertTextIncludes('Cannot reset your password');
60 }) 66 });
61 67
62 test('returns `Cannot reset your password` when token is revoked', async ({ client }) => { 68 test('returns `Cannot reset your password` when token is revoked', async ({
69 client,
70 }) => {
63 const token = await TokenFactory.merge({ 71 const token = await TokenFactory.merge({
64 // eslint-disable-next-line unicorn/no-await-expression-member 72 // eslint-disable-next-line unicorn/no-await-expression-member
65 user_id: (await UserFactory.create()).id, 73 user_id: (await UserFactory.create()).id,
66 }) 74 })
67 .apply('revoked') 75 .apply('revoked')
68 .create() 76 .create();
69 77
70 const response = await client.post('/user/reset').fields({ 78 const response = await client.post('/user/reset').fields({
71 token: token.token, 79 token: token.token,
72 password: 'password', 80 password: 'password',
73 password_confirmation: 'password', 81 password_confirmation: 'password',
74 }) 82 });
75 83
76 response.assertTextIncludes('Cannot reset your password') 84 response.assertTextIncludes('Cannot reset your password');
77 }) 85 });
78 86
79 test('correctly resets password and deletes token and able to login with new password', async ({ 87 test('correctly resets password and deletes token and able to login with new password', async ({
80 client, 88 client,
81 assert, 89 assert,
82 }) => { 90 }) => {
83 const userEmail = 'working-reset-password-login@ferdium.org' 91 const userEmail = 'working-reset-password-login@ferdium.org';
84 const token = await TokenFactory.merge({ 92 const token = await TokenFactory.merge({
85 user_id: 93 user_id:
86 ( 94 (
@@ -90,25 +98,25 @@ test.group('Dashboard / Reset password page', () => {
90 // prettier-ignore 98 // prettier-ignore
91 // eslint-disable-next-line unicorn/no-await-expression-member 99 // eslint-disable-next-line unicorn/no-await-expression-member
92 ).id, 100 ).id,
93 }).create() 101 }).create();
94 102
95 const response = await client.post('/user/reset').fields({ 103 const response = await client.post('/user/reset').fields({
96 token: token.token, 104 token: token.token,
97 password: 'new_password', 105 password: 'new_password',
98 password_confirmation: 'new_password', 106 password_confirmation: 'new_password',
99 }) 107 });
100 108
101 // Assert response is as expected 109 // Assert response is as expected
102 response.assertTextIncludes('Successfully reset your password') 110 response.assertTextIncludes('Successfully reset your password');
103 111
104 // Token should be deleted from database 112 // Token should be deleted from database
105 assert.isNull(await Token.query().where('token', token.token).first()) 113 assert.isNull(await Token.query().where('token', token.token).first());
106 114
107 const loginResponse = await client.post('/user/login').fields({ 115 const loginResponse = await client.post('/user/login').fields({
108 mail: userEmail, 116 mail: userEmail,
109 password: 'new_password', 117 password: 'new_password',
110 }) 118 });
111 119
112 loginResponse.assertRedirectsTo('/user/account') 120 loginResponse.assertRedirectsTo('/user/account');
113 }) 121 });
114}) 122});
diff --git a/tests/functional/dashboard/transfer.spec.ts b/tests/functional/dashboard/transfer.spec.ts
index 41a6709..0a07499 100644
--- a/tests/functional/dashboard/transfer.spec.ts
+++ b/tests/functional/dashboard/transfer.spec.ts
@@ -1,59 +1,80 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2import { readFileSync } from 'node:fs' 2import { readFileSync } from 'node:fs';
3import UserFactory from '#database/factories/UserFactory' 3import UserFactory from '#database/factories/UserFactory';
4 4
5test.group('Dashboard / Transfer page', () => { 5test.group('Dashboard / Transfer page', () => {
6 test('redirects to /user/login when accessing /user/transfer as guest', async ({ client }) => { 6 test('redirects to /user/login when accessing /user/transfer as guest', async ({
7 const response = await client.get('/user/transfer') 7 client,
8 }) => {
9 const response = await client.get('/user/transfer');
8 10
9 response.assertRedirectsTo('/user/login') // Check if it redirects to the expected URL 11 response.assertRedirectsTo('/user/login'); // Check if it redirects to the expected URL
10 }) 12 });
11 13
12 test('returns a 200 opening the transfer route while being logged in', async ({ client }) => { 14 test('returns a 200 opening the transfer route while being logged in', async ({
13 const user = await UserFactory.create() 15 client,
14 const response = await client.get('/user/transfer').loginAs(user) 16 }) => {
17 const user = await UserFactory.create();
18 const response = await client.get('/user/transfer').loginAs(user);
15 19
16 response.assertStatus(200) 20 response.assertStatus(200);
17 }) 21 });
18 22
19 test('returns a validation error when not uploading a file', async ({ client }) => { 23 test('returns a validation error when not uploading a file', async ({
20 const user = await UserFactory.create() 24 client,
21 const response = await client.post('/user/transfer').loginAs(user) 25 }) => {
26 const user = await UserFactory.create();
27 const response = await client.post('/user/transfer').loginAs(user);
22 28
23 response.assertTextIncludes('Invalid Ferdium account file') 29 response.assertTextIncludes('Invalid Ferdium account file');
24 }) 30 });
25 31
26 test('returns a validation error when trying to use anything but json', async ({ client }) => { 32 test('returns a validation error when trying to use anything but json', async ({
27 const user = await UserFactory.create() 33 client,
34 }) => {
35 const user = await UserFactory.create();
28 const response = await client 36 const response = await client
29 .post('/user/transfer') 37 .post('/user/transfer')
30 .loginAs(user) 38 .loginAs(user)
31 .field('file', readFileSync('tests/functional/dashboard/import-stubs/random-file.txt')) 39 .field(
40 'file',
41 readFileSync('tests/functional/dashboard/import-stubs/random-file.txt'),
42 );
32 43
33 response.assertTextIncludes('Invalid Ferdium account file') 44 response.assertTextIncludes('Invalid Ferdium account file');
34 }) 45 });
35 46
36 test('returns a validation error when trying to use anything valid json', async ({ client }) => { 47 test('returns a validation error when trying to use anything valid json', async ({
37 const user = await UserFactory.create() 48 client,
49 }) => {
50 const user = await UserFactory.create();
38 const response = await client 51 const response = await client
39 .post('/user/transfer') 52 .post('/user/transfer')
40 .loginAs(user) 53 .loginAs(user)
41 .field('file', readFileSync('tests/functional/dashboard/import-stubs/invalid.json')) 54 .field(
55 'file',
56 readFileSync('tests/functional/dashboard/import-stubs/invalid.json'),
57 );
42 58
43 response.assertTextIncludes('Invalid Ferdium account file') 59 response.assertTextIncludes('Invalid Ferdium account file');
44 }) 60 });
45 61
46 test('returns a validation error when trying to use a json file with no ferdium structure', async ({ 62 test('returns a validation error when trying to use a json file with no ferdium structure', async ({
47 client, 63 client,
48 }) => { 64 }) => {
49 const user = await UserFactory.create() 65 const user = await UserFactory.create();
50 const response = await client 66 const response = await client
51 .post('/user/transfer') 67 .post('/user/transfer')
52 .loginAs(user) 68 .loginAs(user)
53 .field('file', readFileSync('tests/functional/dashboard/import-stubs/valid-no-data.json')) 69 .field(
70 'file',
71 readFileSync(
72 'tests/functional/dashboard/import-stubs/valid-no-data.json',
73 ),
74 );
54 75
55 response.assertTextIncludes('Invalid Ferdium account file') 76 response.assertTextIncludes('Invalid Ferdium account file');
56 }) 77 });
57 78
58 test('correctly transfers data from json/ferdi-data and ferdium-data file with only workspaces', async ({ 79 test('correctly transfers data from json/ferdi-data and ferdium-data file with only workspaces', async ({
59 client, 80 client,
@@ -64,62 +85,76 @@ test.group('Dashboard / Transfer page', () => {
64 'workspaces-only.json', 85 'workspaces-only.json',
65 'workspaces-only.ferdi-data', 86 'workspaces-only.ferdi-data',
66 'workspaces-only.ferdium-data', 87 'workspaces-only.ferdium-data',
67 ] 88 ];
68 89
69 for (const file of files) { 90 for (const file of files) {
70 // eslint-disable-next-line no-await-in-loop 91 // eslint-disable-next-line no-await-in-loop
71 const user = await UserFactory.create() 92 const user = await UserFactory.create();
72 // eslint-disable-next-line no-await-in-loop 93 // eslint-disable-next-line no-await-in-loop
73 const response = await client 94 const response = await client
74 .post('/user/transfer') 95 .post('/user/transfer')
75 .loginAs(user) 96 .loginAs(user)
76 .field('file', readFileSync(`tests/functional/dashboard/import-stubs/${file}`)) 97 .field(
77 98 'file',
78 response.assertTextIncludes('Your account has been imported, you can now login as usual!') 99 readFileSync(`tests/functional/dashboard/import-stubs/${file}`),
100 );
101
102 response.assertTextIncludes(
103 'Your account has been imported, you can now login as usual!',
104 );
79 // eslint-disable-next-line no-await-in-loop 105 // eslint-disable-next-line no-await-in-loop
80 await user.refresh() 106 await user.refresh();
81 107
82 // eslint-disable-next-line no-await-in-loop 108 // eslint-disable-next-line no-await-in-loop
83 const workspacesForUser = await user.related('workspaces').query() 109 const workspacesForUser = await user.related('workspaces').query();
84 assert.equal(workspacesForUser.length, 3, file) 110 assert.equal(workspacesForUser.length, 3, file);
85 111
86 // ensure not JSON encoded twice 112 // ensure not JSON encoded twice
87 for (const workspace of workspacesForUser) { 113 for (const workspace of workspacesForUser) {
88 assert.isNull(workspace.data.match(/\\"/), file) 114 assert.isNull(workspace.data.match(/\\"/), file);
89 } 115 }
90 } 116 }
91 }) 117 });
92 118
93 test('correctly transfers data from json/ferdi-data and ferdium-data file with only services', async ({ 119 test('correctly transfers data from json/ferdi-data and ferdium-data file with only services', async ({
94 client, 120 client,
95 assert, 121 assert,
96 }) => { 122 }) => {
97 // Repeat for all 3 file extension 123 // Repeat for all 3 file extension
98 const files = ['services-only.json', 'services-only.ferdi-data', 'services-only.ferdium-data'] 124 const files = [
125 'services-only.json',
126 'services-only.ferdi-data',
127 'services-only.ferdium-data',
128 ];
99 129
100 for (const file of files) { 130 for (const file of files) {
101 // eslint-disable-next-line no-await-in-loop 131 // eslint-disable-next-line no-await-in-loop
102 const user = await UserFactory.create() 132 const user = await UserFactory.create();
103 // eslint-disable-next-line no-await-in-loop 133 // eslint-disable-next-line no-await-in-loop
104 const response = await client 134 const response = await client
105 .post('/user/transfer') 135 .post('/user/transfer')
106 .loginAs(user) 136 .loginAs(user)
107 .field('file', readFileSync(`tests/functional/dashboard/import-stubs/${file}`)) 137 .field(
108 138 'file',
109 response.assertTextIncludes('Your account has been imported, you can now login as usual!') 139 readFileSync(`tests/functional/dashboard/import-stubs/${file}`),
140 );
141
142 response.assertTextIncludes(
143 'Your account has been imported, you can now login as usual!',
144 );
110 // eslint-disable-next-line no-await-in-loop 145 // eslint-disable-next-line no-await-in-loop
111 await user.refresh() 146 await user.refresh();
112 147
113 // eslint-disable-next-line no-await-in-loop 148 // eslint-disable-next-line no-await-in-loop
114 const servicesForUser = await user.related('services').query() 149 const servicesForUser = await user.related('services').query();
115 assert.equal(servicesForUser.length, 3, file) 150 assert.equal(servicesForUser.length, 3, file);
116 151
117 // ensure not JSON encoded twice 152 // ensure not JSON encoded twice
118 for (const service of servicesForUser) { 153 for (const service of servicesForUser) {
119 assert.isNull(service.settings.match(/\\"/), file) 154 assert.isNull(service.settings.match(/\\"/), file);
120 } 155 }
121 } 156 }
122 }) 157 });
123 158
124 test('correctly transfers data from json/ferdi-data and ferdium-data file with workspaces and services', async ({ 159 test('correctly transfers data from json/ferdi-data and ferdium-data file with workspaces and services', async ({
125 client, 160 client,
@@ -130,57 +165,72 @@ test.group('Dashboard / Transfer page', () => {
130 'services-workspaces.json', 165 'services-workspaces.json',
131 'services-workspaces.ferdi-data', 166 'services-workspaces.ferdi-data',
132 'services-workspaces.ferdium-data', 167 'services-workspaces.ferdium-data',
133 ] 168 ];
134 169
135 for (const file of files) { 170 for (const file of files) {
136 // eslint-disable-next-line no-await-in-loop 171 // eslint-disable-next-line no-await-in-loop
137 const user = await UserFactory.create() 172 const user = await UserFactory.create();
138 // eslint-disable-next-line no-await-in-loop 173 // eslint-disable-next-line no-await-in-loop
139 const response = await client 174 const response = await client
140 .post('/user/transfer') 175 .post('/user/transfer')
141 .loginAs(user) 176 .loginAs(user)
142 .field('file', readFileSync(`tests/functional/dashboard/import-stubs/${file}`)) 177 .field(
143 178 'file',
144 response.assertTextIncludes('Your account has been imported, you can now login as usual!') 179 readFileSync(`tests/functional/dashboard/import-stubs/${file}`),
180 );
181
182 response.assertTextIncludes(
183 'Your account has been imported, you can now login as usual!',
184 );
145 // eslint-disable-next-line no-await-in-loop 185 // eslint-disable-next-line no-await-in-loop
146 await user.refresh() 186 await user.refresh();
147 187
148 // eslint-disable-next-line no-await-in-loop 188 // eslint-disable-next-line no-await-in-loop
149 const servicesForUser = await user.related('services').query() 189 const servicesForUser = await user.related('services').query();
150 // eslint-disable-next-line no-await-in-loop 190 // eslint-disable-next-line no-await-in-loop
151 const workspacesForUser = await user.related('workspaces').query() 191 const workspacesForUser = await user.related('workspaces').query();
152 assert.equal(servicesForUser.length, 3, file) 192 assert.equal(servicesForUser.length, 3, file);
153 assert.equal(workspacesForUser.length, 3, file) 193 assert.equal(workspacesForUser.length, 3, file);
154 194
155 const firstServiceUuid = servicesForUser.find((s) => s.name === 'random-service-1')?.serviceId 195 const firstServiceUuid = servicesForUser.find(
196 s => s.name === 'random-service-1',
197 )?.serviceId;
156 const secondServiceUuid = servicesForUser.find( 198 const secondServiceUuid = servicesForUser.find(
157 (s) => s.name === 'random-service-2' 199 s => s.name === 'random-service-2',
158 )?.serviceId 200 )?.serviceId;
159 const thirdServiceUUid = servicesForUser.find((s) => s.name === 'random-service-3')?.serviceId 201 const thirdServiceUUid = servicesForUser.find(
202 s => s.name === 'random-service-3',
203 )?.serviceId;
160 204
161 // Assert the first workspace to not have any services 205 // Assert the first workspace to not have any services
162 const firstWorkspace = workspacesForUser.find((w) => w.name === 'workspace1') 206 const firstWorkspace = workspacesForUser.find(
207 w => w.name === 'workspace1',
208 );
163 if (firstWorkspace?.services) { 209 if (firstWorkspace?.services) {
164 assert.empty(JSON.parse(firstWorkspace.services), file) 210 assert.empty(JSON.parse(firstWorkspace.services), file);
165 } 211 }
166 212
167 const secondWorkspace = workspacesForUser.find((w) => w.name === 'workspace2') 213 const secondWorkspace = workspacesForUser.find(
214 w => w.name === 'workspace2',
215 );
168 if (secondWorkspace?.services) { 216 if (secondWorkspace?.services) {
169 assert.deepEqual( 217 assert.deepEqual(
170 JSON.parse(secondWorkspace.services), 218 JSON.parse(secondWorkspace.services),
171 [firstServiceUuid, secondServiceUuid], 219 [firstServiceUuid, secondServiceUuid],
172 file 220 file,
173 ) 221 );
174 } 222 }
175 223
176 const thirdWorkspace = workspacesForUser.find((w) => w.name === 'workspace3') 224 const thirdWorkspace = workspacesForUser.find(
225 w => w.name === 'workspace3',
226 );
177 if (thirdWorkspace?.services) { 227 if (thirdWorkspace?.services) {
178 assert.deepEqual( 228 assert.deepEqual(
179 JSON.parse(thirdWorkspace.services), 229 JSON.parse(thirdWorkspace.services),
180 [firstServiceUuid, secondServiceUuid, thirdServiceUUid], 230 [firstServiceUuid, secondServiceUuid, thirdServiceUUid],
181 file 231 file,
182 ) 232 );
183 } 233 }
184 } 234 }
185 }) 235 });
186}) 236});
diff --git a/tests/functional/health.spec.ts b/tests/functional/health.spec.ts
index 50bf46c..2f7e074 100644
--- a/tests/functional/health.spec.ts
+++ b/tests/functional/health.spec.ts
@@ -1,13 +1,13 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2 2
3test.group('health page', () => { 3test.group('health page', () => {
4 test('returns a 200 response', async ({ client }) => { 4 test('returns a 200 response', async ({ client }) => {
5 const response = await client.get('/health') 5 const response = await client.get('/health');
6 6
7 response.assertStatus(200) 7 response.assertStatus(200);
8 response.assertBodyContains({ 8 response.assertBodyContains({
9 api: 'success', 9 api: 'success',
10 db: 'success', 10 db: 'success',
11 }) 11 });
12 }) 12 });
13}) 13});
diff --git a/tests/functional/static-pages/home.spec.ts b/tests/functional/static-pages/home.spec.ts
index 20d02db..5054e05 100644
--- a/tests/functional/static-pages/home.spec.ts
+++ b/tests/functional/static-pages/home.spec.ts
@@ -1,10 +1,10 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2 2
3test.group('home page', () => { 3test.group('home page', () => {
4 test('returns a 200 response', async ({ client }) => { 4 test('returns a 200 response', async ({ client }) => {
5 const response = await client.get('/') 5 const response = await client.get('/');
6 6
7 response.assertStatus(200) 7 response.assertStatus(200);
8 response.assertTextIncludes('Go to account dashboard') 8 response.assertTextIncludes('Go to account dashboard');
9 }) 9 });
10}) 10});
diff --git a/tests/functional/static-pages/privacy.spec.ts b/tests/functional/static-pages/privacy.spec.ts
index b79f580..f1d5bec 100644
--- a/tests/functional/static-pages/privacy.spec.ts
+++ b/tests/functional/static-pages/privacy.spec.ts
@@ -1,10 +1,10 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2 2
3test.group('privacy page', () => { 3test.group('privacy page', () => {
4 test('returns a 200 response', async ({ client }) => { 4 test('returns a 200 response', async ({ client }) => {
5 const response = await client.get('/privacy') 5 const response = await client.get('/privacy');
6 6
7 response.assertStatus(200) 7 response.assertStatus(200);
8 response.assertTextIncludes('PRIVACY POLICY') 8 response.assertTextIncludes('PRIVACY POLICY');
9 }) 9 });
10}) 10});
diff --git a/tests/functional/static-pages/terms.spec.ts b/tests/functional/static-pages/terms.spec.ts
index 9c22257..de990e4 100644
--- a/tests/functional/static-pages/terms.spec.ts
+++ b/tests/functional/static-pages/terms.spec.ts
@@ -1,10 +1,10 @@
1import { test } from '@japa/runner' 1import { test } from '@japa/runner';
2 2
3test.group('terms page', () => { 3test.group('terms page', () => {
4 test('returns a 200 response', async ({ client }) => { 4 test('returns a 200 response', async ({ client }) => {
5 const response = await client.get('/terms') 5 const response = await client.get('/terms');
6 6
7 response.assertStatus(200) 7 response.assertStatus(200);
8 response.assertTextIncludes('Terms of Service') 8 response.assertTextIncludes('Terms of Service');
9 }) 9 });
10}) 10});
diff --git a/tests/utils.ts b/tests/utils.ts
index b60b867..db6edee 100644
--- a/tests/utils.ts
+++ b/tests/utils.ts
@@ -1,6 +1,6 @@
1import edge from 'edge.js' 1import edge from 'edge.js';
2 2
3export function fakeCsrfField(): void { 3export function fakeCsrfField(): void {
4 // Create fake csrField function in the view 4 // Create fake csrField function in the view
5 edge.global('csrfField', () => '') 5 edge.global('csrfField', () => '');
6} 6}