@tellescope/sdk 1.245.0 → 1.246.1
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/lib/cjs/tests/api_tests/beluga_pharmacy_mappings.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/beluga_pharmacy_mappings.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/beluga_pharmacy_mappings.test.js +357 -0
- package/lib/cjs/tests/api_tests/beluga_pharmacy_mappings.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js +163 -0
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js +268 -0
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/time_tracks.test.d.ts +20 -0
- package/lib/cjs/tests/api_tests/time_tracks.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/time_tracks.test.js +692 -20
- package/lib/cjs/tests/api_tests/time_tracks.test.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +137 -118
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/tests/api_tests/beluga_pharmacy_mappings.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/beluga_pharmacy_mappings.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/beluga_pharmacy_mappings.test.js +353 -0
- package/lib/esm/tests/api_tests/beluga_pharmacy_mappings.test.js.map +1 -0
- package/lib/esm/tests/api_tests/calendar_event_limits.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/calendar_event_limits.test.js +163 -0
- package/lib/esm/tests/api_tests/calendar_event_limits.test.js.map +1 -1
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js +264 -0
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js.map +1 -0
- package/lib/esm/tests/api_tests/time_tracks.test.d.ts +20 -0
- package/lib/esm/tests/api_tests/time_tracks.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/time_tracks.test.js +687 -20
- package/lib/esm/tests/api_tests/time_tracks.test.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +138 -119
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/tests/api_tests/beluga_pharmacy_mappings.test.ts +351 -0
- package/src/tests/api_tests/calendar_event_limits.test.ts +195 -0
- package/src/tests/api_tests/time_tracks.test.ts +542 -16
- package/src/tests/tests.ts +10 -3
- package/test_generated.pdf +0 -0
|
@@ -45,13 +45,34 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
45
45
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.time_tracks_tests = void 0;
|
|
48
|
+
exports.time_tracks_edge_case_tests = exports.time_tracks_lock_tests = exports.time_tracks_review_tests = exports.time_tracks_correction_tests = exports.time_tracks_historical_tests = exports.time_tracks_tests = void 0;
|
|
49
49
|
require('source-map-support').install();
|
|
50
50
|
var sdk_1 = require("../../sdk");
|
|
51
51
|
var testing_1 = require("@tellescope/testing");
|
|
52
52
|
var setup_1 = require("../setup");
|
|
53
53
|
var log = console.log;
|
|
54
54
|
var host = process.env.REACT_APP_TELLESCOPE_API_URL || 'http://localhost:8080';
|
|
55
|
+
// Helper to assert that an async function throws an error
|
|
56
|
+
var assert_throws = function (fn, description) { return __awaiter(void 0, void 0, void 0, function () {
|
|
57
|
+
var e_1;
|
|
58
|
+
return __generator(this, function (_a) {
|
|
59
|
+
switch (_a.label) {
|
|
60
|
+
case 0:
|
|
61
|
+
_a.trys.push([0, 2, , 3]);
|
|
62
|
+
return [4 /*yield*/, fn()];
|
|
63
|
+
case 1:
|
|
64
|
+
_a.sent();
|
|
65
|
+
(0, testing_1.assert)(false, "".concat(description, " - expected error but succeeded"));
|
|
66
|
+
return [3 /*break*/, 3];
|
|
67
|
+
case 2:
|
|
68
|
+
e_1 = _a.sent();
|
|
69
|
+
// SDK parseError returns the response body { message, info } for 4xx errors
|
|
70
|
+
(0, testing_1.assert)((e_1 === null || e_1 === void 0 ? void 0 : e_1.code) === 400 || (e_1 === null || e_1 === void 0 ? void 0 : e_1.statusCode) === 400 || typeof (e_1 === null || e_1 === void 0 ? void 0 : e_1.message) === 'string', "".concat(description, " - expected error, got: ").concat(JSON.stringify(e_1)));
|
|
71
|
+
return [3 /*break*/, 3];
|
|
72
|
+
case 3: return [2 /*return*/];
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}); };
|
|
55
76
|
// Unit tests for calculateTimeTrackDuration
|
|
56
77
|
var test_calculateTimeTrackDuration = function () {
|
|
57
78
|
(0, testing_1.log_header)("calculateTimeTrackDuration Unit Tests");
|
|
@@ -101,13 +122,13 @@ var test_calculateTimeTrackDuration = function () {
|
|
|
101
122
|
{ type: 'pause', timestamp: new Date('2024-01-01T12:05:00Z') }, // 5 min
|
|
102
123
|
]);
|
|
103
124
|
(0, testing_1.assert)(test7 === 2700000, "Three intervals (10+30+5 min) should be 2700000 ms, got ".concat(test7));
|
|
104
|
-
log("
|
|
125
|
+
log("All calculateTimeTrackDuration unit tests passed");
|
|
105
126
|
};
|
|
106
127
|
// API tests for time_tracks CRUD operations
|
|
107
128
|
var time_tracks_tests = function (_a) {
|
|
108
129
|
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
109
130
|
return __awaiter(void 0, void 0, void 0, function () {
|
|
110
|
-
var userId, createdTimeTrackId, enduserId, timeTrack_1, fetchedTimeTrack, allTimeTracks, enduser, linkedTimeTrack_1, pauseTime, pausedTimeTrack, resumeTime, resumedTimeTrack, closedAt, closedTimeTrack, finalTimeTrack, updatedTimeTrack, allUserTimeTracks, activeTimeTracks, nonAdminTimeTracks, hasOtherUserTimeTrack, deletedCheck, stillExists,
|
|
131
|
+
var userId, createdTimeTrackId, enduserId, timeTrack_1, fetchedTimeTrack, allTimeTracks, enduser, linkedTimeTrack_1, pauseTime, pausedTimeTrack, resumeTime, resumedTimeTrack, closedAt, closedTimeTrack, finalTimeTrack, updatedTimeTrack, allUserTimeTracks, activeTimeTracks, nonAdminTimeTracks, hasOtherUserTimeTrack, deletedCheck, stillExists, e_2, e_3;
|
|
111
132
|
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
112
133
|
return __generator(this, function (_p) {
|
|
113
134
|
switch (_p.label) {
|
|
@@ -132,7 +153,7 @@ var time_tracks_tests = function (_a) {
|
|
|
132
153
|
(0, testing_1.assert)(((_d = timeTrack_1.timestamps) === null || _d === void 0 ? void 0 : _d[0].type) === 'start', "First timestamp should be 'start', got ".concat((_e = timeTrack_1.timestamps) === null || _e === void 0 ? void 0 : _e[0].type));
|
|
133
154
|
(0, testing_1.assert)(!timeTrack_1.closedAt, "closedAt should not be set initially");
|
|
134
155
|
(0, testing_1.assert)(!timeTrack_1.totalDurationInMS, "totalDurationInMS should not be set initially");
|
|
135
|
-
log("
|
|
156
|
+
log("Time track created with auto-set userId and initial timestamp");
|
|
136
157
|
// Test 2: Read the time track
|
|
137
158
|
log("Reading time track...");
|
|
138
159
|
return [4 /*yield*/, sdk.api.time_tracks.getOne(timeTrack_1.id)];
|
|
@@ -140,7 +161,7 @@ var time_tracks_tests = function (_a) {
|
|
|
140
161
|
fetchedTimeTrack = _p.sent();
|
|
141
162
|
(0, testing_1.assert)(fetchedTimeTrack.id === timeTrack_1.id, "Fetched time track should have same id");
|
|
142
163
|
(0, testing_1.assert)(fetchedTimeTrack.title === "Test Time Track", "Fetched title should match");
|
|
143
|
-
log("
|
|
164
|
+
log("Time track retrieved successfully");
|
|
144
165
|
// Test 3: Get all time tracks for current user
|
|
145
166
|
log("Getting all time tracks for current user...");
|
|
146
167
|
return [4 /*yield*/, sdk.api.time_tracks.getSome({ filter: { userId: userId } })];
|
|
@@ -148,7 +169,7 @@ var time_tracks_tests = function (_a) {
|
|
|
148
169
|
allTimeTracks = _p.sent();
|
|
149
170
|
(0, testing_1.assert)(allTimeTracks.length >= 1, "Should have at least 1 time track, got ".concat(allTimeTracks.length));
|
|
150
171
|
(0, testing_1.assert)(!!allTimeTracks.find(function (t) { return t.id === timeTrack_1.id; }), "Should find our created time track");
|
|
151
|
-
log("
|
|
172
|
+
log("Retrieved all time tracks for user");
|
|
152
173
|
// Test 4: Create enduser and link time track
|
|
153
174
|
log("Creating enduser for time track linkage...");
|
|
154
175
|
return [4 /*yield*/, sdk.api.endusers.createOne({
|
|
@@ -159,7 +180,7 @@ var time_tracks_tests = function (_a) {
|
|
|
159
180
|
case 5:
|
|
160
181
|
enduser = _p.sent();
|
|
161
182
|
enduserId = enduser.id;
|
|
162
|
-
log("
|
|
183
|
+
log("Enduser created");
|
|
163
184
|
// Test 5: Create time track with enduserId
|
|
164
185
|
log("Creating time track linked to enduser...");
|
|
165
186
|
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
@@ -169,7 +190,7 @@ var time_tracks_tests = function (_a) {
|
|
|
169
190
|
case 6:
|
|
170
191
|
linkedTimeTrack_1 = _p.sent();
|
|
171
192
|
(0, testing_1.assert)(linkedTimeTrack_1.enduserId === enduser.id, "enduserId should be set to ".concat(enduser.id, ", got ").concat(linkedTimeTrack_1.enduserId));
|
|
172
|
-
log("
|
|
193
|
+
log("Time track linked to enduser");
|
|
173
194
|
// Test 6: Update time track - add pause timestamp
|
|
174
195
|
log("Adding pause timestamp...");
|
|
175
196
|
pauseTime = new Date();
|
|
@@ -182,7 +203,7 @@ var time_tracks_tests = function (_a) {
|
|
|
182
203
|
pausedTimeTrack = _p.sent();
|
|
183
204
|
(0, testing_1.assert)(((_f = pausedTimeTrack.timestamps) === null || _f === void 0 ? void 0 : _f.length) === 2, "Should have 2 timestamps after pause, got ".concat((_g = pausedTimeTrack.timestamps) === null || _g === void 0 ? void 0 : _g.length));
|
|
184
205
|
(0, testing_1.assert)(((_h = pausedTimeTrack.timestamps) === null || _h === void 0 ? void 0 : _h[1].type) === 'pause', "Second timestamp should be 'pause', got ".concat((_j = pausedTimeTrack.timestamps) === null || _j === void 0 ? void 0 : _j[1].type));
|
|
185
|
-
log("
|
|
206
|
+
log("Pause timestamp added");
|
|
186
207
|
// Test 7: Update time track - add resume timestamp
|
|
187
208
|
log("Adding resume timestamp...");
|
|
188
209
|
resumeTime = new Date();
|
|
@@ -195,7 +216,7 @@ var time_tracks_tests = function (_a) {
|
|
|
195
216
|
resumedTimeTrack = _p.sent();
|
|
196
217
|
(0, testing_1.assert)(((_k = resumedTimeTrack.timestamps) === null || _k === void 0 ? void 0 : _k.length) === 3, "Should have 3 timestamps after resume, got ".concat((_l = resumedTimeTrack.timestamps) === null || _l === void 0 ? void 0 : _l.length));
|
|
197
218
|
(0, testing_1.assert)(((_m = resumedTimeTrack.timestamps) === null || _m === void 0 ? void 0 : _m[2].type) === 'resume', "Third timestamp should be 'resume', got ".concat((_o = resumedTimeTrack.timestamps) === null || _o === void 0 ? void 0 : _o[2].type));
|
|
198
|
-
log("
|
|
219
|
+
log("Resume timestamp added");
|
|
199
220
|
// Test 8: Close time track and verify auto-calculation
|
|
200
221
|
log("Closing time track with closedAt...");
|
|
201
222
|
closedAt = new Date();
|
|
@@ -219,7 +240,7 @@ var time_tracks_tests = function (_a) {
|
|
|
219
240
|
(0, testing_1.assert)(!!finalTimeTrack.closedAt, "closedAt should be set");
|
|
220
241
|
(0, testing_1.assert)(typeof finalTimeTrack.totalDurationInMS === 'number', "totalDurationInMS should be a number, got ".concat(typeof finalTimeTrack.totalDurationInMS));
|
|
221
242
|
(0, testing_1.assert)(finalTimeTrack.totalDurationInMS > 0, "totalDurationInMS should be > 0, got ".concat(finalTimeTrack.totalDurationInMS));
|
|
222
|
-
log("
|
|
243
|
+
log("Time track closed with auto-calculated duration: ".concat(finalTimeTrack.totalDurationInMS, " ms"));
|
|
223
244
|
// Test 9: Update title
|
|
224
245
|
log("Updating time track title...");
|
|
225
246
|
return [4 /*yield*/, sdk.api.time_tracks.updateOne(timeTrack_1.id, {
|
|
@@ -228,7 +249,7 @@ var time_tracks_tests = function (_a) {
|
|
|
228
249
|
case 12:
|
|
229
250
|
updatedTimeTrack = _p.sent();
|
|
230
251
|
(0, testing_1.assert)(updatedTimeTrack.title === "Updated Time Track Title", "Title should be updated");
|
|
231
|
-
log("
|
|
252
|
+
log("Time track title updated");
|
|
232
253
|
// Test 10: Filter by closedAt (get active time tracks)
|
|
233
254
|
log("Filtering for active time tracks (no closedAt)...");
|
|
234
255
|
return [4 /*yield*/, sdk.api.time_tracks.getSome({
|
|
@@ -239,7 +260,7 @@ var time_tracks_tests = function (_a) {
|
|
|
239
260
|
activeTimeTracks = allUserTimeTracks.filter(function (t) { return !t.closedAt; });
|
|
240
261
|
(0, testing_1.assert)(!activeTimeTracks.find(function (t) { return t.id === timeTrack_1.id; }), "Closed time track should not appear in active filter");
|
|
241
262
|
(0, testing_1.assert)(!!activeTimeTracks.find(function (t) { return t.id === linkedTimeTrack_1.id; }), "Unclosed time track should appear in active filter");
|
|
242
|
-
log("
|
|
263
|
+
log("Active time tracks filtered correctly");
|
|
243
264
|
// Test 11: Access control - non-admin user should only see their own time tracks
|
|
244
265
|
log("Testing access control with non-admin user...");
|
|
245
266
|
return [4 /*yield*/, sdkNonAdmin.api.time_tracks.getSome({})];
|
|
@@ -247,7 +268,7 @@ var time_tracks_tests = function (_a) {
|
|
|
247
268
|
nonAdminTimeTracks = _p.sent();
|
|
248
269
|
hasOtherUserTimeTrack = nonAdminTimeTracks.find(function (t) { return t.userId !== sdkNonAdmin.userInfo.id; });
|
|
249
270
|
(0, testing_1.assert)(!hasOtherUserTimeTrack, "Non-admin user should not see other users' time tracks");
|
|
250
|
-
log("
|
|
271
|
+
log("Access control working correctly");
|
|
251
272
|
// Test 12: Delete time tracks
|
|
252
273
|
log("Deleting time tracks...");
|
|
253
274
|
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(timeTrack_1.id)];
|
|
@@ -261,8 +282,8 @@ var time_tracks_tests = function (_a) {
|
|
|
261
282
|
deletedCheck = _p.sent();
|
|
262
283
|
stillExists = deletedCheck.filter(function (t) { return t.id === timeTrack_1.id || t.id === linkedTimeTrack_1.id; });
|
|
263
284
|
(0, testing_1.assert)(stillExists.length === 0, "Time tracks should be deleted");
|
|
264
|
-
log("
|
|
265
|
-
log("
|
|
285
|
+
log("Time tracks deleted successfully");
|
|
286
|
+
log("All time tracks API tests passed!");
|
|
266
287
|
return [3 /*break*/, 27];
|
|
267
288
|
case 18:
|
|
268
289
|
if (!createdTimeTrackId) return [3 /*break*/, 22];
|
|
@@ -274,7 +295,7 @@ var time_tracks_tests = function (_a) {
|
|
|
274
295
|
_p.sent();
|
|
275
296
|
return [3 /*break*/, 22];
|
|
276
297
|
case 21:
|
|
277
|
-
|
|
298
|
+
e_2 = _p.sent();
|
|
278
299
|
return [3 /*break*/, 22];
|
|
279
300
|
case 22:
|
|
280
301
|
if (!enduserId) return [3 /*break*/, 26];
|
|
@@ -286,7 +307,7 @@ var time_tracks_tests = function (_a) {
|
|
|
286
307
|
_p.sent();
|
|
287
308
|
return [3 /*break*/, 26];
|
|
288
309
|
case 25:
|
|
289
|
-
|
|
310
|
+
e_3 = _p.sent();
|
|
290
311
|
return [3 /*break*/, 26];
|
|
291
312
|
case 26: return [7 /*endfinally*/];
|
|
292
313
|
case 27: return [2 /*return*/];
|
|
@@ -295,6 +316,642 @@ var time_tracks_tests = function (_a) {
|
|
|
295
316
|
});
|
|
296
317
|
};
|
|
297
318
|
exports.time_tracks_tests = time_tracks_tests;
|
|
319
|
+
// ============================================================
|
|
320
|
+
// Group A: Historical Time Track Creation
|
|
321
|
+
// ============================================================
|
|
322
|
+
var time_tracks_historical_tests = function (_a) {
|
|
323
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
324
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
325
|
+
var trackIds, now_1, oneHourAgo, twoHoursAgo_1, historical_1, fetched, _i, trackIds_1, id, e_4;
|
|
326
|
+
var _b;
|
|
327
|
+
return __generator(this, function (_c) {
|
|
328
|
+
switch (_c.label) {
|
|
329
|
+
case 0:
|
|
330
|
+
(0, testing_1.log_header)("Time Tracks - Historical Creation Tests");
|
|
331
|
+
trackIds = [];
|
|
332
|
+
_c.label = 1;
|
|
333
|
+
case 1:
|
|
334
|
+
_c.trys.push([1, , 7, 14]);
|
|
335
|
+
now_1 = new Date();
|
|
336
|
+
oneHourAgo = new Date(now_1.getTime() - 3600000);
|
|
337
|
+
twoHoursAgo_1 = new Date(now_1.getTime() - 7200000);
|
|
338
|
+
// Test A1: Create historical time track with all required fields
|
|
339
|
+
log("A1: Creating historical time track with all required fields...");
|
|
340
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
341
|
+
title: "Historical Entry",
|
|
342
|
+
isHistorical: true,
|
|
343
|
+
closedAt: now_1,
|
|
344
|
+
lockedAt: now_1,
|
|
345
|
+
lockedByUserId: sdk.userInfo.id,
|
|
346
|
+
totalDurationInMS: 3600000,
|
|
347
|
+
timestamps: [
|
|
348
|
+
{ type: 'start', timestamp: twoHoursAgo_1 },
|
|
349
|
+
{ type: 'pause', timestamp: oneHourAgo },
|
|
350
|
+
],
|
|
351
|
+
})];
|
|
352
|
+
case 2:
|
|
353
|
+
historical_1 = _c.sent();
|
|
354
|
+
trackIds.push(historical_1.id);
|
|
355
|
+
(0, testing_1.assert)(historical_1.isHistorical === true, "isHistorical should be true");
|
|
356
|
+
(0, testing_1.assert)(!!historical_1.closedAt, "closedAt should be set");
|
|
357
|
+
(0, testing_1.assert)(!!historical_1.lockedAt, "lockedAt should be set");
|
|
358
|
+
(0, testing_1.assert)(historical_1.lockedByUserId === sdk.userInfo.id, "lockedByUserId should match");
|
|
359
|
+
(0, testing_1.assert)(historical_1.totalDurationInMS === 3600000, "totalDurationInMS should be 3600000, got ".concat(historical_1.totalDurationInMS));
|
|
360
|
+
(0, testing_1.assert)(((_b = historical_1.timestamps) === null || _b === void 0 ? void 0 : _b.length) === 2, "timestamps should have 2 entries");
|
|
361
|
+
log("A1: Historical time track created with all fields persisted");
|
|
362
|
+
// Test A2: Create historical without closedAt - expect 400
|
|
363
|
+
log("A2: Creating historical without closedAt (should fail)...");
|
|
364
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.createOne({
|
|
365
|
+
title: "Missing ClosedAt",
|
|
366
|
+
isHistorical: true,
|
|
367
|
+
lockedAt: now_1,
|
|
368
|
+
lockedByUserId: sdk.userInfo.id,
|
|
369
|
+
totalDurationInMS: 3600000,
|
|
370
|
+
timestamps: [{ type: 'start', timestamp: twoHoursAgo_1 }],
|
|
371
|
+
}); }, "A2: Historical without closedAt")];
|
|
372
|
+
case 3:
|
|
373
|
+
_c.sent();
|
|
374
|
+
log("A2: Correctly rejected historical without closedAt");
|
|
375
|
+
// Test A3: Create historical without lockedAt - expect 400
|
|
376
|
+
log("A3: Creating historical without lockedAt (should fail)...");
|
|
377
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.createOne({
|
|
378
|
+
title: "Missing LockedAt",
|
|
379
|
+
isHistorical: true,
|
|
380
|
+
closedAt: now_1,
|
|
381
|
+
lockedByUserId: sdk.userInfo.id,
|
|
382
|
+
totalDurationInMS: 3600000,
|
|
383
|
+
timestamps: [{ type: 'start', timestamp: twoHoursAgo_1 }],
|
|
384
|
+
}); }, "A3: Historical without lockedAt")];
|
|
385
|
+
case 4:
|
|
386
|
+
_c.sent();
|
|
387
|
+
log("A3: Correctly rejected historical without lockedAt");
|
|
388
|
+
// Test A4: Verify isHistorical cannot be updated (updatesDisabled)
|
|
389
|
+
log("A4: Attempting to update isHistorical (should be rejected)...");
|
|
390
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(historical_1.id, {
|
|
391
|
+
isHistorical: false,
|
|
392
|
+
}); }, "A4: isHistorical update should be rejected")
|
|
393
|
+
// Confirm it's still true
|
|
394
|
+
];
|
|
395
|
+
case 5:
|
|
396
|
+
_c.sent();
|
|
397
|
+
return [4 /*yield*/, sdk.api.time_tracks.getOne(historical_1.id)];
|
|
398
|
+
case 6:
|
|
399
|
+
fetched = _c.sent();
|
|
400
|
+
(0, testing_1.assert)(fetched.isHistorical === true, "isHistorical should remain true after rejected update");
|
|
401
|
+
log("A4: isHistorical correctly rejected on update");
|
|
402
|
+
log("All historical creation tests passed!");
|
|
403
|
+
return [3 /*break*/, 14];
|
|
404
|
+
case 7:
|
|
405
|
+
_i = 0, trackIds_1 = trackIds;
|
|
406
|
+
_c.label = 8;
|
|
407
|
+
case 8:
|
|
408
|
+
if (!(_i < trackIds_1.length)) return [3 /*break*/, 13];
|
|
409
|
+
id = trackIds_1[_i];
|
|
410
|
+
_c.label = 9;
|
|
411
|
+
case 9:
|
|
412
|
+
_c.trys.push([9, 11, , 12]);
|
|
413
|
+
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(id)];
|
|
414
|
+
case 10:
|
|
415
|
+
_c.sent();
|
|
416
|
+
return [3 /*break*/, 12];
|
|
417
|
+
case 11:
|
|
418
|
+
e_4 = _c.sent();
|
|
419
|
+
return [3 /*break*/, 12];
|
|
420
|
+
case 12:
|
|
421
|
+
_i++;
|
|
422
|
+
return [3 /*break*/, 8];
|
|
423
|
+
case 13: return [7 /*endfinally*/];
|
|
424
|
+
case 14: return [2 /*return*/];
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
};
|
|
429
|
+
exports.time_tracks_historical_tests = time_tracks_historical_tests;
|
|
430
|
+
// ============================================================
|
|
431
|
+
// Group B: Correction Flow
|
|
432
|
+
// ============================================================
|
|
433
|
+
var time_tracks_correction_tests = function (_a) {
|
|
434
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
435
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
436
|
+
var trackIds, now, track_1, closedAt, closed_1, originalDuration, correctionTime, correctedTrack_1, track2_1, closed2_1, _i, trackIds_2, id, e_5;
|
|
437
|
+
return __generator(this, function (_b) {
|
|
438
|
+
switch (_b.label) {
|
|
439
|
+
case 0:
|
|
440
|
+
(0, testing_1.log_header)("Time Tracks - Correction Flow Tests");
|
|
441
|
+
trackIds = [];
|
|
442
|
+
_b.label = 1;
|
|
443
|
+
case 1:
|
|
444
|
+
_b.trys.push([1, , 16, 23]);
|
|
445
|
+
now = new Date();
|
|
446
|
+
// Create a real-time track and close it
|
|
447
|
+
log("B0: Creating and closing real-time track...");
|
|
448
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
449
|
+
title: "Track for Correction",
|
|
450
|
+
})];
|
|
451
|
+
case 2:
|
|
452
|
+
track_1 = _b.sent();
|
|
453
|
+
trackIds.push(track_1.id);
|
|
454
|
+
// Add pause
|
|
455
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track_1.id, {
|
|
456
|
+
timestamps: __spreadArray(__spreadArray([], (track_1.timestamps || []), true), [
|
|
457
|
+
{ type: 'pause', timestamp: new Date() },
|
|
458
|
+
], false)
|
|
459
|
+
}, { replaceObjectFields: true })
|
|
460
|
+
// Close it
|
|
461
|
+
];
|
|
462
|
+
case 3:
|
|
463
|
+
// Add pause
|
|
464
|
+
_b.sent();
|
|
465
|
+
closedAt = new Date();
|
|
466
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track_1.id, { closedAt: closedAt })
|
|
467
|
+
// Wait for auto-calculated duration
|
|
468
|
+
];
|
|
469
|
+
case 4:
|
|
470
|
+
_b.sent();
|
|
471
|
+
// Wait for auto-calculated duration
|
|
472
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, 1500)];
|
|
473
|
+
case 5:
|
|
474
|
+
// Wait for auto-calculated duration
|
|
475
|
+
_b.sent();
|
|
476
|
+
return [4 /*yield*/, sdk.api.time_tracks.getOne(track_1.id)];
|
|
477
|
+
case 6:
|
|
478
|
+
closed_1 = _b.sent();
|
|
479
|
+
(0, testing_1.assert)(!!closed_1.closedAt, "Track should be closed");
|
|
480
|
+
(0, testing_1.assert)(typeof closed_1.totalDurationInMS === 'number', "Should have auto-calculated totalDurationInMS");
|
|
481
|
+
originalDuration = closed_1.totalDurationInMS;
|
|
482
|
+
log("B0: Track closed with auto-calculated duration: ".concat(originalDuration, " ms"));
|
|
483
|
+
// Test B1: Apply correction with all required fields
|
|
484
|
+
log("B1: Applying correction with all required fields...");
|
|
485
|
+
correctionTime = new Date();
|
|
486
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track_1.id, {
|
|
487
|
+
correctedAt: correctionTime,
|
|
488
|
+
correctedByUserId: sdk.userInfo.id,
|
|
489
|
+
correctionNote: "Forgot to pause during lunch",
|
|
490
|
+
originalTotalDurationInMS: originalDuration,
|
|
491
|
+
totalDurationInMS: originalDuration - 1800000,
|
|
492
|
+
lockedAt: correctionTime,
|
|
493
|
+
lockedByUserId: sdk.userInfo.id,
|
|
494
|
+
})];
|
|
495
|
+
case 7:
|
|
496
|
+
correctedTrack_1 = _b.sent();
|
|
497
|
+
(0, testing_1.assert)(!!correctedTrack_1.correctedAt, "correctedAt should be set");
|
|
498
|
+
(0, testing_1.assert)(correctedTrack_1.correctedByUserId === sdk.userInfo.id, "correctedByUserId should match");
|
|
499
|
+
(0, testing_1.assert)(correctedTrack_1.correctionNote === "Forgot to pause during lunch", "correctionNote should match");
|
|
500
|
+
(0, testing_1.assert)(correctedTrack_1.originalTotalDurationInMS === originalDuration, "originalTotalDurationInMS should preserve old value");
|
|
501
|
+
(0, testing_1.assert)(correctedTrack_1.totalDurationInMS === originalDuration - 1800000, "totalDurationInMS should be corrected value");
|
|
502
|
+
(0, testing_1.assert)(!!correctedTrack_1.lockedAt, "lockedAt should be set");
|
|
503
|
+
log("B1: Correction applied successfully with all fields persisted");
|
|
504
|
+
// Test B2: Correction without originalTotalDurationInMS - expect 400
|
|
505
|
+
log("B2: Correction without originalTotalDurationInMS (should fail)...");
|
|
506
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({ title: "Track for B2" })];
|
|
507
|
+
case 8:
|
|
508
|
+
track2_1 = _b.sent();
|
|
509
|
+
trackIds.push(track2_1.id);
|
|
510
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track2_1.id, { closedAt: new Date() })];
|
|
511
|
+
case 9:
|
|
512
|
+
_b.sent();
|
|
513
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, 1000)];
|
|
514
|
+
case 10:
|
|
515
|
+
_b.sent();
|
|
516
|
+
return [4 /*yield*/, sdk.api.time_tracks.getOne(track2_1.id)];
|
|
517
|
+
case 11:
|
|
518
|
+
closed2_1 = _b.sent();
|
|
519
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(track2_1.id, {
|
|
520
|
+
correctedAt: new Date(),
|
|
521
|
+
totalDurationInMS: 1000,
|
|
522
|
+
lockedAt: new Date(),
|
|
523
|
+
lockedByUserId: sdk.userInfo.id,
|
|
524
|
+
}); }, "B2: Correction without originalTotalDurationInMS")];
|
|
525
|
+
case 12:
|
|
526
|
+
_b.sent();
|
|
527
|
+
log("B2: Correctly rejected correction without originalTotalDurationInMS");
|
|
528
|
+
// Test B3: Correction without lockedAt - expect 400
|
|
529
|
+
log("B3: Correction without lockedAt (should fail)...");
|
|
530
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(track2_1.id, {
|
|
531
|
+
correctedAt: new Date(),
|
|
532
|
+
originalTotalDurationInMS: closed2_1.totalDurationInMS || 0,
|
|
533
|
+
totalDurationInMS: 1000,
|
|
534
|
+
lockedByUserId: sdk.userInfo.id,
|
|
535
|
+
}); }, "B3: Correction without lockedAt")];
|
|
536
|
+
case 13:
|
|
537
|
+
_b.sent();
|
|
538
|
+
log("B3: Correctly rejected correction without lockedAt");
|
|
539
|
+
// Test B4: After lock, attempt to update title - expect 400
|
|
540
|
+
log("B4: Updating title on locked track (should fail)...");
|
|
541
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(track_1.id, {
|
|
542
|
+
title: "Should Not Work",
|
|
543
|
+
}); }, "B4: Title update on locked track")];
|
|
544
|
+
case 14:
|
|
545
|
+
_b.sent();
|
|
546
|
+
log("B4: Correctly rejected title update on locked track");
|
|
547
|
+
// Test B5: After lock, attempt second correction - expect 400
|
|
548
|
+
log("B5: Second correction on locked track (should fail)...");
|
|
549
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(track_1.id, {
|
|
550
|
+
correctedAt: new Date(),
|
|
551
|
+
originalTotalDurationInMS: correctedTrack_1.totalDurationInMS,
|
|
552
|
+
totalDurationInMS: 500,
|
|
553
|
+
lockedAt: new Date(),
|
|
554
|
+
lockedByUserId: sdk.userInfo.id,
|
|
555
|
+
}); }, "B5: Second correction on locked track")];
|
|
556
|
+
case 15:
|
|
557
|
+
_b.sent();
|
|
558
|
+
log("B5: Correctly rejected second correction on locked track");
|
|
559
|
+
log("All correction flow tests passed!");
|
|
560
|
+
return [3 /*break*/, 23];
|
|
561
|
+
case 16:
|
|
562
|
+
_i = 0, trackIds_2 = trackIds;
|
|
563
|
+
_b.label = 17;
|
|
564
|
+
case 17:
|
|
565
|
+
if (!(_i < trackIds_2.length)) return [3 /*break*/, 22];
|
|
566
|
+
id = trackIds_2[_i];
|
|
567
|
+
_b.label = 18;
|
|
568
|
+
case 18:
|
|
569
|
+
_b.trys.push([18, 20, , 21]);
|
|
570
|
+
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(id)];
|
|
571
|
+
case 19:
|
|
572
|
+
_b.sent();
|
|
573
|
+
return [3 /*break*/, 21];
|
|
574
|
+
case 20:
|
|
575
|
+
e_5 = _b.sent();
|
|
576
|
+
return [3 /*break*/, 21];
|
|
577
|
+
case 21:
|
|
578
|
+
_i++;
|
|
579
|
+
return [3 /*break*/, 17];
|
|
580
|
+
case 22: return [7 /*endfinally*/];
|
|
581
|
+
case 23: return [2 /*return*/];
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
};
|
|
586
|
+
exports.time_tracks_correction_tests = time_tracks_correction_tests;
|
|
587
|
+
// ============================================================
|
|
588
|
+
// Group C: Review Flow
|
|
589
|
+
// ============================================================
|
|
590
|
+
var time_tracks_review_tests = function (_a) {
|
|
591
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
592
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
593
|
+
var trackIds, now, oneHourAgo, twoHoursAgo, historical, reviewTime, reviewed, historical2_1, updatedReview, historical3, rejected, _i, trackIds_3, id, e_6;
|
|
594
|
+
return __generator(this, function (_b) {
|
|
595
|
+
switch (_b.label) {
|
|
596
|
+
case 0:
|
|
597
|
+
(0, testing_1.log_header)("Time Tracks - Review Flow Tests");
|
|
598
|
+
trackIds = [];
|
|
599
|
+
_b.label = 1;
|
|
600
|
+
case 1:
|
|
601
|
+
_b.trys.push([1, , 9, 16]);
|
|
602
|
+
now = new Date();
|
|
603
|
+
oneHourAgo = new Date(now.getTime() - 3600000);
|
|
604
|
+
twoHoursAgo = new Date(now.getTime() - 7200000);
|
|
605
|
+
// Create a historical track for review testing
|
|
606
|
+
log("C0: Creating historical track for review tests...");
|
|
607
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
608
|
+
title: "Track for Review",
|
|
609
|
+
isHistorical: true,
|
|
610
|
+
closedAt: now,
|
|
611
|
+
lockedAt: now,
|
|
612
|
+
lockedByUserId: sdk.userInfo.id,
|
|
613
|
+
totalDurationInMS: 3600000,
|
|
614
|
+
timestamps: [
|
|
615
|
+
{ type: 'start', timestamp: twoHoursAgo },
|
|
616
|
+
{ type: 'pause', timestamp: oneHourAgo },
|
|
617
|
+
],
|
|
618
|
+
})];
|
|
619
|
+
case 2:
|
|
620
|
+
historical = _b.sent();
|
|
621
|
+
trackIds.push(historical.id);
|
|
622
|
+
log("C0: Historical track created");
|
|
623
|
+
// Test C1: Review by different user (approval)
|
|
624
|
+
log("C1: Review by different user (approval)...");
|
|
625
|
+
reviewTime = new Date();
|
|
626
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(historical.id, {
|
|
627
|
+
reviewedAt: reviewTime,
|
|
628
|
+
reviewedByUserId: sdkNonAdmin.userInfo.id,
|
|
629
|
+
reviewApproved: true,
|
|
630
|
+
})];
|
|
631
|
+
case 3:
|
|
632
|
+
reviewed = _b.sent();
|
|
633
|
+
(0, testing_1.assert)(!!reviewed.reviewedAt, "reviewedAt should be set");
|
|
634
|
+
(0, testing_1.assert)(reviewed.reviewedByUserId === sdkNonAdmin.userInfo.id, "reviewedByUserId should match non-admin");
|
|
635
|
+
(0, testing_1.assert)(reviewed.reviewApproved === true, "reviewApproved should be true");
|
|
636
|
+
log("C1: Review approved successfully by different user");
|
|
637
|
+
// Test C2: Self-review (owner reviews own track) - expect 400
|
|
638
|
+
log("C2: Self-review (should fail)...");
|
|
639
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
640
|
+
title: "Track for Self-Review",
|
|
641
|
+
isHistorical: true,
|
|
642
|
+
closedAt: now,
|
|
643
|
+
lockedAt: now,
|
|
644
|
+
lockedByUserId: sdk.userInfo.id,
|
|
645
|
+
totalDurationInMS: 3600000,
|
|
646
|
+
timestamps: [
|
|
647
|
+
{ type: 'start', timestamp: twoHoursAgo },
|
|
648
|
+
{ type: 'pause', timestamp: oneHourAgo },
|
|
649
|
+
],
|
|
650
|
+
})];
|
|
651
|
+
case 4:
|
|
652
|
+
historical2_1 = _b.sent();
|
|
653
|
+
trackIds.push(historical2_1.id);
|
|
654
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(historical2_1.id, {
|
|
655
|
+
reviewedAt: new Date(),
|
|
656
|
+
reviewedByUserId: sdk.userInfo.id,
|
|
657
|
+
reviewApproved: true,
|
|
658
|
+
}); }, "C2: Self-review")];
|
|
659
|
+
case 5:
|
|
660
|
+
_b.sent();
|
|
661
|
+
log("C2: Correctly rejected self-review");
|
|
662
|
+
// Test C3: Review fields updatable even after lock
|
|
663
|
+
log("C3: Review fields updatable after lock...");
|
|
664
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(historical.id, {
|
|
665
|
+
reviewedAt: new Date(),
|
|
666
|
+
reviewedByUserId: sdkNonAdmin.userInfo.id,
|
|
667
|
+
reviewApproved: false,
|
|
668
|
+
reviewNote: "Hours seem too high, please double-check",
|
|
669
|
+
})];
|
|
670
|
+
case 6:
|
|
671
|
+
updatedReview = _b.sent();
|
|
672
|
+
(0, testing_1.assert)(updatedReview.reviewApproved === false, "reviewApproved should be updated to false");
|
|
673
|
+
(0, testing_1.assert)(updatedReview.reviewNote === "Hours seem too high, please double-check", "reviewNote should be set");
|
|
674
|
+
log("C3: Review fields correctly updatable on locked track");
|
|
675
|
+
// Test C4: Rejection flow with reviewNote
|
|
676
|
+
log("C4: Rejection flow with reviewNote...");
|
|
677
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
678
|
+
title: "Track for Rejection",
|
|
679
|
+
isHistorical: true,
|
|
680
|
+
closedAt: now,
|
|
681
|
+
lockedAt: now,
|
|
682
|
+
lockedByUserId: sdk.userInfo.id,
|
|
683
|
+
totalDurationInMS: 1800000,
|
|
684
|
+
timestamps: [
|
|
685
|
+
{ type: 'start', timestamp: twoHoursAgo },
|
|
686
|
+
{ type: 'pause', timestamp: oneHourAgo },
|
|
687
|
+
],
|
|
688
|
+
})];
|
|
689
|
+
case 7:
|
|
690
|
+
historical3 = _b.sent();
|
|
691
|
+
trackIds.push(historical3.id);
|
|
692
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(historical3.id, {
|
|
693
|
+
reviewedAt: new Date(),
|
|
694
|
+
reviewedByUserId: sdkNonAdmin.userInfo.id,
|
|
695
|
+
reviewApproved: false,
|
|
696
|
+
reviewNote: "Rejected - timestamps don't match claimed duration",
|
|
697
|
+
})];
|
|
698
|
+
case 8:
|
|
699
|
+
rejected = _b.sent();
|
|
700
|
+
(0, testing_1.assert)(rejected.reviewApproved === false, "reviewApproved should be false");
|
|
701
|
+
(0, testing_1.assert)(rejected.reviewNote === "Rejected - timestamps don't match claimed duration", "reviewNote should match");
|
|
702
|
+
log("C4: Rejection flow completed successfully");
|
|
703
|
+
log("All review flow tests passed!");
|
|
704
|
+
return [3 /*break*/, 16];
|
|
705
|
+
case 9:
|
|
706
|
+
_i = 0, trackIds_3 = trackIds;
|
|
707
|
+
_b.label = 10;
|
|
708
|
+
case 10:
|
|
709
|
+
if (!(_i < trackIds_3.length)) return [3 /*break*/, 15];
|
|
710
|
+
id = trackIds_3[_i];
|
|
711
|
+
_b.label = 11;
|
|
712
|
+
case 11:
|
|
713
|
+
_b.trys.push([11, 13, , 14]);
|
|
714
|
+
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(id)];
|
|
715
|
+
case 12:
|
|
716
|
+
_b.sent();
|
|
717
|
+
return [3 /*break*/, 14];
|
|
718
|
+
case 13:
|
|
719
|
+
e_6 = _b.sent();
|
|
720
|
+
return [3 /*break*/, 14];
|
|
721
|
+
case 14:
|
|
722
|
+
_i++;
|
|
723
|
+
return [3 /*break*/, 10];
|
|
724
|
+
case 15: return [7 /*endfinally*/];
|
|
725
|
+
case 16: return [2 /*return*/];
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
};
|
|
730
|
+
exports.time_tracks_review_tests = time_tracks_review_tests;
|
|
731
|
+
// ============================================================
|
|
732
|
+
// Group D: Lock Enforcement
|
|
733
|
+
// ============================================================
|
|
734
|
+
var time_tracks_lock_tests = function (_a) {
|
|
735
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
736
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
737
|
+
var trackIds, now, oneHourAgo, twoHoursAgo, locked_1, reviewed, _i, trackIds_4, id, e_7;
|
|
738
|
+
return __generator(this, function (_b) {
|
|
739
|
+
switch (_b.label) {
|
|
740
|
+
case 0:
|
|
741
|
+
(0, testing_1.log_header)("Time Tracks - Lock Enforcement Tests");
|
|
742
|
+
trackIds = [];
|
|
743
|
+
_b.label = 1;
|
|
744
|
+
case 1:
|
|
745
|
+
_b.trys.push([1, , 9, 16]);
|
|
746
|
+
now = new Date();
|
|
747
|
+
oneHourAgo = new Date(now.getTime() - 3600000);
|
|
748
|
+
twoHoursAgo = new Date(now.getTime() - 7200000);
|
|
749
|
+
// Create a locked historical track
|
|
750
|
+
log("D0: Creating locked historical track...");
|
|
751
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
752
|
+
title: "Locked Track",
|
|
753
|
+
isHistorical: true,
|
|
754
|
+
closedAt: now,
|
|
755
|
+
lockedAt: now,
|
|
756
|
+
lockedByUserId: sdk.userInfo.id,
|
|
757
|
+
totalDurationInMS: 3600000,
|
|
758
|
+
timestamps: [
|
|
759
|
+
{ type: 'start', timestamp: twoHoursAgo },
|
|
760
|
+
{ type: 'pause', timestamp: oneHourAgo },
|
|
761
|
+
],
|
|
762
|
+
})];
|
|
763
|
+
case 2:
|
|
764
|
+
locked_1 = _b.sent();
|
|
765
|
+
trackIds.push(locked_1.id);
|
|
766
|
+
log("D0: Locked track created");
|
|
767
|
+
// Test D1: Locked track rejects updates to timestamps
|
|
768
|
+
log("D1: Updating timestamps on locked track (should fail)...");
|
|
769
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
770
|
+
timestamps: [{ type: 'start', timestamp: new Date() }],
|
|
771
|
+
}); }, "D1: timestamps update on locked track")];
|
|
772
|
+
case 3:
|
|
773
|
+
_b.sent();
|
|
774
|
+
log("D1: Correctly rejected timestamps update");
|
|
775
|
+
// Test D2: Locked track rejects updates to closedAt
|
|
776
|
+
log("D2: Updating closedAt on locked track (should fail)...");
|
|
777
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
778
|
+
closedAt: new Date(),
|
|
779
|
+
}); }, "D2: closedAt update on locked track")];
|
|
780
|
+
case 4:
|
|
781
|
+
_b.sent();
|
|
782
|
+
log("D2: Correctly rejected closedAt update");
|
|
783
|
+
// Test D3: Locked track rejects updates to totalDurationInMS
|
|
784
|
+
log("D3: Updating totalDurationInMS on locked track (should fail)...");
|
|
785
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
786
|
+
totalDurationInMS: 999,
|
|
787
|
+
}); }, "D3: totalDurationInMS update on locked track")];
|
|
788
|
+
case 5:
|
|
789
|
+
_b.sent();
|
|
790
|
+
log("D3: Correctly rejected totalDurationInMS update");
|
|
791
|
+
// Test D4: Locked track rejects updates to correctedAt
|
|
792
|
+
log("D4: Updating correctedAt on locked track (should fail)...");
|
|
793
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
794
|
+
correctedAt: new Date(),
|
|
795
|
+
originalTotalDurationInMS: 3600000,
|
|
796
|
+
totalDurationInMS: 1800000,
|
|
797
|
+
lockedAt: new Date(),
|
|
798
|
+
lockedByUserId: sdk.userInfo.id,
|
|
799
|
+
}); }, "D4: correctedAt update on locked track")];
|
|
800
|
+
case 6:
|
|
801
|
+
_b.sent();
|
|
802
|
+
log("D4: Correctly rejected correction on locked track");
|
|
803
|
+
// Test D5: Locked track rejects updates to title
|
|
804
|
+
log("D5: Updating title on locked track (should fail)...");
|
|
805
|
+
return [4 /*yield*/, assert_throws(function () { return sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
806
|
+
title: "Should Not Change",
|
|
807
|
+
}); }, "D5: title update on locked track")];
|
|
808
|
+
case 7:
|
|
809
|
+
_b.sent();
|
|
810
|
+
log("D5: Correctly rejected title update");
|
|
811
|
+
// Test D6: Locked track allows updates to review fields
|
|
812
|
+
log("D6: Updating review fields on locked track (should succeed)...");
|
|
813
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(locked_1.id, {
|
|
814
|
+
reviewedAt: new Date(),
|
|
815
|
+
reviewedByUserId: sdkNonAdmin.userInfo.id,
|
|
816
|
+
reviewApproved: true,
|
|
817
|
+
reviewNote: "Looks good",
|
|
818
|
+
})];
|
|
819
|
+
case 8:
|
|
820
|
+
reviewed = _b.sent();
|
|
821
|
+
(0, testing_1.assert)(reviewed.reviewApproved === true, "reviewApproved should be set");
|
|
822
|
+
(0, testing_1.assert)(reviewed.reviewNote === "Looks good", "reviewNote should be set");
|
|
823
|
+
(0, testing_1.assert)(reviewed.reviewedByUserId === sdkNonAdmin.userInfo.id, "reviewedByUserId should match");
|
|
824
|
+
log("D6: Review fields correctly updatable on locked track");
|
|
825
|
+
log("All lock enforcement tests passed!");
|
|
826
|
+
return [3 /*break*/, 16];
|
|
827
|
+
case 9:
|
|
828
|
+
_i = 0, trackIds_4 = trackIds;
|
|
829
|
+
_b.label = 10;
|
|
830
|
+
case 10:
|
|
831
|
+
if (!(_i < trackIds_4.length)) return [3 /*break*/, 15];
|
|
832
|
+
id = trackIds_4[_i];
|
|
833
|
+
_b.label = 11;
|
|
834
|
+
case 11:
|
|
835
|
+
_b.trys.push([11, 13, , 14]);
|
|
836
|
+
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(id)];
|
|
837
|
+
case 12:
|
|
838
|
+
_b.sent();
|
|
839
|
+
return [3 /*break*/, 14];
|
|
840
|
+
case 13:
|
|
841
|
+
e_7 = _b.sent();
|
|
842
|
+
return [3 /*break*/, 14];
|
|
843
|
+
case 14:
|
|
844
|
+
_i++;
|
|
845
|
+
return [3 /*break*/, 10];
|
|
846
|
+
case 15: return [7 /*endfinally*/];
|
|
847
|
+
case 16: return [2 /*return*/];
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
});
|
|
851
|
+
};
|
|
852
|
+
exports.time_tracks_lock_tests = time_tracks_lock_tests;
|
|
853
|
+
// ============================================================
|
|
854
|
+
// Group E: Edge Cases
|
|
855
|
+
// ============================================================
|
|
856
|
+
var time_tracks_edge_case_tests = function (_a) {
|
|
857
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
858
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
859
|
+
var trackIds, track, updated, withPause, track2, closedTrack, originalDuration, corrected, _i, trackIds_5, id, e_8;
|
|
860
|
+
var _b;
|
|
861
|
+
return __generator(this, function (_c) {
|
|
862
|
+
switch (_c.label) {
|
|
863
|
+
case 0:
|
|
864
|
+
(0, testing_1.log_header)("Time Tracks - Edge Case Tests");
|
|
865
|
+
trackIds = [];
|
|
866
|
+
_c.label = 1;
|
|
867
|
+
case 1:
|
|
868
|
+
_c.trys.push([1, , 10, 17]);
|
|
869
|
+
// Test E1: Normal real-time track - lockedAt stays undefined, all fields updatable
|
|
870
|
+
log("E1: Normal real-time track is fully updatable...");
|
|
871
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
872
|
+
title: "Normal Track",
|
|
873
|
+
})];
|
|
874
|
+
case 2:
|
|
875
|
+
track = _c.sent();
|
|
876
|
+
trackIds.push(track.id);
|
|
877
|
+
(0, testing_1.assert)(!track.lockedAt, "lockedAt should be undefined for normal track");
|
|
878
|
+
(0, testing_1.assert)(!track.isHistorical, "isHistorical should be undefined for normal track");
|
|
879
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track.id, {
|
|
880
|
+
title: "Updated Normal Track",
|
|
881
|
+
})];
|
|
882
|
+
case 3:
|
|
883
|
+
updated = _c.sent();
|
|
884
|
+
(0, testing_1.assert)(updated.title === "Updated Normal Track", "Title should be updatable on unlocked track");
|
|
885
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track.id, {
|
|
886
|
+
timestamps: __spreadArray(__spreadArray([], (track.timestamps || []), true), [
|
|
887
|
+
{ type: 'pause', timestamp: new Date() },
|
|
888
|
+
], false)
|
|
889
|
+
}, { replaceObjectFields: true })];
|
|
890
|
+
case 4:
|
|
891
|
+
withPause = _c.sent();
|
|
892
|
+
(0, testing_1.assert)(((_b = withPause.timestamps) === null || _b === void 0 ? void 0 : _b.length) === 2, "timestamps should be updatable on unlocked track");
|
|
893
|
+
log("E1: Normal track fully updatable as expected");
|
|
894
|
+
// Test E2: Original totalDurationInMS preserved after correction
|
|
895
|
+
log("E2: Original duration preserved after correction...");
|
|
896
|
+
return [4 /*yield*/, sdk.api.time_tracks.createOne({
|
|
897
|
+
title: "Track for Duration Preservation",
|
|
898
|
+
})];
|
|
899
|
+
case 5:
|
|
900
|
+
track2 = _c.sent();
|
|
901
|
+
trackIds.push(track2.id);
|
|
902
|
+
// Close the track
|
|
903
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track2.id, { closedAt: new Date() })];
|
|
904
|
+
case 6:
|
|
905
|
+
// Close the track
|
|
906
|
+
_c.sent();
|
|
907
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, 1500)];
|
|
908
|
+
case 7:
|
|
909
|
+
_c.sent();
|
|
910
|
+
return [4 /*yield*/, sdk.api.time_tracks.getOne(track2.id)];
|
|
911
|
+
case 8:
|
|
912
|
+
closedTrack = _c.sent();
|
|
913
|
+
originalDuration = closedTrack.totalDurationInMS;
|
|
914
|
+
return [4 /*yield*/, sdk.api.time_tracks.updateOne(track2.id, {
|
|
915
|
+
correctedAt: new Date(),
|
|
916
|
+
correctedByUserId: sdk.userInfo.id,
|
|
917
|
+
originalTotalDurationInMS: originalDuration,
|
|
918
|
+
totalDurationInMS: 5000,
|
|
919
|
+
lockedAt: new Date(),
|
|
920
|
+
lockedByUserId: sdk.userInfo.id,
|
|
921
|
+
})];
|
|
922
|
+
case 9:
|
|
923
|
+
corrected = _c.sent();
|
|
924
|
+
(0, testing_1.assert)(corrected.originalTotalDurationInMS === originalDuration, "originalTotalDurationInMS should be ".concat(originalDuration, ", got ").concat(corrected.originalTotalDurationInMS));
|
|
925
|
+
(0, testing_1.assert)(corrected.totalDurationInMS === 5000, "totalDurationInMS should be corrected to 5000, got ".concat(corrected.totalDurationInMS));
|
|
926
|
+
log("E2: Original duration correctly preserved in originalTotalDurationInMS");
|
|
927
|
+
log("All edge case tests passed!");
|
|
928
|
+
return [3 /*break*/, 17];
|
|
929
|
+
case 10:
|
|
930
|
+
_i = 0, trackIds_5 = trackIds;
|
|
931
|
+
_c.label = 11;
|
|
932
|
+
case 11:
|
|
933
|
+
if (!(_i < trackIds_5.length)) return [3 /*break*/, 16];
|
|
934
|
+
id = trackIds_5[_i];
|
|
935
|
+
_c.label = 12;
|
|
936
|
+
case 12:
|
|
937
|
+
_c.trys.push([12, 14, , 15]);
|
|
938
|
+
return [4 /*yield*/, sdk.api.time_tracks.deleteOne(id)];
|
|
939
|
+
case 13:
|
|
940
|
+
_c.sent();
|
|
941
|
+
return [3 /*break*/, 15];
|
|
942
|
+
case 14:
|
|
943
|
+
e_8 = _c.sent();
|
|
944
|
+
return [3 /*break*/, 15];
|
|
945
|
+
case 15:
|
|
946
|
+
_i++;
|
|
947
|
+
return [3 /*break*/, 11];
|
|
948
|
+
case 16: return [7 /*endfinally*/];
|
|
949
|
+
case 17: return [2 /*return*/];
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
};
|
|
954
|
+
exports.time_tracks_edge_case_tests = time_tracks_edge_case_tests;
|
|
298
955
|
// Allow running this test file independently
|
|
299
956
|
if (require.main === module) {
|
|
300
957
|
var sdk_2 = new sdk_1.Session({ host: host });
|
|
@@ -312,6 +969,21 @@ if (require.main === module) {
|
|
|
312
969
|
_a.sent();
|
|
313
970
|
return [4 /*yield*/, (0, exports.time_tracks_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
314
971
|
case 2:
|
|
972
|
+
_a.sent();
|
|
973
|
+
return [4 /*yield*/, (0, exports.time_tracks_historical_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
974
|
+
case 3:
|
|
975
|
+
_a.sent();
|
|
976
|
+
return [4 /*yield*/, (0, exports.time_tracks_correction_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
977
|
+
case 4:
|
|
978
|
+
_a.sent();
|
|
979
|
+
return [4 /*yield*/, (0, exports.time_tracks_review_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
980
|
+
case 5:
|
|
981
|
+
_a.sent();
|
|
982
|
+
return [4 /*yield*/, (0, exports.time_tracks_lock_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
983
|
+
case 6:
|
|
984
|
+
_a.sent();
|
|
985
|
+
return [4 /*yield*/, (0, exports.time_tracks_edge_case_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
986
|
+
case 7:
|
|
315
987
|
_a.sent();
|
|
316
988
|
return [2 /*return*/];
|
|
317
989
|
}
|
|
@@ -319,11 +991,11 @@ if (require.main === module) {
|
|
|
319
991
|
}); };
|
|
320
992
|
runTests()
|
|
321
993
|
.then(function () {
|
|
322
|
-
console.log("
|
|
994
|
+
console.log("Time tracks test suite completed successfully");
|
|
323
995
|
process.exit(0);
|
|
324
996
|
})
|
|
325
997
|
.catch(function (error) {
|
|
326
|
-
console.error("
|
|
998
|
+
console.error("Time tracks test suite failed:", error);
|
|
327
999
|
process.exit(1);
|
|
328
1000
|
});
|
|
329
1001
|
}
|