tabletcommand-backend-models 7.4.115 → 7.4.117
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/build/constants.js +3 -0
- package/build/constants.js.map +1 -1
- package/build/models/department.js +9 -1
- package/build/models/department.js.map +1 -1
- package/build/models/personnel-known.js +11 -0
- package/build/models/personnel-known.js.map +1 -1
- package/build/test/department.js +146 -0
- package/build/test/department.js.map +1 -1
- package/build/test/drone-connection.js +38 -0
- package/build/test/drone-connection.js.map +1 -1
- package/build/test/personnel-known.js +119 -0
- package/build/test/personnel-known.js.map +1 -0
- package/build/types/department.js.map +1 -1
- package/cspell.json +1 -0
- package/definitions/constants.d.ts +4 -1
- package/definitions/constants.d.ts.map +1 -1
- package/definitions/models/department.d.ts +2 -5
- package/definitions/models/department.d.ts.map +1 -1
- package/definitions/models/personnel-known.d.ts.map +1 -1
- package/definitions/test/personnel-known.d.ts +2 -0
- package/definitions/test/personnel-known.d.ts.map +1 -0
- package/definitions/types/department.d.ts +2 -1
- package/definitions/types/department.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +4 -1
- package/src/models/department.ts +10 -2
- package/src/models/personnel-known.ts +12 -0
- package/src/test/department.ts +179 -0
- package/src/test/drone-connection.ts +42 -0
- package/src/test/personnel-known.ts +130 -0
- package/src/types/department.ts +2 -0
|
@@ -60,6 +60,19 @@ describe("DroneConnection", function() {
|
|
|
60
60
|
assert.isUndefined(sut.options);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
for (const provider of Object.values(m.DroneProvider)) {
|
|
64
|
+
it(`saves the ${provider} provider`, async function() {
|
|
65
|
+
const sut = await new models.DroneConnection({
|
|
66
|
+
departmentId,
|
|
67
|
+
provider,
|
|
68
|
+
label: `${provider} fleet`,
|
|
69
|
+
}).save();
|
|
70
|
+
|
|
71
|
+
const loaded = await models.DroneConnection.findOne({ _id: sut._id });
|
|
72
|
+
assert.equal(loaded?.provider, provider);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
63
76
|
it("rejects an unknown provider", async function() {
|
|
64
77
|
let thrownError: unknown = null;
|
|
65
78
|
try {
|
|
@@ -161,4 +174,33 @@ describe("DroneConnection", function() {
|
|
|
161
174
|
assert.equal((thrownError as { code?: number }).code, 11000);
|
|
162
175
|
assert.include(String((thrownError as Error).message), "E11000");
|
|
163
176
|
});
|
|
177
|
+
it("rejects a provider whose case does not match", async function() {
|
|
178
|
+
let thrownError: unknown = null;
|
|
179
|
+
try {
|
|
180
|
+
await new models.DroneConnection({
|
|
181
|
+
departmentId,
|
|
182
|
+
provider: "BRINC",
|
|
183
|
+
label: "Wrong case",
|
|
184
|
+
}).save();
|
|
185
|
+
} catch (e) {
|
|
186
|
+
thrownError = e;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
assert.isNotNull(thrownError, "expected an upper-case provider to be rejected");
|
|
190
|
+
assert.include(String((thrownError as Error).message), "provider");
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("allows one label across different providers in a department", async function() {
|
|
194
|
+
for (const provider of Object.values(m.DroneProvider)) {
|
|
195
|
+
const sut = await new models.DroneConnection({
|
|
196
|
+
departmentId,
|
|
197
|
+
provider,
|
|
198
|
+
label: "Fleet A",
|
|
199
|
+
}).save();
|
|
200
|
+
assert.equal(sut.provider, provider);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const stored = await models.DroneConnection.find({ departmentId, label: "Fleet A" });
|
|
204
|
+
assert.equal(stored.length, Object.values(m.DroneProvider).length);
|
|
205
|
+
});
|
|
164
206
|
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { assert } from "chai";
|
|
2
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
3
|
+
import * as m from "../index";
|
|
4
|
+
import * as config from "./config";
|
|
5
|
+
import mockModule from "./mock";
|
|
6
|
+
|
|
7
|
+
describe("PersonnelKnown", function() {
|
|
8
|
+
let models: m.BackendModels, mongoose: m.MongooseModule;
|
|
9
|
+
beforeEach(async function() {
|
|
10
|
+
const c = await m.connect(config.url);
|
|
11
|
+
models = c.models;
|
|
12
|
+
mongoose = c.mongoose;
|
|
13
|
+
|
|
14
|
+
const mock = mockModule({
|
|
15
|
+
mongoose
|
|
16
|
+
});
|
|
17
|
+
await mock.beforeEach();
|
|
18
|
+
await models.PersonnelKnown.deleteMany({});
|
|
19
|
+
});
|
|
20
|
+
afterEach(async function() {
|
|
21
|
+
await mongoose.disconnect();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("is saved with defaults", async function() {
|
|
25
|
+
const item = new models.PersonnelKnown({
|
|
26
|
+
departmentId: "d1",
|
|
27
|
+
PersonnelID: "P1",
|
|
28
|
+
PersonnelName: "John Doe",
|
|
29
|
+
});
|
|
30
|
+
const sut = await item.save();
|
|
31
|
+
|
|
32
|
+
assert.isNotNull(sut._id);
|
|
33
|
+
assert.equal(sut.departmentId, "d1");
|
|
34
|
+
assert.equal(sut.PersonnelID, "P1");
|
|
35
|
+
assert.equal(sut.PersonnelName, "John Doe");
|
|
36
|
+
assert.equal(sut.PersonnelRank, "");
|
|
37
|
+
assert.equal(sut.PersonnelWorkCode, "");
|
|
38
|
+
assert.isFalse(sut.active);
|
|
39
|
+
assert.isNull(sut.userId);
|
|
40
|
+
assert.isTrue(sut.uuid !== "");
|
|
41
|
+
assert.deepEqual(sut.radios, []);
|
|
42
|
+
assert.equal(sut.jurisdiction, "");
|
|
43
|
+
assert.isNull(sut.agencyId);
|
|
44
|
+
assert.equal(sut.source, "");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("defines departmentId_1_userId_1_active_partial index in schema", function() {
|
|
48
|
+
const indexes = models.PersonnelKnown.schema.indexes();
|
|
49
|
+
|
|
50
|
+
const partialIndex = indexes.find(([fields, options]) => {
|
|
51
|
+
return (
|
|
52
|
+
options?.name === "departmentId_1_userId_1_active_partial" ||
|
|
53
|
+
(fields.departmentId === 1 && fields.userId === 1)
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
assert.isDefined(partialIndex, "Expected departmentId_1_userId_1_active_partial index to be defined");
|
|
58
|
+
const [fields, options] = partialIndex!;
|
|
59
|
+
assert.deepEqual(fields, { departmentId: 1, userId: 1 });
|
|
60
|
+
assert.isTrue(options?.unique);
|
|
61
|
+
assert.deepEqual(options?.partialFilterExpression, {
|
|
62
|
+
active: true,
|
|
63
|
+
userId: { $type: "string" },
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("enforces partial unique (departmentId, userId) when active and userId is a string", async function() {
|
|
68
|
+
await models.PersonnelKnown.createIndexes();
|
|
69
|
+
|
|
70
|
+
await new models.PersonnelKnown({
|
|
71
|
+
departmentId: "d1",
|
|
72
|
+
PersonnelID: "P1",
|
|
73
|
+
PersonnelName: "User One",
|
|
74
|
+
userId: "u1",
|
|
75
|
+
active: true,
|
|
76
|
+
}).save();
|
|
77
|
+
|
|
78
|
+
// Same userId in another department is allowed
|
|
79
|
+
const otherDept = await new models.PersonnelKnown({
|
|
80
|
+
departmentId: "d2",
|
|
81
|
+
PersonnelID: "P1",
|
|
82
|
+
PersonnelName: "User One",
|
|
83
|
+
userId: "u1",
|
|
84
|
+
active: true,
|
|
85
|
+
}).save();
|
|
86
|
+
assert.isNotNull(otherDept._id);
|
|
87
|
+
|
|
88
|
+
// Same userId in same department when active: false is allowed
|
|
89
|
+
const inactiveSameUser = await new models.PersonnelKnown({
|
|
90
|
+
departmentId: "d1",
|
|
91
|
+
PersonnelID: "P2",
|
|
92
|
+
PersonnelName: "User One Inactive",
|
|
93
|
+
userId: "u1",
|
|
94
|
+
active: false,
|
|
95
|
+
}).save();
|
|
96
|
+
assert.isNotNull(inactiveSameUser._id);
|
|
97
|
+
|
|
98
|
+
// Multiple records with userId: null and active: true are allowed
|
|
99
|
+
const nullUser1 = await new models.PersonnelKnown({
|
|
100
|
+
departmentId: "d1",
|
|
101
|
+
PersonnelID: "P3",
|
|
102
|
+
PersonnelName: "User Null 1",
|
|
103
|
+
userId: null,
|
|
104
|
+
active: true,
|
|
105
|
+
}).save();
|
|
106
|
+
const nullUser2 = await new models.PersonnelKnown({
|
|
107
|
+
departmentId: "d1",
|
|
108
|
+
PersonnelID: "P4",
|
|
109
|
+
PersonnelName: "User Null 2",
|
|
110
|
+
userId: null,
|
|
111
|
+
active: true,
|
|
112
|
+
}).save();
|
|
113
|
+
assert.isNotNull(nullUser1._id);
|
|
114
|
+
assert.isNotNull(nullUser2._id);
|
|
115
|
+
|
|
116
|
+
// Duplicate active userId on the same department must fail with E11000
|
|
117
|
+
try {
|
|
118
|
+
await new models.PersonnelKnown({
|
|
119
|
+
departmentId: "d1",
|
|
120
|
+
PersonnelID: "P5",
|
|
121
|
+
PersonnelName: "User One Duplicate",
|
|
122
|
+
userId: "u1",
|
|
123
|
+
active: true,
|
|
124
|
+
}).save();
|
|
125
|
+
assert.isFalse(true, "Expecting duplicate (departmentId, userId) with active: true to fail.");
|
|
126
|
+
} catch (error) {
|
|
127
|
+
assert.match((error as Error).message, /E11000/);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
package/src/types/department.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { PubNubTokenSchemaType } from "./pubnub-token";
|
|
|
5
5
|
import {
|
|
6
6
|
AccountCallerType,
|
|
7
7
|
AccountIndustry,
|
|
8
|
+
DroneProvider,
|
|
8
9
|
} from "../constants";
|
|
9
10
|
import { ReportNumberSchemaType } from "./common-incident";
|
|
10
11
|
import { GeoPolygon } from "./geojson";
|
|
@@ -370,6 +371,7 @@ export interface DronesVideoType {
|
|
|
370
371
|
|
|
371
372
|
export interface DronesConfigurationType {
|
|
372
373
|
enabled: boolean,
|
|
374
|
+
providers?: DroneProvider[],
|
|
373
375
|
video: DronesVideoType,
|
|
374
376
|
}
|
|
375
377
|
|