@oneuptime/common 11.5.5 → 11.5.7
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/Models/DatabaseModels/User.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.ts +11 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784048917994-AddCreatedByUserToUser.ts +23 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +37 -0
- package/Server/Middleware/ProjectAuthorization.ts +40 -15
- package/Server/Services/TeamMemberService.ts +2 -0
- package/Server/Services/UserService.ts +10 -0
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +16 -6
- package/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.ts +14 -3
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +130 -12
- package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilderUnits.test.ts +553 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaMessageBuilderUnits.test.ts +590 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaMessageFormatterUnits.test.ts +254 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +821 -0
- package/build/dist/Models/DatabaseModels/User.js +46 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js +9 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784048917994-AddCreatedByUserToUser.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784048917994-AddCreatedByUserToUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +26 -0
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +40 -14
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +2 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +8 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +15 -7
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js +12 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js +8 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +96 -12
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import MonitorCriteriaMessageFormatter from "../../../../Server/Utils/Monitor/MonitorCriteriaMessageFormatter";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Exhaustive, isolated unit tests for the pure helper
|
|
5
|
+
* MonitorCriteriaMessageFormatter.summarizeNumericSeries(values, unit?).
|
|
6
|
+
*
|
|
7
|
+
* The function turns a numeric series into a single human readable line:
|
|
8
|
+
* - empty array => null
|
|
9
|
+
* - length === 1 => "latest <v> across 1 data point"
|
|
10
|
+
* - length > 1 => "latest <last> (min <min>, max <max>) across N data points"
|
|
11
|
+
* Every number is rendered with value.toFixed(2) (always exactly 2 decimals),
|
|
12
|
+
* and a " <unit>" suffix is appended to every number ONLY when unit is truthy.
|
|
13
|
+
* "latest" is always the LAST element of the array, never the maximum.
|
|
14
|
+
*/
|
|
15
|
+
describe("MonitorCriteriaMessageFormatter.summarizeNumericSeries", () => {
|
|
16
|
+
/* ----- Empty input ----- */
|
|
17
|
+
describe("empty input", () => {
|
|
18
|
+
test("returns null for an empty array", () => {
|
|
19
|
+
const summary: string | null =
|
|
20
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([]);
|
|
21
|
+
|
|
22
|
+
expect(summary).toBeNull();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("returns null for an empty array even when a unit is provided", () => {
|
|
26
|
+
const summary: string | null =
|
|
27
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([], "sec");
|
|
28
|
+
|
|
29
|
+
expect(summary).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/* ----- Single value (singular, no min/max clause) ----- */
|
|
34
|
+
describe("single value", () => {
|
|
35
|
+
test("renders the singular 'data point' with a unit suffix", () => {
|
|
36
|
+
const summary: string | null =
|
|
37
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.06], "sec");
|
|
38
|
+
|
|
39
|
+
expect(summary).toBe("latest 0.06 sec across 1 data point");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("renders the singular 'data point' with no unit suffix", () => {
|
|
43
|
+
const summary: string | null =
|
|
44
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.06]);
|
|
45
|
+
|
|
46
|
+
expect(summary).toBe("latest 0.06 across 1 data point");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("omits the (min .., max ..) clause entirely for a single value", () => {
|
|
50
|
+
const summary: string | null =
|
|
51
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.06], "sec");
|
|
52
|
+
|
|
53
|
+
expect(summary).not.toContain("min");
|
|
54
|
+
expect(summary).not.toContain("max");
|
|
55
|
+
expect(summary).not.toContain("(");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/* ----- Multiple values (plural, full clause) ----- */
|
|
60
|
+
describe("multiple values", () => {
|
|
61
|
+
test("renders the full 'latest .. (min .., max ..) across N data points' shape with a unit", () => {
|
|
62
|
+
const summary: string | null =
|
|
63
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(
|
|
64
|
+
[0.05, 0.06, 0.07],
|
|
65
|
+
"sec",
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(summary).toBe(
|
|
69
|
+
"latest 0.07 sec (min 0.05 sec, max 0.07 sec) across 3 data points",
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("renders the same shape without any unit suffix when no unit is given", () => {
|
|
74
|
+
const summary: string | null =
|
|
75
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([
|
|
76
|
+
0.05, 0.06, 0.07,
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
expect(summary).toBe(
|
|
80
|
+
"latest 0.07 (min 0.05, max 0.07) across 3 data points",
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("uses the LAST element for 'latest', not the maximum", () => {
|
|
85
|
+
// Last element is 0.06 while the max is 0.07 and the min is 0.05.
|
|
86
|
+
const summary: string | null =
|
|
87
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([
|
|
88
|
+
0.07, 0.05, 0.06,
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
expect(summary).toBe(
|
|
92
|
+
"latest 0.06 (min 0.05, max 0.07) across 3 data points",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/* ----- toFixed(2) number formatting proof ----- */
|
|
98
|
+
describe("toFixed(2) number formatting", () => {
|
|
99
|
+
test("pads a sub-unit fraction to two decimals (0.5 => '0.50')", () => {
|
|
100
|
+
const summary: string | null =
|
|
101
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.5]);
|
|
102
|
+
|
|
103
|
+
expect(summary).toBe("latest 0.50 across 1 data point");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("pads small integers to two decimals (5 => '5.00', 60 => '60.00')", () => {
|
|
107
|
+
const five: string | null =
|
|
108
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([5]);
|
|
109
|
+
const sixty: string | null =
|
|
110
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([60]);
|
|
111
|
+
|
|
112
|
+
expect(five).toBe("latest 5.00 across 1 data point");
|
|
113
|
+
expect(sixty).toBe("latest 60.00 across 1 data point");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("keeps two decimals for large integers (2500 => '2500.00')", () => {
|
|
117
|
+
const summary: string | null =
|
|
118
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([2500]);
|
|
119
|
+
|
|
120
|
+
expect(summary).toBe("latest 2500.00 across 1 data point");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("still emits two decimals for a plain integer (42 => '42.00')", () => {
|
|
124
|
+
const summary: string | null =
|
|
125
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([42], "GB");
|
|
126
|
+
|
|
127
|
+
expect(summary).toBe("latest 42.00 GB across 1 data point");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
/* ----- Negative values ----- */
|
|
132
|
+
describe("negative values", () => {
|
|
133
|
+
test("formats negatives with a leading minus and two decimals", () => {
|
|
134
|
+
// Last element (-0.5) is the latest; min is -1.5, max is -0.5.
|
|
135
|
+
const summary: string | null =
|
|
136
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([-1.5, -0.5]);
|
|
137
|
+
|
|
138
|
+
expect(summary).toBe(
|
|
139
|
+
"latest -0.50 (min -1.50, max -0.50) across 2 data points",
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("formats a single negative value with a unit suffix", () => {
|
|
144
|
+
const summary: string | null =
|
|
145
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([-1.5], "sec");
|
|
146
|
+
|
|
147
|
+
expect(summary).toBe("latest -1.50 sec across 1 data point");
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
/* ----- Unit handling (truthiness) ----- */
|
|
152
|
+
describe("unit handling", () => {
|
|
153
|
+
test("treats an empty-string unit as no unit (no suffix)", () => {
|
|
154
|
+
const summary: string | null =
|
|
155
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.06], "");
|
|
156
|
+
|
|
157
|
+
expect(summary).toBe("latest 0.06 across 1 data point");
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("treats an undefined unit as no unit (no suffix)", () => {
|
|
161
|
+
const summary: string | null =
|
|
162
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(
|
|
163
|
+
[0.06],
|
|
164
|
+
undefined,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
expect(summary).toBe("latest 0.06 across 1 data point");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("renders multi-character and symbolic units verbatim on every number", () => {
|
|
171
|
+
const ms: string | null =
|
|
172
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(
|
|
173
|
+
[100, 200],
|
|
174
|
+
"ms",
|
|
175
|
+
);
|
|
176
|
+
const gb: string | null =
|
|
177
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([4], "GB");
|
|
178
|
+
const reqPerSec: string | null =
|
|
179
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(
|
|
180
|
+
[1234.5],
|
|
181
|
+
"req/s",
|
|
182
|
+
);
|
|
183
|
+
const percent: string | null =
|
|
184
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([50, 99.9], "%");
|
|
185
|
+
|
|
186
|
+
expect(ms).toBe(
|
|
187
|
+
"latest 200.00 ms (min 100.00 ms, max 200.00 ms) across 2 data points",
|
|
188
|
+
);
|
|
189
|
+
expect(gb).toBe("latest 4.00 GB across 1 data point");
|
|
190
|
+
expect(reqPerSec).toBe("latest 1234.50 req/s across 1 data point");
|
|
191
|
+
expect(percent).toBe(
|
|
192
|
+
"latest 99.90 % (min 50.00 %, max 99.90 %) across 2 data points",
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
/* ----- data point pluralization boundary ----- */
|
|
198
|
+
describe("data point pluralization", () => {
|
|
199
|
+
test("exactly 1 value => singular '1 data point'", () => {
|
|
200
|
+
const summary: string | null =
|
|
201
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([3]);
|
|
202
|
+
|
|
203
|
+
expect(summary).toContain("1 data point");
|
|
204
|
+
expect(summary).not.toContain("1 data points");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("exactly 2 values => plural '2 data points'", () => {
|
|
208
|
+
const summary: string | null =
|
|
209
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([3, 4]);
|
|
210
|
+
|
|
211
|
+
expect(summary).toContain("2 data points");
|
|
212
|
+
expect(summary).toBe(
|
|
213
|
+
"latest 4.00 (min 3.00, max 4.00) across 2 data points",
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/* ----- Large series ----- */
|
|
219
|
+
describe("large series", () => {
|
|
220
|
+
test("produces one single-line summary with correct latest/min/max/N for 50 values", () => {
|
|
221
|
+
const values: Array<number> = [];
|
|
222
|
+
for (let i: number = 1; i <= 50; i++) {
|
|
223
|
+
values.push(i);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const summary: string | null =
|
|
227
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(values, "ms");
|
|
228
|
+
|
|
229
|
+
expect(summary).toBe(
|
|
230
|
+
"latest 50.00 ms (min 1.00 ms, max 50.00 ms) across 50 data points",
|
|
231
|
+
);
|
|
232
|
+
// Single line: no newline characters anywhere in the output.
|
|
233
|
+
expect(summary).not.toContain("\n");
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
/* ----- Rounding boundaries (discovered by running the real toFixed) ----- */
|
|
238
|
+
describe("rounding boundaries", () => {
|
|
239
|
+
test("0.005 rounds up to '0.01' via toFixed(2)", () => {
|
|
240
|
+
// The double nearest 0.005 is slightly above 0.005, so it rounds up.
|
|
241
|
+
const summary: string | null =
|
|
242
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([0.005]);
|
|
243
|
+
|
|
244
|
+
expect(summary).toBe("latest 0.01 across 1 data point");
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("9.999 rounds up to '10.00' via toFixed(2)", () => {
|
|
248
|
+
const summary: string | null =
|
|
249
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries([9.999], "sec");
|
|
250
|
+
|
|
251
|
+
expect(summary).toBe("latest 10.00 sec across 1 data point");
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|