From 112f3e416a6b70280bb16a6561c27140fe3d8940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9C=A8=20Audrey=20=E2=9C=A8?= Date: Thu, 20 Mar 2025 13:16:08 -0400 Subject: [PATCH] achievement hub event output tests --- .../achievements/achievement-hub.spec.ts | 45 +++++++++++++++---- .../achievements/examples/user-events.ts | 7 ++- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/libs/common/src/tools/achievements/achievement-hub.spec.ts b/libs/common/src/tools/achievements/achievement-hub.spec.ts index d78be5d0451..3615a7eda9d 100644 --- a/libs/common/src/tools/achievements/achievement-hub.spec.ts +++ b/libs/common/src/tools/achievements/achievement-hub.spec.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject, ReplaySubject, Subject, firstValueFrom } from "rxjs"; +import { BehaviorSubject, ReplaySubject, Subject, firstValueFrom, of, timeout } from "rxjs"; import { ConsoleLogService } from "../../platform/services/console-log.service"; import { consoleSemanticLoggerProvider } from "../log"; @@ -9,7 +9,7 @@ import { TotallyAttachedAchievement, TotallyAttachedValidator, } from "./examples/example-validators"; -import { itemAdded$ } from "./examples/user-events"; +import { ItemAddedEvent } from "./examples/user-events"; import { AchievementEarnedEvent, AchievementEvent, @@ -30,9 +30,10 @@ describe("AchievementHub", () => { const achievements$ = new Subject(); const hub = new AchievementHub(validators$, events$, achievements$); const results$ = new ReplaySubject(3); - hub.all$().subscribe(results$); - achievements$.next(ItemCreatedEarnedEvent); + achievements$.complete(); + + hub.all$().subscribe(results$); const result = firstValueFrom(results$); await expect(result).resolves.toEqual(ItemCreatedEarnedEvent); @@ -48,7 +49,7 @@ describe("AchievementHub", () => { // hub starts listening when achievements$ completes achievements$.complete(); - itemAdded$.subscribe(events$); + events$.next(ItemAddedEvent); const result = firstValueFrom(results$); await expect(result).resolves.toMatchObject({ @@ -58,13 +59,41 @@ describe("AchievementHub", () => { }); describe("new$", () => { - it("", async () => { + it("emits achievements derived from events", async () => { + const validators$ = new BehaviorSubject([TotallyAttachedValidator]); + const events$ = new Subject(); + const achievements$ = new Subject(); + const hub = new AchievementHub(validators$, events$, achievements$, 10, testLog); + const results$ = new ReplaySubject(3); + hub.new$().subscribe(results$); + + // hub starts listening when achievements$ completes + achievements$.complete(); + events$.next(ItemAddedEvent); + + const result = firstValueFrom(results$); + await expect(result).resolves.toMatchObject({ + achievement: { type: "earned", name: TotallyAttachedAchievement }, + }); + }); + + it("omits achievement emissions before subscription", async () => { const validators$ = new Subject(); const events$ = new Subject(); const achievements$ = new Subject(); const hub = new AchievementHub(validators$, events$, achievements$); - const results$ = new ReplaySubject(3); - hub.new$().subscribe(results$); + const results$ = new ReplaySubject(3); + achievements$.next(ItemCreatedEarnedEvent); + achievements$.complete(); + + // there are no emissions, so use a timeout to inject a `null` sentinel value + hub + .new$() + .pipe(timeout({ first: 10, with: () => of(null) })) + .subscribe(results$); + + const result = firstValueFrom(results$); + await expect(result).resolves.toBeNull(); }); }); diff --git a/libs/common/src/tools/achievements/examples/user-events.ts b/libs/common/src/tools/achievements/examples/user-events.ts index 3f667308201..111388a02dd 100644 --- a/libs/common/src/tools/achievements/examples/user-events.ts +++ b/libs/common/src/tools/achievements/examples/user-events.ts @@ -3,7 +3,7 @@ import { Observable, of } from "rxjs"; import { UserId } from "../../../types/guid"; import { UserActionEvent } from "../types"; -const itemAdded$: Observable = of({ +const ItemAddedEvent: UserActionEvent = { "@timestamp": Date.now(), user: { id: "1E2EDBC3-4449-4583-A4AC-ACDFA5C2EC71" as UserId, @@ -25,7 +25,9 @@ const itemAdded$: Observable = of({ action: "vault-item-added", labels: { "vault-item-type": "login", "vault-item-uri-quantity": 1 }, tags: ["with-attachment"], -}); +}; + +const itemAdded$ = of(ItemAddedEvent); const itemUpdated$: Observable = of({ "@timestamp": Date.now(), @@ -171,6 +173,7 @@ const credentialGenerated$: Observable = of({ }); export { + ItemAddedEvent, itemAdded$, itemUpdated$, itemDeleted$,