📄 src/models/test/stats.test.ts
D-OPEN SOVEREIGN
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 *
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 *
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15import { describe, it, expect, beforeEach, vi } from 'vitest';
16import { Stats, FavoritesByTypes, DownloadsByType, VisitsByType, PopulateStatsStore } from '../stats.ts';
17import { Rating, ActionTypes } from '../enums.ts';
18import { DateUtils } from '../dates.ts';
19
20describe('Stats', () => {
21 beforeEach(() => {
22 vi.spyOn(DateUtils, 'now').mockReturnValue(100);
23 // Clear global StatsStore mapping since it's module level
24 // We can just create unique object types for isolation
25 });
26
27 it('handles visit and visitPart', () => {
28 const type = 101;
29 const id = 1;
30 const stats = new Stats(id, type);
31
32 stats.visit();
33 stats.visitPart(5);
34 stats.visitPart(5);
35
36 const visits = VisitsByType(type);
37 expect(visits).toContain(id);
38
39 const favs = FavoritesByTypes(type);
40 expect(favs.length).toBe(1);
41 expect(favs[0].id).toBe(id);
42 expect(favs[0].nbVisits).toBe(1);
43
44 const parts = stats.favoriteParts();
45 expect(parts.length).toBe(1);
46 expect(parts[0].partId).toBe(5);
47 expect(parts[0].nbVisits).toBe(2);
48 });
49
50 it('handles download', () => {
51 const type = 102;
52 const id = 2;
53 const stats = new Stats(id, type);
54
55 stats.download();
56 const dls = DownloadsByType(type);
57 expect(dls).toContain(id);
58 });
59
60 it('handles rate and ratePart', () => {
61 const type = 103;
62 const id = 3;
63 const stats = new Stats(id, type);
64
65 stats.rating = Rating.Keep;
66 expect(stats.rating).toBe(Rating.Keep);
67
68 stats.ratePart(10, Rating.Awesome);
69 const parts = stats.favoriteParts();
70 expect(parts[0].partId).toBe(10);
71 expect(parts[0].rating).toBe(Rating.Awesome);
72 });
73
74 it('handles share', () => {
75 const type = 104;
76 const id = 4;
77 const stats = new Stats(id, type);
78
79 stats.share(1); // 1 = some social media id
80
81 // Populate directly to test share part
82 PopulateStatsStore([{
83 action: ActionTypes.SharePart,
84 ts: 100,
85 objectId: id,
86 objectType: type,
87 part: 2,
88 socialMediaId: 1
89 } as any]);
90
91 expect(stats.favoriteParts().find(p => p.partId === 2)).toBeDefined();
92 });
93});
94