StatusPageBanner.utils.test.ts407 lines · main
1import { describe, expect, it } from 'vitest'
2
3import { getRelevantIncidentIds, shouldShowBanner } from './StatusPageBanner.utils'
4
5const noCache = { id: 'no-cache', cache: null } as const
6const noRestrictions = {
7 id: 'no-restrictions',
8 cache: { affected_regions: null, affects_project_creation: false },
9}
10const affectsCreation = {
11 id: 'affects-creation',
12 cache: { affected_regions: null, affects_project_creation: true },
13}
14const usEast1Only = {
15 id: 'us-east-1-only',
16 cache: { affected_regions: ['us-east-1'], affects_project_creation: false },
17}
18const usEast1AndCreation = {
19 id: 'us-east-1-and-creation',
20 cache: { affected_regions: ['us-east-1'], affects_project_creation: true },
21}
22const forced = {
23 id: 'forced',
24 cache: { affected_regions: ['us-east-1'], affects_project_creation: false, force: true },
25}
26
27describe('shouldShowBanner', () => {
28 describe('no incidents', () => {
29 it('does not show when there are no incidents', () => {
30 expect(
31 shouldShowBanner({ incidents: [], hasProjects: true, userRegions: new Set(['us-east-1']) })
32 ).toBe(false)
33 })
34 })
35
36 describe('user has no projects', () => {
37 it('does not show when cache is absent', () => {
38 expect(
39 shouldShowBanner({ incidents: [noCache], hasProjects: false, userRegions: new Set() })
40 ).toBe(false)
41 })
42
43 it('does not show when affects_project_creation is false', () => {
44 expect(
45 shouldShowBanner({
46 incidents: [noRestrictions],
47 hasProjects: false,
48 userRegions: new Set(),
49 })
50 ).toBe(false)
51 })
52
53 it('shows when affects_project_creation is true and no region restriction', () => {
54 expect(
55 shouldShowBanner({
56 incidents: [affectsCreation],
57 hasProjects: false,
58 userRegions: new Set(),
59 })
60 ).toBe(true)
61 })
62
63 it('does not show when affects_project_creation is true but there is a region restriction', () => {
64 expect(
65 shouldShowBanner({
66 incidents: [usEast1AndCreation],
67 hasProjects: false,
68 userRegions: new Set(),
69 })
70 ).toBe(false)
71 })
72 })
73
74 describe('user has projects, no region restriction', () => {
75 it('shows when cache is absent', () => {
76 expect(
77 shouldShowBanner({
78 incidents: [noCache],
79 hasProjects: true,
80 userRegions: new Set(['us-east-1']),
81 })
82 ).toBe(true)
83 })
84
85 it('shows when affected_regions is null', () => {
86 expect(
87 shouldShowBanner({
88 incidents: [noRestrictions],
89 hasProjects: true,
90 userRegions: new Set(['us-east-1']),
91 })
92 ).toBe(true)
93 })
94
95 it('shows when affected_regions is an empty array', () => {
96 expect(
97 shouldShowBanner({
98 incidents: [
99 { id: 'test', cache: { affected_regions: [], affects_project_creation: false } },
100 ],
101 hasProjects: true,
102 userRegions: new Set(['us-east-1']),
103 })
104 ).toBe(true)
105 })
106 })
107
108 describe('user has projects, with region restriction', () => {
109 it('shows when user has a primary database in an affected region', () => {
110 expect(
111 shouldShowBanner({
112 incidents: [usEast1Only],
113 hasProjects: true,
114 userRegions: new Set(['us-east-1']),
115 })
116 ).toBe(true)
117 })
118
119 it('shows when user has a read replica in an affected region', () => {
120 expect(
121 shouldShowBanner({
122 incidents: [
123 {
124 id: 'test',
125 cache: { affected_regions: ['eu-west-1'], affects_project_creation: false },
126 },
127 ],
128 hasProjects: true,
129 userRegions: new Set(['us-east-1', 'eu-west-1']),
130 })
131 ).toBe(true)
132 })
133
134 it('shows when one of multiple affected regions matches', () => {
135 expect(
136 shouldShowBanner({
137 incidents: [
138 {
139 id: 'test',
140 cache: {
141 affected_regions: ['us-east-1', 'ap-southeast-1'],
142 affects_project_creation: false,
143 },
144 },
145 ],
146 hasProjects: true,
147 userRegions: new Set(['ap-southeast-1']),
148 })
149 ).toBe(true)
150 })
151
152 it('shows when affected region has inconsistent casing (AI-generated cache)', () => {
153 expect(
154 shouldShowBanner({
155 incidents: [
156 {
157 id: 'test',
158 cache: { affected_regions: ['US-East-1'], affects_project_creation: false },
159 },
160 ],
161 hasProjects: true,
162 userRegions: new Set(['us-east-1']),
163 })
164 ).toBe(true)
165 })
166
167 it('does not show when user has no databases in any affected region', () => {
168 expect(
169 shouldShowBanner({
170 incidents: [usEast1Only],
171 hasProjects: true,
172 userRegions: new Set(['eu-west-1', 'ap-southeast-1']),
173 })
174 ).toBe(false)
175 })
176
177 it('does not show when user has projects but no databases in affected region, even with affects_project_creation', () => {
178 expect(
179 shouldShowBanner({
180 incidents: [usEast1AndCreation],
181 hasProjects: true,
182 userRegions: new Set(['eu-west-1']),
183 })
184 ).toBe(false)
185 })
186 })
187
188 describe('multiple incidents', () => {
189 it('shows when at least one incident matches even if others do not', () => {
190 expect(
191 shouldShowBanner({
192 incidents: [usEast1Only, noRestrictions],
193 hasProjects: true,
194 userRegions: new Set(['eu-west-1']),
195 })
196 ).toBe(true)
197 })
198
199 it('does not show when no incident matches', () => {
200 expect(
201 shouldShowBanner({
202 incidents: [usEast1Only, usEast1AndCreation],
203 hasProjects: true,
204 userRegions: new Set(['eu-west-1']),
205 })
206 ).toBe(false)
207 })
208
209 it('shows when any incident matches for a no-project user via affects_project_creation', () => {
210 expect(
211 shouldShowBanner({
212 incidents: [usEast1Only, affectsCreation],
213 hasProjects: false,
214 userRegions: new Set(),
215 })
216 ).toBe(true)
217 })
218 })
219
220 describe('force', () => {
221 it('shows for a user with no projects regardless of affects_project_creation', () => {
222 expect(
223 shouldShowBanner({ incidents: [forced], hasProjects: false, userRegions: new Set() })
224 ).toBe(true)
225 })
226
227 it('shows for a user whose regions do not overlap with affected_regions', () => {
228 expect(
229 shouldShowBanner({
230 incidents: [forced],
231 hasProjects: true,
232 userRegions: new Set(['eu-west-1']),
233 })
234 ).toBe(true)
235 })
236
237 it('shows for a user with projects and no regions at all', () => {
238 expect(
239 shouldShowBanner({ incidents: [forced], hasProjects: true, userRegions: new Set() })
240 ).toBe(true)
241 })
242
243 it('shows even when mixed with non-matching non-forced incidents', () => {
244 expect(
245 shouldShowBanner({
246 incidents: [usEast1Only, forced],
247 hasProjects: false,
248 userRegions: new Set(),
249 })
250 ).toBe(true)
251 })
252 })
253
254 describe('hasUnknownRegions', () => {
255 it('shows when regions are unknown and incident has a region restriction', () => {
256 expect(
257 shouldShowBanner({
258 incidents: [usEast1Only],
259 hasProjects: true,
260 userRegions: new Set(),
261 hasUnknownRegions: true,
262 })
263 ).toBe(true)
264 })
265
266 it('still applies no-projects check even when regions are unknown', () => {
267 expect(
268 shouldShowBanner({
269 incidents: [usEast1Only],
270 hasProjects: false,
271 userRegions: new Set(),
272 hasUnknownRegions: true,
273 })
274 ).toBe(false)
275 })
276
277 it('does not show for affects_project_creation with no projects when there is a region restriction, even when regions are unknown', () => {
278 expect(
279 shouldShowBanner({
280 incidents: [usEast1AndCreation],
281 hasProjects: false,
282 userRegions: new Set(),
283 hasUnknownRegions: true,
284 })
285 ).toBe(false)
286 })
287 })
288})
289
290describe('getRelevantIncidentIds', () => {
291 it('returns empty array when there are no incidents', () => {
292 expect(
293 getRelevantIncidentIds({ incidents: [], hasProjects: true, userRegions: new Set() })
294 ).toEqual([])
295 })
296
297 it('returns empty array when no incidents are relevant to the user', () => {
298 expect(
299 getRelevantIncidentIds({
300 incidents: [usEast1Only],
301 hasProjects: true,
302 userRegions: new Set(['eu-west-1']),
303 })
304 ).toEqual([])
305 })
306
307 it('returns the ID of a single relevant incident', () => {
308 expect(
309 getRelevantIncidentIds({
310 incidents: [noRestrictions],
311 hasProjects: true,
312 userRegions: new Set(['us-east-1']),
313 })
314 ).toEqual(['no-restrictions'])
315 })
316
317 it('returns IDs of all relevant incidents', () => {
318 const euWest1Only = {
319 id: 'eu-west-1-only',
320 cache: { affected_regions: ['eu-west-1'], affects_project_creation: false },
321 }
322 const apSoutheast1Only = {
323 id: 'ap-southeast-1-only',
324 cache: { affected_regions: ['ap-southeast-1'], affects_project_creation: false },
325 }
326
327 expect(
328 getRelevantIncidentIds({
329 incidents: [euWest1Only, apSoutheast1Only],
330 hasProjects: true,
331 userRegions: new Set(['eu-west-1', 'ap-southeast-1']),
332 })
333 ).toEqual(expect.arrayContaining(['ap-southeast-1-only', 'eu-west-1-only']))
334 })
335
336 it('returns the ID of a relevant incident when affected_regions has inconsistent casing', () => {
337 expect(
338 getRelevantIncidentIds({
339 incidents: [
340 {
341 id: 'mixed-case-region',
342 cache: { affected_regions: ['US-East-1'], affects_project_creation: false },
343 },
344 ],
345 hasProjects: true,
346 userRegions: new Set(['us-east-1']),
347 })
348 ).toEqual(['mixed-case-region'])
349 })
350
351 it('excludes incidents irrelevant to the user from the result', () => {
352 // User is in eu-west-1; us-east-1-only incident should not be included
353 expect(
354 getRelevantIncidentIds({
355 incidents: [usEast1Only, noRestrictions],
356 hasProjects: true,
357 userRegions: new Set(['eu-west-1']),
358 })
359 ).toEqual(['no-restrictions'])
360 })
361
362 describe('user has no projects', () => {
363 it('includes incidents with affects_project_creation', () => {
364 expect(
365 getRelevantIncidentIds({
366 incidents: [affectsCreation],
367 hasProjects: false,
368 userRegions: new Set(),
369 })
370 ).toEqual(['affects-creation'])
371 })
372
373 it('excludes incidents without affects_project_creation', () => {
374 expect(
375 getRelevantIncidentIds({
376 incidents: [noRestrictions, usEast1Only],
377 hasProjects: false,
378 userRegions: new Set(),
379 })
380 ).toEqual([])
381 })
382 })
383
384 describe('hasUnknownRegions', () => {
385 it('includes region-restricted incidents when regions are unknown', () => {
386 expect(
387 getRelevantIncidentIds({
388 incidents: [usEast1Only],
389 hasProjects: true,
390 userRegions: new Set(),
391 hasUnknownRegions: true,
392 })
393 ).toEqual(['us-east-1-only'])
394 })
395
396 it('still excludes incidents for no-project users even when regions are unknown', () => {
397 expect(
398 getRelevantIncidentIds({
399 incidents: [usEast1Only],
400 hasProjects: false,
401 userRegions: new Set(),
402 hasUnknownRegions: true,
403 })
404 ).toEqual([])
405 })
406 })
407})