@edifice.io/communities-tests 1.0.0-develop-pedago.9.20250731094830 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/it/scenarios/api-announcements.spec.ts +270 -0
- package/it/scenarios/api-community-role-check.spec.ts +1 -1
- package/it/scenarios/api-folders.spec.ts +306 -0
- package/it/scenarios/api-invitations-search-sort.spec.ts +1 -1
- package/it/scenarios/api-invitations.spec.ts +33 -13
- package/it/scenarios/api-membership.spec.ts +26 -24
- package/it/scenarios/api-permission-check.spec.ts +1 -1
- package/it/scenarios/api-resources-search-sort.spec.ts +64 -12
- package/it/scenarios/api-resources.spec.ts +2 -7
- package/it/scenarios/utils/_announcements-api.utils.ts +195 -0
- package/it/scenarios/utils/_folders-api.utils.ts +199 -0
- package/it/scenarios/utils/_http-response.utils.ts +46 -0
- package/it/scenarios/utils/_invitation-api.utils.ts +19 -21
- package/it/scenarios/utils/_resource-api.utils.ts +14 -7
- package/it/scenarios/utils/_role.utils.ts +11 -3
- package/package.json +2 -10
- package/types/generated/announcement.ts +73 -0
- package/types/generated/base.ts +32 -0
- package/types/generated/community.ts +97 -0
- package/types/generated/discussion.ts +47 -0
- package/types/generated/folder.ts +49 -0
- package/types/generated/index.ts +12 -0
- package/types/generated/invitation.ts +135 -0
- package/types/generated/membership.ts +74 -0
- package/types/generated/resource.ts +94 -0
- package/types/generated/wiki.ts +24 -0
- /package/loadtest/{index.ts → scenarios/index.ts} +0 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { chai, describe } from "https://jslib.k6.io/k6chaijs/4.3.4.0/index.js";
|
|
3
|
+
import { check } from "k6";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
authenticateWeb,
|
|
7
|
+
getUsersOfSchool,
|
|
8
|
+
createAndSetRole,
|
|
9
|
+
linkRoleToUsers,
|
|
10
|
+
initStructure,
|
|
11
|
+
getRandomUserWithProfile,
|
|
12
|
+
getRolesOfStructure,
|
|
13
|
+
Structure,
|
|
14
|
+
logout,
|
|
15
|
+
UserInfo,
|
|
16
|
+
checkReturnCode,
|
|
17
|
+
} from "../../node_modules/edifice-k6-commons/dist/index.js";
|
|
18
|
+
|
|
19
|
+
// Import community API utils
|
|
20
|
+
import {
|
|
21
|
+
createCommunityOrFail,
|
|
22
|
+
deleteCommunity,
|
|
23
|
+
CreateCommunityParams,
|
|
24
|
+
getCommunity,
|
|
25
|
+
Community,
|
|
26
|
+
} from "./utils/_community-api.utils.ts";
|
|
27
|
+
import {
|
|
28
|
+
countAnnouncements,
|
|
29
|
+
createAnnouncement,
|
|
30
|
+
deleteAnnouncement,
|
|
31
|
+
getAnnouncement,
|
|
32
|
+
listAnnouncements,
|
|
33
|
+
updateAnnouncement,
|
|
34
|
+
} from "./utils/_announcements-api.utils.ts";
|
|
35
|
+
import {
|
|
36
|
+
InvitationStatus,
|
|
37
|
+
listMyInvitations,
|
|
38
|
+
updateInvitationStatus,
|
|
39
|
+
} from "./utils/_invitation-api.utils.ts";
|
|
40
|
+
|
|
41
|
+
chai.config.logFailures = true;
|
|
42
|
+
|
|
43
|
+
export const options = {
|
|
44
|
+
setupTimeout: "1h",
|
|
45
|
+
maxRedirects: 0,
|
|
46
|
+
thresholds: {
|
|
47
|
+
checks: ["rate == 1.00"],
|
|
48
|
+
},
|
|
49
|
+
scenarios: {
|
|
50
|
+
announcementsTest: {
|
|
51
|
+
exec: "testAnnouncementsApi",
|
|
52
|
+
executor: "per-vu-iterations",
|
|
53
|
+
vus: 1,
|
|
54
|
+
maxDuration: "1m",
|
|
55
|
+
gracefulStop: "5s",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const timestamp = new Date().toISOString();
|
|
61
|
+
const schoolName = `IT Community`;
|
|
62
|
+
|
|
63
|
+
function acceptInvitation(user: UserInfo) {
|
|
64
|
+
authenticateWeb(user.login, "password");
|
|
65
|
+
listMyInvitations()?.items.forEach((inv) =>
|
|
66
|
+
updateInvitationStatus(inv.id, InvitationStatus.ACCEPTED),
|
|
67
|
+
);
|
|
68
|
+
logout();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function setup(): [UserInfo, UserInfo, UserInfo, Community] {
|
|
72
|
+
//Create structure
|
|
73
|
+
let structure: Structure = {} as Structure;
|
|
74
|
+
describe("[CommunityAnnouncements] Initialize data", () => {
|
|
75
|
+
authenticateWeb(__ENV.ADMC_LOGIN, __ENV.ADMC_PASSWORD);
|
|
76
|
+
structure = initStructure(schoolName, "tiny");
|
|
77
|
+
const role = createAndSetRole("Communities");
|
|
78
|
+
const groups = getRolesOfStructure(structure.id);
|
|
79
|
+
linkRoleToUsers(
|
|
80
|
+
structure,
|
|
81
|
+
role,
|
|
82
|
+
groups.map((g: any) => g.name),
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Get users from school
|
|
87
|
+
const users = getUsersOfSchool(structure);
|
|
88
|
+
const adminUser1 = getRandomUserWithProfile(users, "Teacher");
|
|
89
|
+
const adminUser2 = getRandomUserWithProfile(users, "Teacher", [adminUser1]);
|
|
90
|
+
const memberUser = getRandomUserWithProfile(users, "Student", [
|
|
91
|
+
adminUser1,
|
|
92
|
+
adminUser2,
|
|
93
|
+
]);
|
|
94
|
+
logout();
|
|
95
|
+
|
|
96
|
+
//Create a test community with 2 admins and 1 member
|
|
97
|
+
const communityData: CreateCommunityParams = {
|
|
98
|
+
title: `AnnouncementTest - Community ${timestamp}`,
|
|
99
|
+
type: "FREE",
|
|
100
|
+
schoolYearStart: 2025,
|
|
101
|
+
schoolYearEnd: 2026,
|
|
102
|
+
discussionEnabled: true,
|
|
103
|
+
welcomeNote: "Test community for announcements API tests",
|
|
104
|
+
invitations: {
|
|
105
|
+
users: [
|
|
106
|
+
{ userId: adminUser2.id, role: "ADMIN" },
|
|
107
|
+
{ userId: memberUser.id, role: "MEMBER" },
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
authenticateWeb(adminUser1.login, "password");
|
|
112
|
+
const communityId = Number(createCommunityOrFail(communityData));
|
|
113
|
+
const community = getCommunity(communityId);
|
|
114
|
+
logout();
|
|
115
|
+
acceptInvitation(adminUser2);
|
|
116
|
+
acceptInvitation(memberUser);
|
|
117
|
+
|
|
118
|
+
return [adminUser1, adminUser2, memberUser, community!];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function testAnnouncementsApi(
|
|
122
|
+
data: [UserInfo, UserInfo, UserInfo, Community],
|
|
123
|
+
) {
|
|
124
|
+
const [adminUser1, adminUser2, memberUser, community] = data;
|
|
125
|
+
const communityId = Number(community.id);
|
|
126
|
+
|
|
127
|
+
//Login as admin 1
|
|
128
|
+
authenticateWeb(adminUser1.login);
|
|
129
|
+
|
|
130
|
+
//Check list announcements initially empty
|
|
131
|
+
let announcements = listAnnouncements(communityId);
|
|
132
|
+
check(announcements, {
|
|
133
|
+
"Announcement list should be initially empty": (r) => r?.items.length == 0,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
//Check announcement A creation
|
|
137
|
+
const mediaList = [
|
|
138
|
+
{
|
|
139
|
+
id: "1",
|
|
140
|
+
name: "media 1",
|
|
141
|
+
type: "audio",
|
|
142
|
+
mimeType: "foo",
|
|
143
|
+
url: "bar",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: "2",
|
|
147
|
+
name: "media 2",
|
|
148
|
+
type: "image",
|
|
149
|
+
mimeType: "foo",
|
|
150
|
+
url: "bar",
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
const createA = createAnnouncement(communityId, {
|
|
154
|
+
content: "Announcement A",
|
|
155
|
+
media: mediaList,
|
|
156
|
+
});
|
|
157
|
+
checkReturnCode(
|
|
158
|
+
createA,
|
|
159
|
+
`Admin 1 should be able to create announcement A`,
|
|
160
|
+
201,
|
|
161
|
+
);
|
|
162
|
+
const idA = Number(JSON.parse(<string>createA.body).id);
|
|
163
|
+
announcements = listAnnouncements(communityId);
|
|
164
|
+
check(announcements, {
|
|
165
|
+
"Announcement list should be of size 1": (r) => r?.items.length == 1,
|
|
166
|
+
});
|
|
167
|
+
const announcementA = getAnnouncement(communityId, idA);
|
|
168
|
+
check(announcementA, {
|
|
169
|
+
"Announcement A should be correct": (r) => {
|
|
170
|
+
return (
|
|
171
|
+
r?.author.entId == adminUser1.id &&
|
|
172
|
+
r.content == "Announcement A" &&
|
|
173
|
+
r.media.length == 2 &&
|
|
174
|
+
r.media.at(0)!.name == "media 1"
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
logout();
|
|
179
|
+
|
|
180
|
+
//Login as admin 2
|
|
181
|
+
authenticateWeb(adminUser2.login);
|
|
182
|
+
|
|
183
|
+
//Check announcement B creation
|
|
184
|
+
const timeBeforeB = new Date().toISOString();
|
|
185
|
+
const createB = createAnnouncement(communityId, {
|
|
186
|
+
content: "Announcement B",
|
|
187
|
+
media: [],
|
|
188
|
+
});
|
|
189
|
+
checkReturnCode(
|
|
190
|
+
createA,
|
|
191
|
+
`Admin 2 should be able to create announcement B`,
|
|
192
|
+
201,
|
|
193
|
+
);
|
|
194
|
+
const idB = Number(JSON.parse(<string>createB.body).id);
|
|
195
|
+
announcements = listAnnouncements(communityId);
|
|
196
|
+
check(announcements, {
|
|
197
|
+
"Announcement list should be of size 2": (r) => r?.items.length == 2,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
//Check announcement A modification
|
|
201
|
+
const announcementAModif = updateAnnouncement(communityId, idA, {
|
|
202
|
+
content: "Oui bonjour",
|
|
203
|
+
media: mediaList.reverse(),
|
|
204
|
+
});
|
|
205
|
+
check(announcementAModif, {
|
|
206
|
+
"Admin 2 should be able to modify announcement": (r) => {
|
|
207
|
+
return (
|
|
208
|
+
r?.author.entId == adminUser1.id &&
|
|
209
|
+
r.content == "Oui bonjour" &&
|
|
210
|
+
Date.parse(r.modificationDate) > Date.parse(r.publicationDate) &&
|
|
211
|
+
r.modifier.entId == adminUser2.id &&
|
|
212
|
+
r.media.length == 2 &&
|
|
213
|
+
r.media.at(0)!.name == "media 2"
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
logout();
|
|
218
|
+
|
|
219
|
+
//Login as member
|
|
220
|
+
authenticateWeb(memberUser.login);
|
|
221
|
+
|
|
222
|
+
//Check filtering and ordering on GET requests
|
|
223
|
+
check(countAnnouncements(communityId), {
|
|
224
|
+
"Member should count 2 announcements": (n) => n?.count == 2,
|
|
225
|
+
});
|
|
226
|
+
check(countAnnouncements(communityId, timeBeforeB), {
|
|
227
|
+
"Member should count 1 announcement with filtering": (n) => n?.count == 1,
|
|
228
|
+
});
|
|
229
|
+
check(listAnnouncements(communityId, 1, 10, timeBeforeB), {
|
|
230
|
+
"Member should list 1 announcement with filtering": (n) =>
|
|
231
|
+
n?.meta.itemCount == 1,
|
|
232
|
+
});
|
|
233
|
+
check(listAnnouncements(communityId, 1, 10, null, "publicationDate", "ASC"), {
|
|
234
|
+
"List with ASC order should be in correct order": (li) =>
|
|
235
|
+
li?.items.at(0)?.id == idA && li?.items.at(1)?.id == idB,
|
|
236
|
+
});
|
|
237
|
+
check(listAnnouncements(communityId, 1, 10, null, "modificationDate"), {
|
|
238
|
+
"List by modification date should be in correct order": (li) =>
|
|
239
|
+
li?.items.at(0)?.id == idA && li?.items.at(1)?.id == idB,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
//Check that member cannot create/update/delete announcements
|
|
243
|
+
checkReturnCode(
|
|
244
|
+
createAnnouncement(communityId, { content: "foo", media: [] }),
|
|
245
|
+
"Member should not be able to create announcement",
|
|
246
|
+
403,
|
|
247
|
+
);
|
|
248
|
+
check(updateAnnouncement(communityId, idB, { content: "foo", media: [] }), {
|
|
249
|
+
"Member should not be able to update announcement B": (b) => b == null,
|
|
250
|
+
});
|
|
251
|
+
check(deleteAnnouncement(communityId, idB), {
|
|
252
|
+
"Member should not be able to delete Announcement B": (b) => !b,
|
|
253
|
+
});
|
|
254
|
+
logout();
|
|
255
|
+
|
|
256
|
+
//Login as admin1
|
|
257
|
+
authenticateWeb(adminUser1.login);
|
|
258
|
+
check(deleteAnnouncement(communityId, idB), {
|
|
259
|
+
"Admin 1 should be able to delete Announcement B": (b) => b,
|
|
260
|
+
});
|
|
261
|
+
logout();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//Cleanup: delete test community
|
|
265
|
+
export function teardown(data: [UserInfo, UserInfo, UserInfo, Community]) {
|
|
266
|
+
const [adminUser, , , community] = data;
|
|
267
|
+
authenticateWeb(adminUser.login, "password");
|
|
268
|
+
deleteCommunity(community.id);
|
|
269
|
+
logout();
|
|
270
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { chai, describe } from "https://jslib.k6.io/k6chaijs/4.3.4.0/index.js";
|
|
3
|
+
import { check } from "k6";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
authenticateWeb,
|
|
7
|
+
getUsersOfSchool,
|
|
8
|
+
createAndSetRole,
|
|
9
|
+
linkRoleToUsers,
|
|
10
|
+
initStructure,
|
|
11
|
+
getRandomUserWithProfile,
|
|
12
|
+
getRolesOfStructure,
|
|
13
|
+
Structure,
|
|
14
|
+
logout,
|
|
15
|
+
UserInfo,
|
|
16
|
+
checkReturnCode,
|
|
17
|
+
} from "../../node_modules/edifice-k6-commons/dist/index.js";
|
|
18
|
+
|
|
19
|
+
//Import community API utils
|
|
20
|
+
import {
|
|
21
|
+
createCommunityOrFail,
|
|
22
|
+
deleteCommunity,
|
|
23
|
+
CreateCommunityParams,
|
|
24
|
+
getCommunity,
|
|
25
|
+
Community,
|
|
26
|
+
} from "./utils/_community-api.utils.ts";
|
|
27
|
+
import {
|
|
28
|
+
getFolders,
|
|
29
|
+
getRootFolders,
|
|
30
|
+
createFolder,
|
|
31
|
+
updateFolder,
|
|
32
|
+
getFolderContent,
|
|
33
|
+
removeFolder,
|
|
34
|
+
addResourceToFolder,
|
|
35
|
+
removeResourceFromFolder,
|
|
36
|
+
Folder,
|
|
37
|
+
PaginatedFolders,
|
|
38
|
+
FolderDetails,
|
|
39
|
+
} from "./utils/_folders-api.utils.ts";
|
|
40
|
+
import {
|
|
41
|
+
InvitationStatus,
|
|
42
|
+
listMyInvitations,
|
|
43
|
+
updateInvitationStatus,
|
|
44
|
+
} from "./utils/_invitation-api.utils.ts";
|
|
45
|
+
import {
|
|
46
|
+
AppName,
|
|
47
|
+
createResource,
|
|
48
|
+
ResourceType,
|
|
49
|
+
} from "./utils/_resource-api.utils.ts";
|
|
50
|
+
import { HttpError } from "./utils/_http-response.utils.ts";
|
|
51
|
+
|
|
52
|
+
chai.config.logFailures = true;
|
|
53
|
+
|
|
54
|
+
export const options = {
|
|
55
|
+
setupTimeout: "1h",
|
|
56
|
+
maxRedirects: 0,
|
|
57
|
+
thresholds: {
|
|
58
|
+
checks: ["rate == 1.00"],
|
|
59
|
+
},
|
|
60
|
+
scenarios: {
|
|
61
|
+
foldersTest: {
|
|
62
|
+
exec: "testFoldersApi",
|
|
63
|
+
executor: "per-vu-iterations",
|
|
64
|
+
vus: 1,
|
|
65
|
+
maxDuration: "1m",
|
|
66
|
+
gracefulStop: "5s",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const timestamp = new Date().toISOString();
|
|
72
|
+
const schoolName = `IT Community`;
|
|
73
|
+
|
|
74
|
+
function acceptInvitation(user: UserInfo) {
|
|
75
|
+
authenticateWeb(user.login, "password");
|
|
76
|
+
listMyInvitations()?.items.forEach((inv) =>
|
|
77
|
+
updateInvitationStatus(inv.id, InvitationStatus.ACCEPTED),
|
|
78
|
+
);
|
|
79
|
+
logout();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function setup(): [UserInfo, UserInfo, Community] {
|
|
83
|
+
//Create structure
|
|
84
|
+
let structure: Structure = {} as Structure;
|
|
85
|
+
describe("[CommunityFolders] Initialize data", () => {
|
|
86
|
+
authenticateWeb(__ENV.ADMC_LOGIN, __ENV.ADMC_PASSWORD);
|
|
87
|
+
structure = initStructure(schoolName, "tiny");
|
|
88
|
+
const role = createAndSetRole("Communities");
|
|
89
|
+
const groups = getRolesOfStructure(structure.id);
|
|
90
|
+
linkRoleToUsers(
|
|
91
|
+
structure,
|
|
92
|
+
role,
|
|
93
|
+
groups.map((g: any) => g.name),
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Get users from school
|
|
98
|
+
const users = getUsersOfSchool(structure);
|
|
99
|
+
const adminUser = getRandomUserWithProfile(users, "Teacher");
|
|
100
|
+
const memberUser = getRandomUserWithProfile(users, "Student", [adminUser]);
|
|
101
|
+
logout();
|
|
102
|
+
|
|
103
|
+
//Create a test community with 2 admins and 1 member
|
|
104
|
+
const communityData: CreateCommunityParams = {
|
|
105
|
+
title: `FolderTest - Community ${timestamp}`,
|
|
106
|
+
type: "FREE",
|
|
107
|
+
schoolYearStart: 2025,
|
|
108
|
+
schoolYearEnd: 2026,
|
|
109
|
+
discussionEnabled: true,
|
|
110
|
+
welcomeNote: "Test community for folders API tests",
|
|
111
|
+
invitations: {
|
|
112
|
+
users: [{ userId: memberUser.id, role: "MEMBER" }],
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
authenticateWeb(adminUser.login, "password");
|
|
116
|
+
const communityId = Number(createCommunityOrFail(communityData));
|
|
117
|
+
const community = getCommunity(communityId);
|
|
118
|
+
logout();
|
|
119
|
+
acceptInvitation(memberUser);
|
|
120
|
+
|
|
121
|
+
return [adminUser, memberUser, community!];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function testFoldersApi(data: [UserInfo, UserInfo, Community]) {
|
|
125
|
+
const [adminUser, memberUser, community] = data;
|
|
126
|
+
const communityId = Number(community.id);
|
|
127
|
+
|
|
128
|
+
//Login as admin
|
|
129
|
+
authenticateWeb(adminUser.login);
|
|
130
|
+
|
|
131
|
+
//Check list folders initially empty
|
|
132
|
+
let folders = getFolders(communityId).value as PaginatedFolders;
|
|
133
|
+
check(folders, {
|
|
134
|
+
"Folder list should be initially empty": (res) => res?.items.length == 0,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
//Check folder creation
|
|
138
|
+
const folderA = createFolder(communityId, {
|
|
139
|
+
name: "Folder A",
|
|
140
|
+
}).value as Folder;
|
|
141
|
+
check(folderA, {
|
|
142
|
+
"Admin should be able to create root folder A": (res) => {
|
|
143
|
+
return res?.name == "Folder A" && res?.isRoot == true;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
const idA = Number(folderA?.id);
|
|
147
|
+
folders = getFolders(communityId).value as PaginatedFolders;
|
|
148
|
+
check(folders, {
|
|
149
|
+
"Folder list should be of size 1": (res) => res?.items.length == 1,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
//Check subfolder creation
|
|
153
|
+
const folderB = createFolder(communityId, {
|
|
154
|
+
name: "Folder B",
|
|
155
|
+
parentId: idA,
|
|
156
|
+
}).value as Folder;
|
|
157
|
+
check(folderB, {
|
|
158
|
+
"Admin should be able to create subfolder B": (res) => {
|
|
159
|
+
return (
|
|
160
|
+
res?.name == "Folder B" && res?.isRoot == false && res?.parentId == idA
|
|
161
|
+
);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
const idB = Number(folderB?.id);
|
|
165
|
+
folders = getFolders(communityId).value as PaginatedFolders;
|
|
166
|
+
check(folders, {
|
|
167
|
+
"Folder list should be of size 2": (res) => res?.items.length == 2,
|
|
168
|
+
});
|
|
169
|
+
let rootFolders = getRootFolders(communityId).value as Folder[];
|
|
170
|
+
check(rootFolders, {
|
|
171
|
+
"Root folders list should still be of size 1": (res) => res?.length == 1,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
//Check folder filtering by parent
|
|
175
|
+
let folderSearch = getFolders(communityId, 1, 10, undefined, idA)
|
|
176
|
+
.value as PaginatedFolders;
|
|
177
|
+
check(folderSearch, {
|
|
178
|
+
"Folder A should have 1 subfolder": (res) => res?.items.length == 1,
|
|
179
|
+
});
|
|
180
|
+
let folderDetails = getFolderContent(communityId, idA).value as FolderDetails;
|
|
181
|
+
check(folderDetails, {
|
|
182
|
+
"Folder details should show subfolder B": (res) =>
|
|
183
|
+
res?.subFolders?.at(0)?.id == idB,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
//Check folder modification
|
|
187
|
+
const folderBModif = updateFolder(communityId, idB, {
|
|
188
|
+
name: "Root B",
|
|
189
|
+
}).value as Folder;
|
|
190
|
+
check(folderBModif, {
|
|
191
|
+
"Subfolder should be moved to the root": (res) => {
|
|
192
|
+
return (
|
|
193
|
+
Date.parse(res?.modificationDate!) > Date.parse(res?.creationDate!) &&
|
|
194
|
+
res?.modifier?.entId == adminUser.id &&
|
|
195
|
+
res?.isRoot
|
|
196
|
+
);
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
rootFolders = getRootFolders(communityId).value as Folder[];
|
|
200
|
+
check(rootFolders, {
|
|
201
|
+
"Root folders list should be of size 2": (res) => res?.length == 2,
|
|
202
|
+
});
|
|
203
|
+
//Check folder filtering by parent
|
|
204
|
+
folderSearch = getFolders(communityId, 1, 10, undefined, idA)
|
|
205
|
+
.value as PaginatedFolders;
|
|
206
|
+
check(folderSearch, {
|
|
207
|
+
"Folder A should now have 0 subfolder": (res) => res?.items.length == 0,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
//Create test resources
|
|
211
|
+
const resourceCreate1 = {
|
|
212
|
+
type: ResourceType.EXTERNAL_LINK,
|
|
213
|
+
appName: AppName.EXTERNAL_LINK,
|
|
214
|
+
title: "coin coin",
|
|
215
|
+
resourceUrl: "duckduckgo.com",
|
|
216
|
+
};
|
|
217
|
+
const resource = createResource(communityId, resourceCreate1);
|
|
218
|
+
const resourceAdd = addResourceToFolder(communityId, idA, resource?.id!)
|
|
219
|
+
.value as boolean;
|
|
220
|
+
check(resourceAdd, {
|
|
221
|
+
"Resource should be added to folder A": (add) => add,
|
|
222
|
+
});
|
|
223
|
+
folderDetails = getFolderContent(communityId, idA).value as FolderDetails;
|
|
224
|
+
check(folderDetails, {
|
|
225
|
+
"Folder details should show resource, and no subfolder": (res) =>
|
|
226
|
+
res?.resources?.at(0)?.id == resource?.id && res?.subFolders?.length == 0,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
//Move resources
|
|
230
|
+
const resourceMove = addResourceToFolder(communityId, idB, resource?.id!)
|
|
231
|
+
.value as boolean;
|
|
232
|
+
check(resourceMove, {
|
|
233
|
+
"Resource should be added to folder B": (add) => add,
|
|
234
|
+
});
|
|
235
|
+
folderDetails = getFolderContent(communityId, idB).value as FolderDetails;
|
|
236
|
+
check(folderDetails, {
|
|
237
|
+
"Folder details should show resource on folder B": (res) =>
|
|
238
|
+
res?.resources?.at(0)?.id == resource?.id,
|
|
239
|
+
});
|
|
240
|
+
folderDetails = getFolderContent(communityId, idA).value as FolderDetails;
|
|
241
|
+
check(folderDetails, {
|
|
242
|
+
"Resource should be removed from folder A": (res) =>
|
|
243
|
+
res?.resources?.length == 0,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
//Delete resource
|
|
247
|
+
removeResourceFromFolder(communityId, idB, resource?.id!);
|
|
248
|
+
folderDetails = getFolderContent(communityId, idB).value as FolderDetails;
|
|
249
|
+
check(folderDetails, {
|
|
250
|
+
"Resource should be removed from folder B": (res) =>
|
|
251
|
+
res?.resources?.length == 0,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
logout();
|
|
255
|
+
|
|
256
|
+
//Login as member
|
|
257
|
+
authenticateWeb(memberUser.login);
|
|
258
|
+
|
|
259
|
+
//Check GET requests
|
|
260
|
+
check(getFolders(communityId, 1, 10).value as PaginatedFolders, {
|
|
261
|
+
"Member should list 2 folders without filtering": (res) =>
|
|
262
|
+
res?.meta.itemCount == 2,
|
|
263
|
+
});
|
|
264
|
+
check(getFolders(communityId, 1, 10, "Folder").value as PaginatedFolders, {
|
|
265
|
+
"Member should list 1 folders with name filtering": (res) =>
|
|
266
|
+
res?.meta.itemCount == 1,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
//Check that member cannot create/update/delete folders
|
|
270
|
+
checkReturnCode(
|
|
271
|
+
createFolder(communityId, { name: "foo" }).value as HttpError,
|
|
272
|
+
"Member should not be able to create folder",
|
|
273
|
+
403,
|
|
274
|
+
);
|
|
275
|
+
checkReturnCode(
|
|
276
|
+
updateFolder(communityId, idB, { name: "foo" }).value as HttpError,
|
|
277
|
+
"Member should not be able to update folder",
|
|
278
|
+
403,
|
|
279
|
+
);
|
|
280
|
+
checkReturnCode(
|
|
281
|
+
removeFolder(communityId, idB).value as HttpError,
|
|
282
|
+
"Member should not be able to delete folder",
|
|
283
|
+
403,
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
logout();
|
|
287
|
+
|
|
288
|
+
//Check folder deletion
|
|
289
|
+
authenticateWeb(adminUser.login);
|
|
290
|
+
const deleteFolder = removeFolder(communityId, idA).value as boolean;
|
|
291
|
+
check(deleteFolder, {
|
|
292
|
+
"Admin should be able to delete folder": (res) => res,
|
|
293
|
+
});
|
|
294
|
+
check(getFolders(communityId, 1, 10).value as PaginatedFolders, {
|
|
295
|
+
"Folder should be correctly deleted": (res) => res?.meta.itemCount == 1,
|
|
296
|
+
});
|
|
297
|
+
logout();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
//Cleanup: delete test community
|
|
301
|
+
export function teardown(data: [UserInfo, UserInfo, Community]) {
|
|
302
|
+
const [adminUser, , community] = data;
|
|
303
|
+
authenticateWeb(adminUser.login, "password");
|
|
304
|
+
deleteCommunity(community.id);
|
|
305
|
+
logout();
|
|
306
|
+
}
|
|
@@ -57,7 +57,7 @@ export const options = {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
const timestamp = new Date().toISOString();
|
|
60
|
-
const schoolName = `IT Community
|
|
60
|
+
const schoolName = `IT Community`;
|
|
61
61
|
|
|
62
62
|
export function setup(): Structure {
|
|
63
63
|
let structure: Structure = {} as Structure;
|
|
@@ -67,7 +67,7 @@ export const options = {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
const timestamp = new Date().toISOString();
|
|
70
|
-
const schoolName = `IT Community
|
|
70
|
+
const schoolName = `IT Community`;
|
|
71
71
|
|
|
72
72
|
export function setup(): Structure {
|
|
73
73
|
let structure: Structure = {} as Structure;
|
|
@@ -504,10 +504,14 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
504
504
|
message: "This invitation will be marked as see later",
|
|
505
505
|
};
|
|
506
506
|
|
|
507
|
-
const seeLaterInvitations = createInvitations(
|
|
507
|
+
const seeLaterInvitations = createInvitations(
|
|
508
|
+
communityId,
|
|
509
|
+
seeLaterInvitationData,
|
|
510
|
+
);
|
|
508
511
|
|
|
509
512
|
check(seeLaterInvitations, {
|
|
510
|
-
"See-later test invitation created successfully": (r) =>
|
|
513
|
+
"See-later test invitation created successfully": (r) =>
|
|
514
|
+
r !== null && r.length > 0,
|
|
511
515
|
});
|
|
512
516
|
|
|
513
517
|
if (!seeLaterInvitations || seeLaterInvitations.length === 0) {
|
|
@@ -516,7 +520,9 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
516
520
|
}
|
|
517
521
|
|
|
518
522
|
const seeLaterInvitationId = seeLaterInvitations[0].id;
|
|
519
|
-
console.log(
|
|
523
|
+
console.log(
|
|
524
|
+
`Created invitation with ID: ${seeLaterInvitationId} for see-later test`,
|
|
525
|
+
);
|
|
520
526
|
|
|
521
527
|
// Member logs in
|
|
522
528
|
logout();
|
|
@@ -524,15 +530,22 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
524
530
|
|
|
525
531
|
// Check that the invitation exists in the member's list
|
|
526
532
|
const initialInvitations = listMyInvitations();
|
|
527
|
-
const initialInvitation = findInvitationById(
|
|
533
|
+
const initialInvitation = findInvitationById(
|
|
534
|
+
seeLaterInvitationId,
|
|
535
|
+
initialInvitations,
|
|
536
|
+
);
|
|
528
537
|
|
|
529
538
|
check(initialInvitation, {
|
|
530
539
|
"See-later invitation found in member's list": (r) => r !== null,
|
|
531
|
-
"See-later flag is initially false": (r) =>
|
|
540
|
+
"See-later flag is initially false": (r) =>
|
|
541
|
+
r !== null && r.seeLater === false,
|
|
532
542
|
});
|
|
533
543
|
|
|
534
544
|
// Update the see-later flag to true
|
|
535
|
-
const updatedInvitation = updateInvitationSeeLater(
|
|
545
|
+
const updatedInvitation = updateInvitationSeeLater(
|
|
546
|
+
seeLaterInvitationId,
|
|
547
|
+
true,
|
|
548
|
+
);
|
|
536
549
|
|
|
537
550
|
check(updatedInvitation, {
|
|
538
551
|
"See-later flag updated successfully": (r) => r !== null,
|
|
@@ -543,17 +556,23 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
543
556
|
const filteredInvitations = listMyInvitations({ seeLater: true });
|
|
544
557
|
|
|
545
558
|
check(filteredInvitations, {
|
|
546
|
-
"Can filter invitations by see-later flag": (r) =>
|
|
559
|
+
"Can filter invitations by see-later flag": (r) =>
|
|
560
|
+
r !== null && r.items.length > 0,
|
|
547
561
|
"Filtered list contains our marked invitation": (r) =>
|
|
548
|
-
r !== null &&
|
|
562
|
+
r !== null &&
|
|
563
|
+
r.items.some((inv: Invitation) => inv.id === seeLaterInvitationId),
|
|
549
564
|
});
|
|
550
565
|
|
|
551
566
|
// Change see-later flag back to false
|
|
552
|
-
const updatedAgainInvitation = updateInvitationSeeLater(
|
|
567
|
+
const updatedAgainInvitation = updateInvitationSeeLater(
|
|
568
|
+
seeLaterInvitationId,
|
|
569
|
+
false,
|
|
570
|
+
);
|
|
553
571
|
|
|
554
572
|
check(updatedAgainInvitation, {
|
|
555
573
|
"See-later flag turned off successfully": (r) => r !== null,
|
|
556
|
-
"See-later flag set back to false": (r) =>
|
|
574
|
+
"See-later flag set back to false": (r) =>
|
|
575
|
+
r !== null && r.seeLater === false,
|
|
557
576
|
});
|
|
558
577
|
|
|
559
578
|
// Verify filtering with seeLater=false
|
|
@@ -562,7 +581,8 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
562
581
|
check(nonSeeLaterInvitations, {
|
|
563
582
|
"Can filter invitations by see-later=false": (r) => r !== null,
|
|
564
583
|
"Filtered list contains our unmarked invitation": (r) =>
|
|
565
|
-
r !== null &&
|
|
584
|
+
r !== null &&
|
|
585
|
+
r.items.some((inv: Invitation) => inv.id === seeLaterInvitationId),
|
|
566
586
|
});
|
|
567
587
|
});
|
|
568
588
|
|
|
@@ -571,7 +591,7 @@ export function testInvitationsApi(structure: Structure) {
|
|
|
571
591
|
// Assurez-vous que l'admin est connecté pour supprimer la communauté
|
|
572
592
|
logout();
|
|
573
593
|
authenticateWeb(adminUser.login, "password");
|
|
574
|
-
|
|
594
|
+
|
|
575
595
|
const deleted = deleteCommunity(communityId);
|
|
576
596
|
|
|
577
597
|
check(deleted, {
|