📄 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