musora-content-services 2.3.6 → 2.3.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.
Files changed (131) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/workflows/node.js.yml +0 -0
  4. package/.prettierignore +0 -0
  5. package/.prettierrc +0 -0
  6. package/.yarnrc.yml +1 -0
  7. package/CHANGELOG.md +2 -0
  8. package/README.md +0 -0
  9. package/babel.config.cjs +0 -0
  10. package/docs/Content-Organization.html +0 -0
  11. package/docs/ContentOrganization.html +0 -0
  12. package/docs/Gamification.html +0 -0
  13. package/docs/UserManagement.html +0 -0
  14. package/docs/UserManagementSystem.html +0 -0
  15. package/docs/api_types.js.html +0 -0
  16. package/docs/config.js.html +0 -0
  17. package/docs/content-org_content-org.js.html +0 -0
  18. package/docs/content-org_playlists-types.js.html +0 -0
  19. package/docs/content-org_playlists.js.html +0 -0
  20. package/docs/content.js.html +0 -0
  21. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  22. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  23. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  26. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  29. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  30. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  31. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  39. package/docs/gamification_awards.js.html +0 -0
  40. package/docs/gamification_gamification.js.html +0 -0
  41. package/docs/gamification_types.js.html +0 -0
  42. package/docs/global.html +0 -0
  43. package/docs/global.html#User +0 -0
  44. package/docs/index.html +0 -0
  45. package/docs/module-Awards.html +0 -0
  46. package/docs/module-Config.html +0 -0
  47. package/docs/module-Content-Services-V2.html +0 -0
  48. package/docs/module-Content-Services.html +763 -0
  49. package/docs/module-Permissions.html +0 -0
  50. package/docs/module-Playlists.html +0 -0
  51. package/docs/module-Railcontent-Services.html +0 -0
  52. package/docs/module-Sanity-Services.html +0 -0
  53. package/docs/module-Session-Management.html +0 -0
  54. package/docs/module-Sessions.html +0 -0
  55. package/docs/module-User-Management.html +0 -0
  56. package/docs/module-User-Permissions.html +0 -0
  57. package/docs/module-UserManagement.html +0 -0
  58. package/docs/railcontent.js.html +0 -0
  59. package/docs/sanity.js.html +0 -0
  60. package/docs/scripts/collapse.js +0 -0
  61. package/docs/scripts/commonNav.js +0 -0
  62. package/docs/scripts/linenumber.js +0 -0
  63. package/docs/scripts/nav.js +0 -0
  64. package/docs/scripts/polyfill.js +0 -0
  65. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  66. package/docs/scripts/prettify/lang-css.js +0 -0
  67. package/docs/scripts/prettify/prettify.js +0 -0
  68. package/docs/scripts/search.js +0 -0
  69. package/docs/styles/jsdoc.css +0 -0
  70. package/docs/styles/prettify.css +0 -0
  71. package/docs/types.js.html +0 -0
  72. package/docs/user_management.js.html +0 -0
  73. package/docs/user_permissions.js.html +0 -0
  74. package/docs/user_sessions.js.html +0 -0
  75. package/docs/user_types.js.html +0 -0
  76. package/docs/user_user-management-system.js.html +0 -0
  77. package/docs/user_user-management.js.html +0 -0
  78. package/jest.config.js +0 -0
  79. package/jsdoc.json +0 -0
  80. package/link_mcs.sh +0 -0
  81. package/package.json +1 -1
  82. package/src/contentMetaData.js +0 -0
  83. package/src/filterBuilder.js +0 -0
  84. package/src/index.d.ts +0 -0
  85. package/src/index.js +0 -0
  86. package/src/lib/httpHelper.js +0 -0
  87. package/src/lib/lastUpdated.js +0 -0
  88. package/src/services/api/types.js +0 -0
  89. package/src/services/config.js +0 -0
  90. package/src/services/content-org/content-org.js +0 -0
  91. package/src/services/content-org/playlists-types.js +0 -0
  92. package/src/services/content-org/playlists.js +0 -0
  93. package/src/services/content.js +0 -0
  94. package/src/services/contentLikes.js +0 -0
  95. package/src/services/contentProgress.js +0 -0
  96. package/src/services/dataContext.js +0 -0
  97. package/src/services/forum.js +0 -0
  98. package/src/services/gamification/awards.js +0 -0
  99. package/src/services/gamification/gamification.js +0 -0
  100. package/src/services/gamification/types.js +0 -0
  101. package/src/services/imageSRCBuilder.js +0 -0
  102. package/src/services/imageSRCVerify.js +0 -0
  103. package/src/services/railcontent.js +16 -3
  104. package/src/services/recommendations.js +0 -0
  105. package/src/services/types.js +0 -0
  106. package/src/services/user/management.js +0 -0
  107. package/src/services/user/permissions.js +0 -0
  108. package/src/services/user/sessions.js +0 -0
  109. package/src/services/user/types.js +0 -0
  110. package/src/services/user/user-management-system.js +0 -0
  111. package/src/services/userActivity.js +301 -90
  112. package/test/content.test.js +0 -0
  113. package/test/contentLikes.test.js +0 -0
  114. package/test/contentProgress.test.js +0 -0
  115. package/test/dataContext.test.js +0 -0
  116. package/test/forum.test.js +0 -0
  117. package/test/imageSRCBuilder.test.js +0 -0
  118. package/test/imageSRCVerify.test.js +0 -0
  119. package/test/initializeTests.js +0 -0
  120. package/test/lib/lastUpdated.test.js +0 -0
  121. package/test/live/contentProgressLive.test.js +0 -0
  122. package/test/live/railcontentLive.test.js +0 -0
  123. package/test/localStorageMock.js +0 -0
  124. package/test/log.js +0 -0
  125. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  126. package/test/mockData/mockData_user_practices.json +9 -0
  127. package/test/sanityQueryService.test.js +0 -0
  128. package/test/streakMessage.test.js +263 -0
  129. package/test/user/permissions.test.js +0 -0
  130. package/test/userActivity.test.js +6 -6
  131. package/tools/generate-index.cjs +0 -0
@@ -0,0 +1,263 @@
1
+ import { initializeTestService } from './initializeTests.js'
2
+ import {getUserWeeklyStats, userActivityContext} from '../src/services/userActivity.js'
3
+ import {log} from './log.js'
4
+
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+
8
+ global.fetch = jest.fn()
9
+ let mock = null
10
+ const DEBUG = false
11
+
12
+
13
+ // Test Examples are taken from this document
14
+ // https://docs.google.com/spreadsheets/d/1pBmBTAODeRWI5uIO84lXjaQFW-lRPNh6gi7GV0lCwyc/edit?gid=0#gid=0
15
+ describe('Streak Messages', function () {
16
+ beforeEach(() => {
17
+ initializeTestService()
18
+ const userLocalMidnight = new Date();
19
+ userLocalMidnight.setFullYear(2025, 2, 24);
20
+ jest.useFakeTimers();
21
+ jest.setSystemTime(userLocalMidnight);
22
+ })
23
+
24
+ test('streak message - example1', async () => {
25
+ const fixedDate = new Date('2025-03-24T12:00:00.000Z');
26
+ const allData = [
27
+ { day: 1, date: '2025-03-24', duration_seconds: 120 },
28
+ { day: 2, date: '2025-03-25', duration_seconds: 120 },
29
+ { day: 3, date: '2025-03-26', duration_seconds: 120 },
30
+ { day: 7, date: '2025-03-30', duration_seconds: 120 },
31
+ { day: 8, date: '2025-03-31', duration_seconds: 120 },
32
+ { day: 22, date: '2025-04-14', duration_seconds: 120 },
33
+ { day: 23, date: '2025-04-15', duration_seconds: 120 },
34
+ ]
35
+
36
+ const expectedMessages = [
37
+ {day: 1, incomplete: 'Start your streak by taking any lesson!', complete: 'Nice! You have a 1 day streak!'},
38
+ {day: 2, incomplete: 'You have a 1 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
39
+ {day: 3, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 3 day streak! Way to keep it going!'},
40
+ {day: 4, incomplete: 'You have a 3 day streak! Keep it going with any lesson or song!', complete: ''},
41
+ {day: 5, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
42
+ {day: 6, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
43
+ {day: 7, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: 'You have a 1 week streak! Way to keep up the momentum!'},
44
+ {day: 8, incomplete: 'You have a 1 week streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
45
+ {day: 9, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: ''},
46
+ {day: 10, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
47
+ {day: 11, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
48
+ {day: 12, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
49
+ {day: 13, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
50
+ {day: 14, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
51
+ {day: 15, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
52
+ {day: 16, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
53
+ {day: 17, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
54
+ {day: 18, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
55
+ {day: 19, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
56
+ {day: 20, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
57
+ {day: 21, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
58
+ {day: 22, incomplete: 'Restart your streak by taking any lesson!', complete: 'Nice! You have a 1 day streak!'},
59
+ {day: 23, incomplete: 'You have a 1 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
60
+ {day: 24, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: ''},
61
+ ]
62
+
63
+ mock = jest.spyOn(userActivityContext, 'fetchData')
64
+ // you can test a specific day by setting this value to the correct date and the test will only run that day
65
+ // this is 0 indexed
66
+ const testSpecificDay = null;
67
+ await testExpectedMessageForDays(allData, expectedMessages, fixedDate, testSpecificDay)
68
+ })
69
+
70
+ test('streak message - example2', async () => {
71
+ const fixedDate = new Date('2025-03-24T12:00:00.000Z');
72
+ const allData = [
73
+ { day: 1, date: '2025-03-24', duration_seconds: 120 },
74
+ { day: 8, date: '2025-03-31', duration_seconds: 120 },
75
+ { day: 10, date: '2025-04-02', duration_seconds: 120 },
76
+ { day: 11, date: '2025-04-03', duration_seconds: 120 },
77
+ { day: 13, date: '2025-04-05', duration_seconds: 120 },
78
+ { day: 16, date: '2025-04-08', duration_seconds: 120 },
79
+ ]
80
+
81
+ const expectedMessages = [
82
+ {day: 1, incomplete: 'Start your streak by taking any lesson!', complete: 'Nice! You have a 1 day streak!'},
83
+ {day: 2, incomplete: 'You have a 1 day streak! Keep it going with any lesson or song!', complete: ''},
84
+ {day: 3, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
85
+ {day: 4, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
86
+ {day: 5, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
87
+ {day: 6, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
88
+ {day: 7, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
89
+ {day: 8, incomplete: 'You have a 1 week streak! Keep it going with any lesson or song!', complete: 'Great job! You have a 2 week streak! Way to keep it going!'},
90
+ {day: 9, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
91
+ {day: 10, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'You have a 2 week streak! Way to keep up the momentum!'},
92
+ {day: 11, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
93
+ {day: 12, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: ''},
94
+ {day: 13, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'You have a 2 week streak! Way to keep up the momentum!'},
95
+ {day: 14, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
96
+ {day: 15, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
97
+ {day: 16, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: 'Great job! You have a 3 week streak! Way to keep it going!'},
98
+ {day: 17, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
99
+ {day: 18, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
100
+ {day: 19, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
101
+ {day: 20, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
102
+ {day: 21, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
103
+ {day: 22, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
104
+ {day: 23, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
105
+ {day: 24, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
106
+ {day: 25, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
107
+ {day: 26, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
108
+ {day: 27, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
109
+ {day: 28, incomplete: 'You have a 3 week streak! Keep it going with any lesson or song!', complete: ''},
110
+ ]
111
+
112
+ mock = jest.spyOn(userActivityContext, 'fetchData')
113
+ // you can test a specific day by setting this value to the correct date and the test will only run that day
114
+ // this is zero indexed so do 1 day below the day you want to test
115
+ const testSpecificDay = null;
116
+ await testExpectedMessageForDays(allData, expectedMessages, fixedDate, testSpecificDay)
117
+ })
118
+
119
+ test('streak message - example3', async () => {
120
+ const fixedDate = new Date('2025-03-24T12:00:00.000Z');
121
+ const allData = [
122
+ { day: 2, date: '2025-03-25', duration_seconds: 120 },
123
+ { day: 5, date: '2025-03-28', duration_seconds: 120 },
124
+ { day: 6, date: '2025-03-29', duration_seconds: 120 },
125
+ { day: 7, date: '2025-03-30', duration_seconds: 120 },
126
+ { day: 9, date: '2025-04-01', duration_seconds: 120 },
127
+ { day: 11, date: '2025-04-03', duration_seconds: 120 },
128
+ { day: 12, date: '2025-04-04', duration_seconds: 120 },
129
+ { day: 17, date: '2025-04-09', duration_seconds: 120 },
130
+ { day: 19, date: '2025-04-11', duration_seconds: 120 },
131
+ ]
132
+
133
+ const expectedMessages = [
134
+ {day: 1, incomplete: 'Start your streak by taking any lesson!', complete: ''},
135
+ {day: 2, incomplete: 'Start your streak by taking any lesson!', complete: 'Nice! You have a 1 day streak!'},
136
+ {day: 3, incomplete: 'You have a 1 day streak! Keep it going with any lesson or song!', complete: ''},
137
+ {day: 4, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: ''},
138
+ {day: 5, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: 'You have a 1 week streak! Way to keep up the momentum!'},
139
+ {day: 6, incomplete: 'You have a 1 week streak! Keep up the momentum!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
140
+ {day: 7, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 3 day streak! Way to keep it going!'},
141
+ {day: 8, incomplete: 'You have a 3 day streak! Keep it going with any lesson or song!', complete: ''},
142
+ {day: 9, incomplete: 'You have a 1 week streak! Keep it going with any lesson or song!', complete: 'Great job! You have a 2 week streak! Way to keep it going!'},
143
+ {day: 10, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
144
+ {day: 11, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'You have a 2 week streak! Way to keep up the momentum!'},
145
+ {day: 12, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
146
+ {day: 13, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: ''},
147
+ {day: 14, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: ''},
148
+ {day: 15, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
149
+ {day: 16, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: ''},
150
+ {day: 17, incomplete: 'You have a 2 week streak! Keep it going with any lesson or song!', complete: 'Great job! You have a 3 week streak! Way to keep it going!'},
151
+ {day: 18, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
152
+ {day: 19, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: 'You have a 3 week streak! Way to keep up the momentum!'},
153
+ {day: 20, incomplete: 'You have a 3 week streak! Keep up the momentum!', complete: ''},
154
+ ]
155
+
156
+ mock = jest.spyOn(userActivityContext, 'fetchData')
157
+ // you can test a specific day by setting this value to the correct date and the test will only run that day
158
+ // this is 0 indexed
159
+ const testSpecificDay = null;
160
+ await testExpectedMessageForDays(allData, expectedMessages, fixedDate, testSpecificDay)
161
+ })
162
+
163
+ test('streak message - example4', async () => {
164
+ const fixedDate = new Date('2025-03-24T12:00:00.000Z');
165
+ const allData = [
166
+ { day: 1, date: '2025-03-24', duration_seconds: 120},
167
+ { day: 2, date: '2025-03-25', duration_seconds: 120},
168
+ { day: 3, date: '2025-03-26', duration_seconds: 120},
169
+ { day: 4, date: '2025-03-27', duration_seconds: 120},
170
+ { day: 5, date: '2025-03-28', duration_seconds: 120},
171
+ { day: 6, date: '2025-03-29', duration_seconds: 120},
172
+ { day: 7, date: '2025-03-30', duration_seconds: 120},
173
+ { day: 8, date: '2025-03-31', duration_seconds: 120},
174
+ ]
175
+
176
+ const expectedMessages = [
177
+ {day: 1, incomplete: 'Start your streak by taking any lesson!', complete: 'Nice! You have a 1 day streak!'},
178
+ {day: 2, incomplete: 'You have a 1 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 2 day streak! Way to keep it going!'},
179
+ {day: 3, incomplete: 'You have a 2 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 3 day streak! Way to keep it going!'},
180
+ {day: 4, incomplete: 'You have a 3 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 4 day streak! Way to keep it going!'},
181
+ {day: 5, incomplete: 'You have a 4 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 5 day streak! Way to keep it going!'},
182
+ {day: 6, incomplete: 'You have a 5 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 6 day streak! Way to keep it going!'},
183
+ {day: 7, incomplete: 'You have a 6 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have a 7 day streak! Way to keep it going!'},
184
+ {day: 8, incomplete: 'You have a 7 day streak! Keep it going with any lesson or song!', complete: 'Nice! You have an 8 day streak! Way to keep it going!'},
185
+ {day: 9, incomplete: 'You have an 8 day streak! Keep it going with any lesson or song!', complete: ''},
186
+ {day: 10, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'You have a 2 week streak! Keep up the momentum!'},
187
+ {day: 11, incomplete: 'You have a 2 week streak! Keep up the momentum!', complete: 'You have a 2 week streak! Keep up the momentum!'},
188
+ ]
189
+
190
+ mock = jest.spyOn(userActivityContext, 'fetchData')
191
+ // you can test a specific day by setting this value to the correct date and the test will only run that day
192
+ // this is 0 indexed
193
+ const testSpecificDay = null;
194
+ await testExpectedMessageForDays(allData, expectedMessages, fixedDate, testSpecificDay)
195
+ })
196
+ })
197
+
198
+ function incrementFakeDate(nDays = 1){
199
+ let today = new Date();
200
+ today.setFullYear(today.getFullYear(), today.getMonth(), (today.getDate() + nDays));
201
+ jest.useFakeTimers();
202
+ jest.setSystemTime(today);
203
+ }
204
+
205
+ const loadMockDataForDays = (fileName, datesArray) => {
206
+ const jsonPath = path.join(__dirname, 'mockData/', fileName);
207
+ let json = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
208
+ let practices = {};
209
+ // Loop through the provided dates and durations
210
+ datesArray.forEach(({ date, duration_seconds }) => {
211
+ practices[date] = [{ "duration_seconds": duration_seconds }];
212
+ });
213
+
214
+ // Replace the placeholder with dynamically generated data
215
+ json.data.practices = practices;
216
+ return json;
217
+ };
218
+
219
+ function sliceExampleData(startDate, nDays, includeToday, activeDays)
220
+ {
221
+ if (nDays === 0 && !includeToday) {
222
+ return []
223
+ }
224
+ nDays = includeToday ? nDays : nDays - 1
225
+ let target = new Date(startDate)
226
+ target.setDate(target.getDate() + nDays)
227
+ return activeDays.filter((obj) => {
228
+ let activeDate = new Date(obj.date)
229
+ return activeDate <= target
230
+ })
231
+ }
232
+
233
+ async function testExpectedMessageForDays(exampleData, expectedMessages, startDate, testDayN = null) {
234
+ const start = testDayN ?? 0;
235
+ const end = testDayN != null ? testDayN + 1 : expectedMessages.length
236
+ if (testDayN != null) incrementFakeDate(testDayN)
237
+ for (let i = start; i < end; i++) {
238
+ let target = new Date(startDate)
239
+ target.setDate(target.getDate() + i)
240
+ const setDataAndCheckStreakMessage = async function(includeToday) {
241
+ let activeDays = sliceExampleData(startDate, i, includeToday, exampleData)
242
+ let json = loadMockDataForDays('mockData_user_practices.json', activeDays);
243
+ mock.mockImplementation(() => json);
244
+ userActivityContext.clearCache()
245
+ let practices = await getUserWeeklyStats()
246
+ const state = includeToday ? 'STARTED' : 'NOT-STARTED'
247
+ const expected = includeToday && !!expectedMessages[i].complete ? expectedMessages[i].complete :
248
+ expectedMessages[i].incomplete
249
+ const day = expectedMessages[i].day
250
+ log(`Running ${state} content tests for Day ${day} on ${target}`)
251
+ log(`Expecting ${expected}`)
252
+ expect(practices.data.streakMessage).toBeDefined()
253
+ if (practices.data.streakMessage !== expected) {
254
+ throw new Error(`Mismatch on Day ${expectedMessages[i].day} [${target.toDateString()}]:
255
+ Expected: "${expected}"
256
+ Received: "${practices.data.streakMessage}"`);
257
+ }
258
+ }
259
+ await setDataAndCheckStreakMessage(false)
260
+ await setDataAndCheckStreakMessage(true)
261
+ incrementFakeDate(1)
262
+ }
263
+ }
File without changes
@@ -1,6 +1,5 @@
1
1
  import { initializeTestService } from './initializeTests.js'
2
- import {getUserMonthlyStats, getUserWeeklyStats, userActivityContext, recordUserPractice, getUserPractices} from '../src/services/userActivity.js'
3
- import { logUserPractice } from '../src/services/railcontent.js'
2
+ import {getUserMonthlyStats, getUserWeeklyStats, userActivityContext, recordUserPractice} from '../src/services/userActivity.js'
4
3
  import {fetchByRailContentIds} from "../src";
5
4
  import mockData_fetchByRailContentIds_one_content from './mockData/mockData_fetchByRailContentIds_one_content.json';
6
5
 
@@ -53,10 +52,9 @@ describe('User Activity API Tests', function () {
53
52
  const practices = await getUserMonthlyStats()
54
53
  consoleLog(practices)
55
54
  // Assert that dailyActiveStats contains correct data
56
- const dailyStats = practices.dailyActiveStats
55
+ const dailyStats = practices.data.dailyActiveStats
57
56
  const currentDate = new Date()
58
57
  const currentDateString = currentDate.toISOString().split('T')[0]
59
- expect(dailyStats).toHaveLength(42)
60
58
 
61
59
  // Verify current day's stats (e.g., March 17, 2025)
62
60
  const current = dailyStats.find(stat => stat.label === currentDateString)
@@ -75,7 +73,7 @@ describe('User Activity API Tests', function () {
75
73
  consoleLog(practices)
76
74
 
77
75
  // Assert that dailyActiveStats contains correct data
78
- const dailyStats = practices.dailyActiveStats
76
+ const dailyStats = practices.data.dailyActiveStats
79
77
  const feb10 = dailyStats.find(stat => stat.label === '2025-02-10')
80
78
  expect(feb10.inStreak).toBe(true)
81
79
  expect(feb10.type).toBe('tracked')
@@ -87,7 +85,7 @@ describe('User Activity API Tests', function () {
87
85
  const practices = await getUserWeeklyStats( )
88
86
  consoleLog(practices)
89
87
 
90
- const dailyStats = practices.dailyActiveStats
88
+ const dailyStats = practices.data.dailyActiveStats
91
89
  const monday = dailyStats.find(stat => stat.label === 'M')
92
90
  expect(monday).toBeDefined
93
91
  const tuesday = dailyStats.find(stat => stat.label === 'T')
@@ -116,3 +114,5 @@ describe('User Activity API Tests', function () {
116
114
  }
117
115
  }
118
116
  })
117
+
118
+
File without changes