@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
|
@@ -36,10 +36,10 @@ import {
|
|
|
36
36
|
} from "./utils/_membership-api.utils.ts";
|
|
37
37
|
|
|
38
38
|
// Import invitation API utils for join workflow
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
40
|
joinCommunity,
|
|
41
41
|
updateRequestStatus,
|
|
42
|
-
InvitationStatus
|
|
42
|
+
InvitationStatus,
|
|
43
43
|
} from "./utils/_invitation-api.utils.ts";
|
|
44
44
|
|
|
45
45
|
chai.config.logFailures = true;
|
|
@@ -62,7 +62,7 @@ export const options = {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
const timestamp = new Date().toISOString();
|
|
65
|
-
const schoolName = `IT Community
|
|
65
|
+
const schoolName = `IT Community`;
|
|
66
66
|
|
|
67
67
|
export function setup(): Structure {
|
|
68
68
|
let structure: Structure = {} as Structure;
|
|
@@ -131,7 +131,7 @@ export function testMembershipApi(structure: Structure) {
|
|
|
131
131
|
console.log(`Retrieved secret code: ${secretCode}`);
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
-
// Step 3: Member creates join request with secret code
|
|
134
|
+
// Step 3: Member creates join request with secret code
|
|
135
135
|
describe("Member creates join request with secret code", () => {
|
|
136
136
|
// Authenticate as member
|
|
137
137
|
logout();
|
|
@@ -144,29 +144,31 @@ export function testMembershipApi(structure: Structure) {
|
|
|
144
144
|
const joinRequest = joinCommunity(secretCode);
|
|
145
145
|
check(joinRequest, {
|
|
146
146
|
"Join request created successfully": (r) => r !== null,
|
|
147
|
-
"Join request has REQUEST status": (r) =>
|
|
147
|
+
"Join request has REQUEST status": (r) =>
|
|
148
148
|
r !== null && r.status === InvitationStatus.REQUEST,
|
|
149
149
|
});
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
// Store the invitation ID and user ID for later approval
|
|
152
152
|
const invitationId = joinRequest?.id;
|
|
153
153
|
currentUserId = Number(joinRequest?.receiver?.id);
|
|
154
|
-
console.log(
|
|
155
|
-
|
|
154
|
+
console.log(
|
|
155
|
+
`Created join request with ID: ${invitationId} for user ID: ${currentUserId}`,
|
|
156
|
+
);
|
|
157
|
+
|
|
156
158
|
// Step 4: Admin approves the join request
|
|
157
159
|
logout();
|
|
158
160
|
authenticateWeb(adminUser.login, "password");
|
|
159
|
-
|
|
161
|
+
|
|
160
162
|
// Approve join request
|
|
161
163
|
const approvedRequest = updateRequestStatus(
|
|
162
|
-
communityId,
|
|
163
|
-
invitationId!,
|
|
164
|
-
InvitationStatus.REQUEST_ACCEPTED
|
|
164
|
+
communityId,
|
|
165
|
+
invitationId!,
|
|
166
|
+
InvitationStatus.REQUEST_ACCEPTED,
|
|
165
167
|
);
|
|
166
|
-
|
|
168
|
+
|
|
167
169
|
check(approvedRequest, {
|
|
168
170
|
"Join request approved successfully": (r) => r !== null,
|
|
169
|
-
"Status changed to REQUEST_ACCEPTED": (r) =>
|
|
171
|
+
"Status changed to REQUEST_ACCEPTED": (r) =>
|
|
170
172
|
r !== null && r.status === InvitationStatus.REQUEST_ACCEPTED,
|
|
171
173
|
});
|
|
172
174
|
});
|
|
@@ -264,19 +266,19 @@ export function testMembershipApi(structure: Structure) {
|
|
|
264
266
|
check(joinRequest, {
|
|
265
267
|
"Join request created successfully": (r) => r !== null,
|
|
266
268
|
});
|
|
267
|
-
|
|
269
|
+
|
|
268
270
|
// Store the invitation ID
|
|
269
271
|
const invitationId = joinRequest?.id;
|
|
270
|
-
|
|
272
|
+
|
|
271
273
|
// Admin approves the request
|
|
272
274
|
logout();
|
|
273
275
|
authenticateWeb(adminUser.login, "password");
|
|
274
|
-
|
|
276
|
+
|
|
275
277
|
// Approve join request
|
|
276
278
|
updateRequestStatus(
|
|
277
|
-
communityId,
|
|
278
|
-
invitationId!,
|
|
279
|
-
InvitationStatus.REQUEST_ACCEPTED
|
|
279
|
+
communityId,
|
|
280
|
+
invitationId!,
|
|
281
|
+
InvitationStatus.REQUEST_ACCEPTED,
|
|
280
282
|
);
|
|
281
283
|
|
|
282
284
|
// Admin removes the member
|
|
@@ -357,12 +359,12 @@ export function testMembershipApi(structure: Structure) {
|
|
|
357
359
|
authenticateWeb(adminUser.login, "password");
|
|
358
360
|
for (let i = 0; i < testMemberInvitationIds.length; i++) {
|
|
359
361
|
updateRequestStatus(
|
|
360
|
-
communityId,
|
|
361
|
-
testMemberInvitationIds[i],
|
|
362
|
-
InvitationStatus.REQUEST_ACCEPTED
|
|
362
|
+
communityId,
|
|
363
|
+
testMemberInvitationIds[i],
|
|
364
|
+
InvitationStatus.REQUEST_ACCEPTED,
|
|
363
365
|
);
|
|
364
366
|
}
|
|
365
|
-
|
|
367
|
+
|
|
366
368
|
// Verify all users are now members
|
|
367
369
|
const membersBeforeRemoval = listCommunityMembers(communityId);
|
|
368
370
|
check(membersBeforeRemoval, {
|
|
@@ -84,7 +84,7 @@ export const options = {
|
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const schoolName = `IT Community
|
|
87
|
+
const schoolName = `IT Community`;
|
|
88
88
|
// Setup function to create structure and configure roles
|
|
89
89
|
export function setup(): StructureWithRole {
|
|
90
90
|
let structure: StructureWithRole = {} as StructureWithRole;
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
SortDirection,
|
|
39
39
|
listResourcesWithSearch,
|
|
40
40
|
} from "./utils/_resource-api.utils.ts";
|
|
41
|
+
import { createFolder, Folder } from "./utils/_folders-api.utils.ts";
|
|
41
42
|
|
|
42
43
|
chai.config.logFailures = true;
|
|
43
44
|
|
|
@@ -60,7 +61,7 @@ export const options = {
|
|
|
60
61
|
|
|
61
62
|
// Generate unique timestamp for test resources
|
|
62
63
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
63
|
-
const schoolName = `
|
|
64
|
+
const schoolName = `IT Community`;
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
67
|
* Setup function to prepare test environment and assign permissions
|
|
@@ -102,7 +103,7 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
102
103
|
};
|
|
103
104
|
|
|
104
105
|
// Resource test data
|
|
105
|
-
|
|
106
|
+
let resourceTestData = [
|
|
106
107
|
{
|
|
107
108
|
type: ResourceType.ENT,
|
|
108
109
|
appName: AppName.EXTERNAL_LINK,
|
|
@@ -136,6 +137,7 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
136
137
|
appName: AppName.EXTERNAL_LINK,
|
|
137
138
|
title: "Epsilon Blog Resource",
|
|
138
139
|
resourceUrl: "https://example.com/delta",
|
|
140
|
+
folderId: -1, // Placeholder. Folder id will be updated once the test folder is created
|
|
139
141
|
},
|
|
140
142
|
];
|
|
141
143
|
|
|
@@ -143,6 +145,7 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
143
145
|
let adminUser: UserInfo;
|
|
144
146
|
let memberUser: UserInfo;
|
|
145
147
|
const resourceIds: number[] = [];
|
|
148
|
+
let folderId: number;
|
|
146
149
|
|
|
147
150
|
describe("[Resource Search and Sort API Test]", () => {
|
|
148
151
|
// Get test users as admin
|
|
@@ -163,6 +166,18 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
163
166
|
communityId = Number(createCommunityOrFail(communityData));
|
|
164
167
|
console.log(`Created community with ID: ${communityId}`);
|
|
165
168
|
|
|
169
|
+
const folder = createFolder(communityId, { name: "Test Folder" })
|
|
170
|
+
.value as Folder;
|
|
171
|
+
folderId = folder.id;
|
|
172
|
+
console.log(`Created folder with ID: ${folderId}`);
|
|
173
|
+
// Assign correct folder id to resource data with folderId property
|
|
174
|
+
resourceTestData = resourceTestData.map((resource) => {
|
|
175
|
+
if (typeof resource.folderId !== "undefined") {
|
|
176
|
+
resource.folderId = folderId;
|
|
177
|
+
}
|
|
178
|
+
return resource;
|
|
179
|
+
});
|
|
180
|
+
|
|
166
181
|
// Create test resources with small delay between them for reliable date sorting
|
|
167
182
|
for (const data of resourceTestData) {
|
|
168
183
|
const resource = createResource(communityId, data);
|
|
@@ -310,6 +325,30 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
310
325
|
});
|
|
311
326
|
});
|
|
312
327
|
|
|
328
|
+
// Test filtering by folder ID
|
|
329
|
+
group("Filter by folder ID", () => {
|
|
330
|
+
const folderSearch = listResourcesWithSearch(communityId, {
|
|
331
|
+
folderId,
|
|
332
|
+
});
|
|
333
|
+
check(folderSearch, {
|
|
334
|
+
"Filtering by folder ID returns results": (r) =>
|
|
335
|
+
r !== null && r.items && r.items.length > 0,
|
|
336
|
+
"All results are in correct folder": (r) =>
|
|
337
|
+
r !== null &&
|
|
338
|
+
r.items &&
|
|
339
|
+
r.items.every((item) => item.folderId == folderId),
|
|
340
|
+
});
|
|
341
|
+
const rootResources = listResourcesWithSearch(communityId);
|
|
342
|
+
check(rootResources, {
|
|
343
|
+
"Not providing folder ID returns results": (r) =>
|
|
344
|
+
r !== null && r.items && r.items.length > 0,
|
|
345
|
+
"All results have no folder defined": (r) =>
|
|
346
|
+
r !== null &&
|
|
347
|
+
r.items &&
|
|
348
|
+
r.items.every((item) => item.folderId === undefined),
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
313
352
|
// Test sorting capabilities
|
|
314
353
|
group("Sort resources by different fields", () => {
|
|
315
354
|
// Test sorting by addedDate ASC
|
|
@@ -325,22 +364,29 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
325
364
|
|
|
326
365
|
// Verify ASC order - first item should have earliest date
|
|
327
366
|
if (dateAsc && dateAsc.items && dateAsc.items.length > 1) {
|
|
328
|
-
const dateArray = dateAsc.items.map(item =>
|
|
329
|
-
|
|
367
|
+
const dateArray = dateAsc.items.map((item) =>
|
|
368
|
+
new Date(item.addedDate).getTime(),
|
|
369
|
+
);
|
|
370
|
+
|
|
330
371
|
// Log dates to help debug sorting issues
|
|
331
|
-
console.log(
|
|
332
|
-
|
|
372
|
+
console.log(
|
|
373
|
+
"Dates in ASC order:",
|
|
374
|
+
dateArray.map((d) => new Date(d).toISOString()),
|
|
375
|
+
);
|
|
376
|
+
|
|
333
377
|
const sortedCorrectly = dateArray.slice(1).every((curr, i) => {
|
|
334
378
|
const prev = dateArray[i];
|
|
335
379
|
const isCorrectlySorted = curr >= prev;
|
|
336
|
-
|
|
380
|
+
|
|
337
381
|
if (!isCorrectlySorted) {
|
|
338
|
-
console.log(
|
|
382
|
+
console.log(
|
|
383
|
+
`Sorting issue at index ${i}: ${new Date(prev).toISOString()} should be <= ${new Date(curr).toISOString()}`,
|
|
384
|
+
);
|
|
339
385
|
}
|
|
340
|
-
|
|
386
|
+
|
|
341
387
|
return isCorrectlySorted;
|
|
342
388
|
});
|
|
343
|
-
|
|
389
|
+
|
|
344
390
|
check(dateAsc, {
|
|
345
391
|
"Resources are correctly sorted by date ASC": () => sortedCorrectly,
|
|
346
392
|
});
|
|
@@ -465,7 +511,10 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
465
511
|
"First page returns correct number of items": (r) =>
|
|
466
512
|
r !== null && r.items && r.items.length === 2,
|
|
467
513
|
[`First page has correct pagination metadata`]: (r) =>
|
|
468
|
-
r !== null &&
|
|
514
|
+
r !== null &&
|
|
515
|
+
r.meta &&
|
|
516
|
+
r.meta.currentPage === 1 &&
|
|
517
|
+
r.meta.itemCount === 2,
|
|
469
518
|
});
|
|
470
519
|
|
|
471
520
|
// Get second page
|
|
@@ -477,7 +526,10 @@ export function testResourcesSearchSort(structure: Structure) {
|
|
|
477
526
|
check(secondPage, {
|
|
478
527
|
"Second page returns results": (r) => r !== null && !!r.items,
|
|
479
528
|
"Second page has correct pagination metadata": (r) =>
|
|
480
|
-
r !== null &&
|
|
529
|
+
r !== null &&
|
|
530
|
+
r.meta &&
|
|
531
|
+
r.meta.currentPage === 2 &&
|
|
532
|
+
r.meta.itemCount === 2,
|
|
481
533
|
"Pages return different resources": (r) => {
|
|
482
534
|
if (!r || !r.items || !firstPage || !firstPage.items) return false;
|
|
483
535
|
|
|
@@ -59,7 +59,7 @@ export const options = {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const timestamp = new Date().toISOString();
|
|
62
|
-
const schoolName = `IT
|
|
62
|
+
const schoolName = `IT Community`;
|
|
63
63
|
|
|
64
64
|
// List of app types to test
|
|
65
65
|
// You can adjust this list based on which app types you want to test
|
|
@@ -156,12 +156,7 @@ export function testResourcesApi(structure: Structure) {
|
|
|
156
156
|
for (const appType of APP_TYPES_TO_TEST) {
|
|
157
157
|
group(`Testing ${appType} resources`, () => {
|
|
158
158
|
const resource = DEFAULT_TEST_CONFIGS[appType];
|
|
159
|
-
testResourceManagement(
|
|
160
|
-
communityId,
|
|
161
|
-
resource,
|
|
162
|
-
adminUser,
|
|
163
|
-
memberUser,
|
|
164
|
-
);
|
|
159
|
+
testResourceManagement(communityId, resource, adminUser, memberUser);
|
|
165
160
|
});
|
|
166
161
|
}
|
|
167
162
|
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import http, { RefinedResponse } from "k6/http";
|
|
2
|
+
import { getHeaders } from "../../../node_modules/edifice-k6-commons/dist/index.js";
|
|
3
|
+
|
|
4
|
+
//Types
|
|
5
|
+
export type User = {
|
|
6
|
+
id: number;
|
|
7
|
+
displayName: string;
|
|
8
|
+
entId: string;
|
|
9
|
+
profile: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type Media = {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
mimeType: string;
|
|
17
|
+
url: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type Announcement = {
|
|
21
|
+
id: number;
|
|
22
|
+
content: string;
|
|
23
|
+
media: Media[];
|
|
24
|
+
publicationDate: string;
|
|
25
|
+
modificationDate: string;
|
|
26
|
+
author: User;
|
|
27
|
+
modifier: User;
|
|
28
|
+
communityId: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type AnnouncementCount = {
|
|
32
|
+
count: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type CreateAnnouncementParams = {
|
|
36
|
+
content: string;
|
|
37
|
+
media: Media[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type UpdateAnnouncementParams = {
|
|
41
|
+
content: string;
|
|
42
|
+
media: Media[];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type PaginatedAnnouncements = {
|
|
46
|
+
items: Announcement[];
|
|
47
|
+
meta: {
|
|
48
|
+
totalItems: number;
|
|
49
|
+
currentPage: number;
|
|
50
|
+
itemCount: number;
|
|
51
|
+
totalPages: number;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const rootUrl = __ENV.ROOT_URL || "";
|
|
56
|
+
function baseUrl(id: number): string {
|
|
57
|
+
return `${rootUrl}/communities/api/communities/${id}/announcements`;
|
|
58
|
+
}
|
|
59
|
+
function makeHeaders(): object {
|
|
60
|
+
return {
|
|
61
|
+
headers: { ...getHeaders(), "Content-Type": "application/json" },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a new announcement
|
|
67
|
+
* @param communityId Community ID
|
|
68
|
+
* @param announcementData announcement creation data
|
|
69
|
+
* @returns HTTP response
|
|
70
|
+
*/
|
|
71
|
+
export function createAnnouncement(
|
|
72
|
+
communityId: number,
|
|
73
|
+
announcementData: CreateAnnouncementParams,
|
|
74
|
+
): RefinedResponse<undefined> {
|
|
75
|
+
return http.post<undefined>(
|
|
76
|
+
`${baseUrl(communityId)}`,
|
|
77
|
+
JSON.stringify(announcementData),
|
|
78
|
+
makeHeaders(),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* List all announcements with pagination
|
|
84
|
+
* @param communityId Community ID
|
|
85
|
+
* @param page Page number (default: 1)
|
|
86
|
+
* @param limit Items per page (default: 10)
|
|
87
|
+
* @param publishedAfter Date to filter announcements from (optional)
|
|
88
|
+
* @param sortBy 'publicationDate' or 'ModificationDate' (optional)
|
|
89
|
+
* @param sortDirection 'ASC' or 'DESC' (optional)
|
|
90
|
+
* @returns List of announcements or null if failed
|
|
91
|
+
*/
|
|
92
|
+
export function listAnnouncements(
|
|
93
|
+
communityId: number,
|
|
94
|
+
page: number = 1,
|
|
95
|
+
limit: number = 10,
|
|
96
|
+
publishedAfter: string | null = null,
|
|
97
|
+
sortBy: string | null = null,
|
|
98
|
+
sortDirection: string | null = null,
|
|
99
|
+
): PaginatedAnnouncements | null {
|
|
100
|
+
let urlParams: string = "";
|
|
101
|
+
if (publishedAfter != null) urlParams += `&publishedAfter=${publishedAfter}`;
|
|
102
|
+
if (sortBy != null) urlParams += `&sortBy=${sortBy}`;
|
|
103
|
+
if (sortDirection != null) urlParams += `&sortDirection=${sortDirection}`;
|
|
104
|
+
const response = http.get(
|
|
105
|
+
`${baseUrl(communityId)}?page=${page}&limit=${limit}${urlParams}`,
|
|
106
|
+
makeHeaders(),
|
|
107
|
+
);
|
|
108
|
+
if (response.status === 200) {
|
|
109
|
+
return JSON.parse(<string>response.body);
|
|
110
|
+
} else {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Count all announcements
|
|
117
|
+
* @param communityId Community ID
|
|
118
|
+
* @param publishedAfter Date to filter announcements from (optional)
|
|
119
|
+
* @returns List of announcements or null if failed
|
|
120
|
+
*/
|
|
121
|
+
export function countAnnouncements(
|
|
122
|
+
communityId: number,
|
|
123
|
+
publishedAfter: string | null = null,
|
|
124
|
+
): AnnouncementCount | null {
|
|
125
|
+
const urlParams =
|
|
126
|
+
publishedAfter == null ? "" : `?publishedAfter=${publishedAfter}`;
|
|
127
|
+
const response = http.get(
|
|
128
|
+
`${baseUrl(communityId)}/count${urlParams}`,
|
|
129
|
+
makeHeaders(),
|
|
130
|
+
);
|
|
131
|
+
if (response.status === 200) {
|
|
132
|
+
return JSON.parse(<string>response.body);
|
|
133
|
+
} else {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get a specific announcement by ID
|
|
140
|
+
* @param communityId Community ID
|
|
141
|
+
* @param announcementId Announcement ID
|
|
142
|
+
* @returns Announcement or null if not found
|
|
143
|
+
*/
|
|
144
|
+
export function getAnnouncement(
|
|
145
|
+
communityId: number,
|
|
146
|
+
announcementId: number,
|
|
147
|
+
): Announcement | null {
|
|
148
|
+
const response = http.get(
|
|
149
|
+
`${baseUrl(communityId)}/${announcementId}`,
|
|
150
|
+
makeHeaders(),
|
|
151
|
+
);
|
|
152
|
+
if (response.status === 200) {
|
|
153
|
+
return JSON.parse(<string>response.body);
|
|
154
|
+
} else {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Update an announcement
|
|
161
|
+
* @param communityId Community ID
|
|
162
|
+
* @param announcementId Announcement ID
|
|
163
|
+
* @param updateData Update data
|
|
164
|
+
* @returns Updated announcement or null if failed
|
|
165
|
+
*/
|
|
166
|
+
export function updateAnnouncement(
|
|
167
|
+
communityId: number,
|
|
168
|
+
announcementId: number,
|
|
169
|
+
updateData: UpdateAnnouncementParams,
|
|
170
|
+
): Announcement | null {
|
|
171
|
+
const response = http.put(
|
|
172
|
+
`${baseUrl(communityId)}/${announcementId}`,
|
|
173
|
+
JSON.stringify(updateData),
|
|
174
|
+
makeHeaders(),
|
|
175
|
+
);
|
|
176
|
+
if (response.status === 200) {
|
|
177
|
+
return JSON.parse(<string>response.body);
|
|
178
|
+
} else {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Delete an announcement
|
|
185
|
+
* @param communityId Community ID
|
|
186
|
+
* @param announcementId Announcement ID
|
|
187
|
+
* @returns True if deletion was successful, false otherwise
|
|
188
|
+
*/
|
|
189
|
+
export function deleteAnnouncement(
|
|
190
|
+
communityId: number,
|
|
191
|
+
announcementId: number,
|
|
192
|
+
): boolean {
|
|
193
|
+
const response = http.del(`${baseUrl(communityId)}/${announcementId}`);
|
|
194
|
+
return response.status === 204;
|
|
195
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import http from "k6/http";
|
|
2
|
+
import { getHeaders } from "../../../node_modules/edifice-k6-commons/dist/index.js";
|
|
3
|
+
import { Resource } from "./_resource-api.utils.js";
|
|
4
|
+
import { HttpResponse, success, failure } from "./_http-response.utils.ts";
|
|
5
|
+
|
|
6
|
+
//Types
|
|
7
|
+
export type User = {
|
|
8
|
+
id: number;
|
|
9
|
+
displayName: string;
|
|
10
|
+
entId: string;
|
|
11
|
+
profile: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Folder = {
|
|
15
|
+
id: number;
|
|
16
|
+
name: string;
|
|
17
|
+
creationDate: string;
|
|
18
|
+
modificationDate: string;
|
|
19
|
+
isRoot: boolean;
|
|
20
|
+
creator: User;
|
|
21
|
+
modifier?: User;
|
|
22
|
+
parentId?: number;
|
|
23
|
+
communityId: number;
|
|
24
|
+
stats?: FolderStats;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type FolderStats = {
|
|
28
|
+
childCount: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type FolderDetails = {
|
|
32
|
+
id: number;
|
|
33
|
+
name: string;
|
|
34
|
+
creationDate: string;
|
|
35
|
+
modificationDate: string;
|
|
36
|
+
isRoot: boolean;
|
|
37
|
+
creator: User;
|
|
38
|
+
modifier?: User;
|
|
39
|
+
parentId?: number;
|
|
40
|
+
communityId: number;
|
|
41
|
+
stats?: FolderStats;
|
|
42
|
+
subFolders?: Folder[];
|
|
43
|
+
resources?: Resource[];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type CreateFolderParams = {
|
|
47
|
+
name: string;
|
|
48
|
+
parentId?: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type UpdateFolderParams = {
|
|
52
|
+
name: string;
|
|
53
|
+
parentId?: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type PaginatedFolders = {
|
|
57
|
+
items: Folder[];
|
|
58
|
+
meta: {
|
|
59
|
+
totalItems: number;
|
|
60
|
+
currentPage: number;
|
|
61
|
+
itemCount: number;
|
|
62
|
+
totalPages: number;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const rootUrl = __ENV.ROOT_URL || "";
|
|
67
|
+
function baseUrl(id: number): string {
|
|
68
|
+
return `${rootUrl}/communities/api/communities/${id}/folders`;
|
|
69
|
+
}
|
|
70
|
+
function makeHeaders(): object {
|
|
71
|
+
return {
|
|
72
|
+
headers: { ...getHeaders(), "Content-Type": "application/json" },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function getFolders(
|
|
77
|
+
communityId: number,
|
|
78
|
+
page: number = 1,
|
|
79
|
+
limit: number = 10,
|
|
80
|
+
name: string | undefined = undefined,
|
|
81
|
+
parent: number | undefined = undefined,
|
|
82
|
+
rootOnly: boolean = false,
|
|
83
|
+
): HttpResponse<PaginatedFolders> {
|
|
84
|
+
let urlParams: string = name ? `&name=${name}` : "";
|
|
85
|
+
if (parent) {
|
|
86
|
+
urlParams += `&parentId=${parent}`;
|
|
87
|
+
}
|
|
88
|
+
if (rootOnly) {
|
|
89
|
+
urlParams += `&rootOnly=${rootOnly}`;
|
|
90
|
+
}
|
|
91
|
+
const response = http.get(
|
|
92
|
+
`${baseUrl(communityId)}?page=${page}&limit=${limit}${urlParams}`,
|
|
93
|
+
makeHeaders(),
|
|
94
|
+
);
|
|
95
|
+
if (response.status === 200) {
|
|
96
|
+
return success(JSON.parse(<string>response.body));
|
|
97
|
+
} else {
|
|
98
|
+
return failure(response.status);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function getRootFolders(communityId: number): HttpResponse<Folder[]> {
|
|
103
|
+
const response = http.get(`${baseUrl(communityId)}/root`, makeHeaders());
|
|
104
|
+
if (response.status === 200) {
|
|
105
|
+
return success(JSON.parse(<string>response.body));
|
|
106
|
+
} else {
|
|
107
|
+
return failure(response.status);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function createFolder(
|
|
112
|
+
communityId: number,
|
|
113
|
+
createData: CreateFolderParams,
|
|
114
|
+
): HttpResponse<Folder> {
|
|
115
|
+
const response = http.post(
|
|
116
|
+
`${baseUrl(communityId)}`,
|
|
117
|
+
JSON.stringify(createData),
|
|
118
|
+
makeHeaders(),
|
|
119
|
+
);
|
|
120
|
+
if (response.status === 201) {
|
|
121
|
+
return success(JSON.parse(<string>response.body));
|
|
122
|
+
} else {
|
|
123
|
+
return failure(response.status);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function updateFolder(
|
|
128
|
+
communityId: number,
|
|
129
|
+
folderId: number,
|
|
130
|
+
updateData: UpdateFolderParams,
|
|
131
|
+
): HttpResponse<Folder> {
|
|
132
|
+
const response = http.put(
|
|
133
|
+
`${baseUrl(communityId)}/${folderId}`,
|
|
134
|
+
JSON.stringify(updateData),
|
|
135
|
+
makeHeaders(),
|
|
136
|
+
);
|
|
137
|
+
if (response.status === 200) {
|
|
138
|
+
return success(JSON.parse(<string>response.body));
|
|
139
|
+
} else {
|
|
140
|
+
return failure(response.status);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getFolderContent(
|
|
145
|
+
communityId: number,
|
|
146
|
+
folderId: number,
|
|
147
|
+
): HttpResponse<FolderDetails> {
|
|
148
|
+
const response = http.get(
|
|
149
|
+
`${baseUrl(communityId)}/${folderId}`,
|
|
150
|
+
makeHeaders(),
|
|
151
|
+
);
|
|
152
|
+
if (response.status === 200) {
|
|
153
|
+
return success(JSON.parse(<string>response.body));
|
|
154
|
+
} else {
|
|
155
|
+
return failure(response.status);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function removeFolder(
|
|
160
|
+
communityId: number,
|
|
161
|
+
folderId: number,
|
|
162
|
+
): HttpResponse<boolean> {
|
|
163
|
+
const response = http.del(`${baseUrl(communityId)}/${folderId}`);
|
|
164
|
+
if (response.status === 204) {
|
|
165
|
+
return success(true);
|
|
166
|
+
} else {
|
|
167
|
+
return failure(response.status);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function addResourceToFolder(
|
|
172
|
+
communityId: number,
|
|
173
|
+
folderId: number,
|
|
174
|
+
resourceId: number,
|
|
175
|
+
): HttpResponse<boolean> {
|
|
176
|
+
const response = http.post(
|
|
177
|
+
`${baseUrl(communityId)}/${folderId}/resources/${resourceId}`,
|
|
178
|
+
);
|
|
179
|
+
if (response.status === 204) {
|
|
180
|
+
return success(true);
|
|
181
|
+
} else {
|
|
182
|
+
return failure(response.status);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function removeResourceFromFolder(
|
|
187
|
+
communityId: number,
|
|
188
|
+
folderId: number,
|
|
189
|
+
resourceId: number,
|
|
190
|
+
): HttpResponse<boolean> {
|
|
191
|
+
const response = http.del(
|
|
192
|
+
`${baseUrl(communityId)}/${folderId}/resources/${resourceId}`,
|
|
193
|
+
);
|
|
194
|
+
if (response.status === 204) {
|
|
195
|
+
return success(true);
|
|
196
|
+
} else {
|
|
197
|
+
return failure(response.status);
|
|
198
|
+
}
|
|
199
|
+
}
|