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