@insignia-education/api-sdk-js 0.15.61 → 0.15.63

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 (90) hide show
  1. package/.github/workflows/npm-publish-github-packages.yml +95 -12
  2. package/coverage/clover.xml +132 -1512
  3. package/coverage/coverage-final.json +1 -47
  4. package/coverage/lcov-report/Client.js.html +463 -0
  5. package/coverage/lcov-report/index.html +20 -65
  6. package/coverage/lcov-report/src/Client.js.html +141 -132
  7. package/coverage/lcov-report/src/api/index.html +1 -1
  8. package/coverage/lcov-report/src/api/index.js.html +8 -8
  9. package/coverage/lcov-report/src/api/v1/Accounts.js.html +3 -3
  10. package/coverage/lcov-report/src/api/v1/Admin.js.html +3 -3
  11. package/coverage/lcov-report/src/api/v1/Auth.js.html +7 -7
  12. package/coverage/lcov-report/src/api/v1/Categories.js.html +8 -8
  13. package/coverage/lcov-report/src/api/v1/Changelogs.js.html +8 -8
  14. package/coverage/lcov-report/src/api/v1/Configs.js.html +8 -8
  15. package/coverage/lcov-report/src/api/v1/ContactForms.js.html +8 -8
  16. package/coverage/lcov-report/src/api/v1/ConversationalTopics.js.html +8 -8
  17. package/coverage/lcov-report/src/api/v1/Countries.js.html +8 -8
  18. package/coverage/lcov-report/src/api/v1/Coupons.js.html +16 -16
  19. package/coverage/lcov-report/src/api/v1/Courses.js.html +27 -27
  20. package/coverage/lcov-report/src/api/v1/Currencies.js.html +10 -10
  21. package/coverage/lcov-report/src/api/v1/Dashboard.js.html +3 -3
  22. package/coverage/lcov-report/src/api/v1/EducationCenter.js.html +3 -3
  23. package/coverage/lcov-report/src/api/v1/Employee.js.html +5 -5
  24. package/coverage/lcov-report/src/api/v1/Files.js.html +8 -8
  25. package/coverage/lcov-report/src/api/v1/Forums.js.html +8 -8
  26. package/coverage/lcov-report/src/api/v1/Hashes.js.html +16 -13
  27. package/coverage/lcov-report/src/api/v1/Insignias.js.html +8 -8
  28. package/coverage/lcov-report/src/api/v1/Languages.js.html +8 -8
  29. package/coverage/lcov-report/src/api/v1/MailBlacklist.js.html +8 -8
  30. package/coverage/lcov-report/src/api/v1/MailingLists.js.html +3 -3
  31. package/coverage/lcov-report/src/api/v1/Offers.js.html +16 -16
  32. package/coverage/lcov-report/src/api/v1/Organizations.js.html +52 -52
  33. package/coverage/lcov-report/src/api/v1/PaymentMethods.js.html +7 -7
  34. package/coverage/lcov-report/src/api/v1/Payments.js.html +3 -3
  35. package/coverage/lcov-report/src/api/v1/Premiums.js.html +3 -3
  36. package/coverage/lcov-report/src/api/v1/Quizzes.js.html +42 -42
  37. package/coverage/lcov-report/src/api/v1/Sales.js.html +3 -3
  38. package/coverage/lcov-report/src/api/v1/Search.js.html +3 -3
  39. package/coverage/lcov-report/src/api/v1/ShortLinks.js.html +8 -8
  40. package/coverage/lcov-report/src/api/v1/Surveys.js.html +8 -8
  41. package/coverage/lcov-report/src/api/v1/Taxes.js.html +8 -8
  42. package/coverage/lcov-report/src/api/v1/Teacher.js.html +100 -70
  43. package/coverage/lcov-report/src/api/v1/Telegram.js.html +3 -3
  44. package/coverage/lcov-report/src/api/v1/TwoFactor.js.html +3 -3
  45. package/coverage/lcov-report/src/api/v1/UserSessionTypes.js.html +3 -3
  46. package/coverage/lcov-report/src/api/v1/UserTypes.js.html +8 -8
  47. package/coverage/lcov-report/src/api/v1/Users.js.html +112 -16
  48. package/coverage/lcov-report/src/api/v1/Utm.js.html +3 -3
  49. package/coverage/lcov-report/src/api/v1/Webauthn.js.html +3 -3
  50. package/coverage/lcov-report/src/api/v1/Zoom.js.html +19 -19
  51. package/coverage/lcov-report/src/api/v1/index.html +154 -184
  52. package/coverage/lcov-report/src/api/v1/index.js.html +52 -64
  53. package/coverage/lcov-report/src/index.html +21 -21
  54. package/coverage/lcov-report/src/index.js.html +3 -3
  55. package/coverage/lcov-report/tests/helpers.js.html +11 -11
  56. package/coverage/lcov-report/tests/index.html +7 -7
  57. package/coverage/lcov.info +146 -2451
  58. package/coverage/test-report.html +1 -10
  59. package/jest.config.mjs +12 -1
  60. package/package.json +2 -2
  61. package/src/api/v1/Coupons.js +11 -0
  62. package/src/api/v1/Courses.js +2 -0
  63. package/src/api/v1/Hashes.js +3 -2
  64. package/src/api/v1/Telegram.js +6 -0
  65. package/src/api/v1/Users.js +12 -0
  66. package/src/api/v1/index.js +0 -4
  67. package/tests/integration/api/v1/accounts.test.js +5 -11
  68. package/tests/integration/api/v1/auth/login.test.js +18 -34
  69. package/tests/integration/api/v1/conversational-topics.test.js +3 -5
  70. package/tests/integration/api/v1/countries.test.js +1 -1
  71. package/tests/integration/api/v1/coupons.test.js +2 -9
  72. package/tests/integration/api/v1/currencies/index.test.js +1 -1
  73. package/tests/integration/api/v1/files.test.js +18 -15
  74. package/tests/integration/api/v1/hashes.test.js +2 -10
  75. package/tests/integration/api/v1/mail-blacklist.test.js +2 -9
  76. package/tests/integration/api/v1/offers.test.js +2 -9
  77. package/tests/integration/api/v1/organizations.test.js +8 -8
  78. package/tests/integration/api/v1/quizzes/index.test.js +0 -2
  79. package/tests/integration/api/v1/short-links.test.js +2 -9
  80. package/tests/integration/api/v1/taxes.test.js +2 -3
  81. package/tests/integration/api/v1/teacher/index.test.js +1 -1
  82. package/tests/integration/api/v1/telegram.test.js +33 -0
  83. package/tests/integration/api/v1/user-types.test.js +2 -4
  84. package/tests/integration/api/v1/users/index.test.js +10 -13
  85. package/tests/integration/api/v1/users/telegram.test.js +36 -0
  86. package/tests/integration/api/v1/zoom.test.js +2 -9
  87. package/src/api/v1/Categories.js +0 -12
  88. package/src/api/v1/Configs.js +0 -12
  89. package/tests/integration/api/v1/categories.test.js +0 -19
  90. package/tests/integration/api/v1/configs.test.js +0 -20
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">21.73% </span>
26
+ <span class="strong">59.49% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>15/69</span>
28
+ <span class='fraction'>47/79</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">100% </span>
33
+ <span class="strong">53.33% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>2/2</span>
35
+ <span class='fraction'>8/15</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">33.33% </span>
40
+ <span class="strong">44.44% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>2/6</span>
42
+ <span class='fraction'>8/18</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">21.73% </span>
47
+ <span class="strong">59.49% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>15/69</span>
49
+ <span class='fraction'>47/79</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line low'></div>
64
+ <div class='status-line medium'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -132,7 +132,51 @@
132
132
  <a name='L67'></a><a href='#L67'>67</a>
133
133
  <a name='L68'></a><a href='#L68'>68</a>
134
134
  <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
146
+ <span class="cline-any cline-yes">1x</span>
147
+ <span class="cline-any cline-yes">1x</span>
148
+ <span class="cline-any cline-yes">1x</span>
149
+ <span class="cline-any cline-yes">30x</span>
150
+ <span class="cline-any cline-yes">30x</span>
151
+ <span class="cline-any cline-yes">1x</span>
152
+ <span class="cline-any cline-yes">1x</span>
153
+ <span class="cline-any cline-yes">1x</span>
154
+ <span class="cline-any cline-yes">1x</span>
155
+ <span class="cline-any cline-yes">1x</span>
156
+ <span class="cline-any cline-yes">1x</span>
157
+ <span class="cline-any cline-yes">1x</span>
158
+ <span class="cline-any cline-yes">1x</span>
159
+ <span class="cline-any cline-yes">1x</span>
160
+ <span class="cline-any cline-yes">1x</span>
161
+ <span class="cline-any cline-yes">1x</span>
162
+ <span class="cline-any cline-yes">1x</span>
163
+ <span class="cline-any cline-yes">1x</span>
164
+ <span class="cline-any cline-yes">1x</span>
165
+ <span class="cline-any cline-yes">1x</span>
166
+ <span class="cline-any cline-yes">1x</span>
167
+ <span class="cline-any cline-yes">1x</span>
168
+ <span class="cline-any cline-yes">1x</span>
169
+ <span class="cline-any cline-yes">1x</span>
170
+ <span class="cline-any cline-yes">1x</span>
171
+ <span class="cline-any cline-yes">1x</span>
172
+ <span class="cline-any cline-yes">1x</span>
173
+ <span class="cline-any cline-yes">1x</span>
174
+ <span class="cline-any cline-yes">1x</span>
175
+ <span class="cline-any cline-yes">1x</span>
176
+ <span class="cline-any cline-yes">1x</span>
177
+ <span class="cline-any cline-yes">1x</span>
178
+ <span class="cline-any cline-yes">1x</span>
179
+ <span class="cline-any cline-yes">1x</span>
136
180
  <span class="cline-any cline-yes">1x</span>
137
181
  <span class="cline-any cline-yes">1x</span>
138
182
  <span class="cline-any cline-yes">1x</span>
@@ -140,28 +184,8 @@
140
184
  <span class="cline-any cline-yes">1x</span>
141
185
  <span class="cline-any cline-yes">1x</span>
142
186
  <span class="cline-any cline-yes">1x</span>
143
- <span class="cline-any cline-no">&nbsp;</span>
144
- <span class="cline-any cline-no">&nbsp;</span>
145
- <span class="cline-any cline-no">&nbsp;</span>
146
- <span class="cline-any cline-no">&nbsp;</span>
147
- <span class="cline-any cline-no">&nbsp;</span>
148
- <span class="cline-any cline-no">&nbsp;</span>
149
- <span class="cline-any cline-no">&nbsp;</span>
150
- <span class="cline-any cline-no">&nbsp;</span>
151
187
  <span class="cline-any cline-yes">1x</span>
152
188
  <span class="cline-any cline-yes">1x</span>
153
- <span class="cline-any cline-no">&nbsp;</span>
154
- <span class="cline-any cline-no">&nbsp;</span>
155
- <span class="cline-any cline-no">&nbsp;</span>
156
- <span class="cline-any cline-no">&nbsp;</span>
157
- <span class="cline-any cline-no">&nbsp;</span>
158
- <span class="cline-any cline-no">&nbsp;</span>
159
- <span class="cline-any cline-no">&nbsp;</span>
160
- <span class="cline-any cline-no">&nbsp;</span>
161
- <span class="cline-any cline-no">&nbsp;</span>
162
- <span class="cline-any cline-no">&nbsp;</span>
163
- <span class="cline-any cline-no">&nbsp;</span>
164
- <span class="cline-any cline-no">&nbsp;</span>
165
189
  <span class="cline-any cline-yes">1x</span>
166
190
  <span class="cline-any cline-yes">1x</span>
167
191
  <span class="cline-any cline-no">&nbsp;</span>
@@ -176,10 +200,6 @@
176
200
  <span class="cline-any cline-no">&nbsp;</span>
177
201
  <span class="cline-any cline-no">&nbsp;</span>
178
202
  <span class="cline-any cline-no">&nbsp;</span>
179
- <span class="cline-any cline-yes">1x</span>
180
- <span class="cline-any cline-yes">1x</span>
181
- <span class="cline-any cline-no">&nbsp;</span>
182
- <span class="cline-any cline-no">&nbsp;</span>
183
203
  <span class="cline-any cline-no">&nbsp;</span>
184
204
  <span class="cline-any cline-no">&nbsp;</span>
185
205
  <span class="cline-any cline-no">&nbsp;</span>
@@ -208,43 +228,43 @@
208
228
  this.#client = client;
209
229
  }
210
230
  &nbsp;
211
- <span class="fstat-no" title="function not covered" > absences() {</span>
212
- <span class="cstat-no" title="statement not covered" > const base = '/teacher/absences';</span>
213
- <span class="cstat-no" title="statement not covered" > return {</span>
214
- <span class="cstat-no" title="statement not covered" > get: (id = null) =&gt; id ? this.#client.get(`${base}/${id}`) : this.#client.get(base),</span>
215
- <span class="cstat-no" title="statement not covered" > create: (data) =&gt; this.#client.put(base, data),</span>
216
- <span class="cstat-no" title="statement not covered" > edit: (id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
217
- <span class="cstat-no" title="statement not covered" > delete: (id) =&gt; this.#client.del(`${base}/${id}`),</span>
218
- <span class="cstat-no" title="statement not covered" > };</span>
219
- <span class="cstat-no" title="statement not covered" > }</span>
231
+ absences() {
232
+ const base = '/teacher/absences';
233
+ return {
234
+ get: (id = null) =&gt; id<span class="branch-0 cbranch-no" title="branch not covered" > ? this.#client.get(`${base}/${id}`) </span>: this.#client.get(base),
235
+ create: (<span class="fstat-no" title="function not covered" >data) =&gt; this.#client.put(base, data),</span>
236
+ edit: <span class="fstat-no" title="function not covered" >(id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
237
+ delete: (<span class="fstat-no" title="function not covered" >id) =&gt; this.#client.del(`${base}/${id}`),</span>
238
+ };
239
+ }
220
240
  &nbsp;
221
- <span class="fstat-no" title="function not covered" > configSets() {</span>
222
- <span class="cstat-no" title="statement not covered" > const base = '/teacher/config-sets';</span>
223
- <span class="cstat-no" title="statement not covered" > return {</span>
224
- <span class="cstat-no" title="statement not covered" > /** get() / get(id) / get({ user_id }) — the last filters the list to one teacher's sets. */</span>
225
- <span class="cstat-no" title="statement not covered" > get: (idOrParams = null) =&gt; {</span>
226
- <span class="cstat-no" title="statement not covered" > if (idOrParams &amp;&amp; typeof idOrParams === 'object') return this.#client.get(base, idOrParams);</span>
227
- <span class="cstat-no" title="statement not covered" > return idOrParams ? this.#client.get(`${base}/${idOrParams}`) : this.#client.get(base);</span>
228
- <span class="cstat-no" title="statement not covered" > },</span>
229
- <span class="cstat-no" title="statement not covered" > create: (data) =&gt; this.#client.put(base, data),</span>
230
- <span class="cstat-no" title="statement not covered" > edit: (id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
231
- <span class="cstat-no" title="statement not covered" > delete: (id) =&gt; this.#client.del(`${base}/${id}`),</span>
232
- <span class="cstat-no" title="statement not covered" > };</span>
233
- <span class="cstat-no" title="statement not covered" > }</span>
241
+ configSets() {
242
+ const base = '/teacher/config-sets';
243
+ return {
244
+ /** get() / get(id) / get({ user_id }) — the last filters the list to one teacher's sets. */
245
+ get: (idOrParams = null) =&gt; {
246
+ if (idOrParams<span class="branch-0 cbranch-no" title="branch not covered" > &amp;&amp; typeof idOrParams === 'object')</span> <span class="branch-0 cbranch-no" title="branch not covered" >return this.#client.get(base, idOrParams);</span>
247
+ return idOrParams<span class="branch-0 cbranch-no" title="branch not covered" > ? this.#client.get(`${base}/${idOrParams}`) </span>: this.#client.get(base);
248
+ },
249
+ create: (<span class="fstat-no" title="function not covered" >data) =&gt; this.#client.put(base, data),</span>
250
+ edit: <span class="fstat-no" title="function not covered" >(id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
251
+ delete: (<span class="fstat-no" title="function not covered" >id) =&gt; this.#client.del(`${base}/${id}`),</span>
252
+ };
253
+ }
234
254
  &nbsp;
235
- <span class="fstat-no" title="function not covered" > configs() {</span>
236
- <span class="cstat-no" title="statement not covered" > const base = '/teacher/configs';</span>
237
- <span class="cstat-no" title="statement not covered" > return {</span>
238
- <span class="cstat-no" title="statement not covered" > /** get() / get(id) / get({ config_set_id }) — the last filters the list to one config set. */</span>
239
- <span class="cstat-no" title="statement not covered" > get: (idOrParams = null) =&gt; {</span>
240
- <span class="cstat-no" title="statement not covered" > if (idOrParams &amp;&amp; typeof idOrParams === 'object') return this.#client.get(base, idOrParams);</span>
241
- <span class="cstat-no" title="statement not covered" > return idOrParams ? this.#client.get(`${base}/${idOrParams}`) : this.#client.get(base);</span>
242
- <span class="cstat-no" title="statement not covered" > },</span>
243
- <span class="cstat-no" title="statement not covered" > create: (data) =&gt; this.#client.put(base, data),</span>
244
- <span class="cstat-no" title="statement not covered" > edit: (id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
245
- <span class="cstat-no" title="statement not covered" > delete: (id) =&gt; this.#client.del(`${base}/${id}`),</span>
246
- <span class="cstat-no" title="statement not covered" > };</span>
247
- <span class="cstat-no" title="statement not covered" > }</span>
255
+ configs() {
256
+ const base = '/teacher/configs';
257
+ return {
258
+ /** get() / get(id) / get({ config_set_id }) — the last filters the list to one config set. */
259
+ get: (idOrParams = null) =&gt; {
260
+ if (idOrParams<span class="branch-0 cbranch-no" title="branch not covered" > &amp;&amp; typeof idOrParams === 'object')</span> <span class="branch-0 cbranch-no" title="branch not covered" >return this.#client.get(base, idOrParams);</span>
261
+ return idOrParams<span class="branch-0 cbranch-no" title="branch not covered" > ? this.#client.get(`${base}/${idOrParams}`) </span>: this.#client.get(base);
262
+ },
263
+ create: (<span class="fstat-no" title="function not covered" >data) =&gt; this.#client.put(base, data),</span>
264
+ edit: <span class="fstat-no" title="function not covered" >(id, data) =&gt; this.#client.patch(`${base}/${id}`, data),</span>
265
+ delete: (<span class="fstat-no" title="function not covered" >id) =&gt; this.#client.del(`${base}/${id}`),</span>
266
+ };
267
+ }
248
268
  &nbsp;
249
269
  <span class="fstat-no" title="function not covered" > dashboard() {</span>
250
270
  <span class="cstat-no" title="statement not covered" > const base = '/teacher/dashboard';</span>
@@ -259,10 +279,20 @@
259
279
  <span class="cstat-no" title="statement not covered" > courseDateContentDownload: (courseDateId) =&gt; this.#client.get(`${base}/course-dates/${courseDateId}/content-download`),</span>
260
280
  <span class="cstat-no" title="statement not covered" > /** Ungraded quiz submissions from one CourseDate's own students. */</span>
261
281
  <span class="cstat-no" title="statement not covered" > courseDateUngradedQuizzes: (courseDateId) =&gt; this.#client.get(`${base}/course-dates/${courseDateId}/quizzes/ungraded`),</span>
282
+ <span class="cstat-no" title="statement not covered" > /** Already-graded quiz submissions from one CourseDate's own students, optionally narrowed to one quiz. */</span>
283
+ <span class="cstat-no" title="statement not covered" > courseDateGradedQuizzes: (courseDateId, quizId = null) =&gt; this.#client.get(`${base}/course-dates/${courseDateId}/quizzes/graded`, quizId ? { quiz_id: quizId } : {}),</span>
284
+ <span class="cstat-no" title="statement not covered" > /** Distinct { id, title } quizzes needing correction under this CourseDate's course — for the graded-tab quiz filter. */</span>
285
+ <span class="cstat-no" title="statement not covered" > courseDateCorrectableQuizzes: (courseDateId) =&gt; this.#client.get(`${base}/course-dates/${courseDateId}/quizzes/correctable`),</span>
262
286
  <span class="cstat-no" title="statement not covered" > /** Ungraded quiz submissions grouped by course, for every course this teacher teaches. */</span>
263
287
  <span class="cstat-no" title="statement not covered" > ungradedQuizzes: () =&gt; this.#client.get(`${base}/quizzes/ungraded`),</span>
288
+ <span class="cstat-no" title="statement not covered" > /** Full attempt detail (all score fields, answers, quiz.questions.answers eager-loaded) for one of this teacher's own students. */</span>
289
+ <span class="cstat-no" title="statement not covered" > quizDetail: (id) =&gt; this.#client.get(`${base}/quizzes/${id}`),</span>
290
+ <span class="cstat-no" title="statement not covered" > /** Grade (or partially grade) an attempt: any field omitted keeps its current value, so open/audio/session can be saved independently of finalizing (teacher_graded_at). */</span>
291
+ <span class="cstat-no" title="statement not covered" > gradeQuiz: (id, data) =&gt; this.#client.patch(`${base}/quizzes/${id}/grade`, data),</span>
264
292
  <span class="cstat-no" title="statement not covered" > /** Mark one student's attendance (present: true/false) on one of this teacher's own sessions. */</span>
265
293
  <span class="cstat-no" title="statement not covered" > markAttendance: (sessionId, studentId, present) =&gt; this.#client.patch(`${base}/sessions/${sessionId}/attendance`, { student_id: studentId, present }),</span>
294
+ <span class="cstat-no" title="statement not covered" > /** Mark the teacher's own presence (present: true/false) on one of their own sessions. */</span>
295
+ <span class="cstat-no" title="statement not covered" > markTeacherPresent: (sessionId, present) =&gt; this.#client.patch(`${base}/sessions/${sessionId}/teacher-present`, { present }),</span>
266
296
  <span class="cstat-no" title="statement not covered" > /** Attendance/substitution totals. Pass { from, to } (YYYY-MM-DD) to filter, omit for all-time. */</span>
267
297
  <span class="cstat-no" title="statement not covered" > stats: ({ from, to } = {}) =&gt; this.#client.get(`${base}/stats`, { from, to }),</span>
268
298
  <span class="cstat-no" title="statement not covered" > /** Pay owed for sessions taught (teacher_present = 1), per course. Pass { from, to } (YYYY-MM-DD) to filter, omit for all-time. */</span>
@@ -277,7 +307,7 @@
277
307
  <div class='footer quiet pad2 space-top1 center small'>
278
308
  Code coverage generated by
279
309
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
280
- at 2026-08-03T13:22:45.069Z
310
+ at 2026-08-09T19:41:47.271Z
281
311
  </div>
282
312
  <script src="../../../prettify.js"></script>
283
313
  <script>
@@ -80,8 +80,8 @@
80
80
  <span class="cline-any cline-yes">1x</span>
81
81
  <span class="cline-any cline-yes">1x</span>
82
82
  <span class="cline-any cline-yes">1x</span>
83
- <span class="cline-any cline-yes">1x</span>
84
- <span class="cline-any cline-yes">1x</span>
83
+ <span class="cline-any cline-yes">30x</span>
84
+ <span class="cline-any cline-yes">30x</span>
85
85
  <span class="cline-any cline-yes">1x</span>
86
86
  <span class="cline-any cline-yes">1x</span>
87
87
  <span class="cline-any cline-yes">1x</span>
@@ -109,7 +109,7 @@
109
109
  <div class='footer quiet pad2 space-top1 center small'>
110
110
  Code coverage generated by
111
111
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
112
- at 2026-08-03T13:22:45.069Z
112
+ at 2026-08-09T19:41:47.271Z
113
113
  </div>
114
114
  <script src="../../../prettify.js"></script>
115
115
  <script>
@@ -91,8 +91,8 @@
91
91
  <span class="cline-any cline-yes">1x</span>
92
92
  <span class="cline-any cline-yes">1x</span>
93
93
  <span class="cline-any cline-yes">1x</span>
94
- <span class="cline-any cline-yes">1x</span>
95
- <span class="cline-any cline-yes">1x</span>
94
+ <span class="cline-any cline-yes">30x</span>
95
+ <span class="cline-any cline-yes">30x</span>
96
96
  <span class="cline-any cline-yes">1x</span>
97
97
  <span class="cline-any cline-yes">1x</span>
98
98
  <span class="cline-any cline-yes">1x</span>
@@ -130,7 +130,7 @@ export default class TwoFactor {
130
130
  <div class='footer quiet pad2 space-top1 center small'>
131
131
  Code coverage generated by
132
132
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
133
- at 2026-08-03T13:22:45.069Z
133
+ at 2026-08-09T19:41:47.271Z
134
134
  </div>
135
135
  <script src="../../../prettify.js"></script>
136
136
  <script>
@@ -76,8 +76,8 @@
76
76
  <span class="cline-any cline-yes">1x</span>
77
77
  <span class="cline-any cline-yes">1x</span>
78
78
  <span class="cline-any cline-yes">1x</span>
79
- <span class="cline-any cline-yes">1x</span>
80
- <span class="cline-any cline-yes">1x</span>
79
+ <span class="cline-any cline-yes">30x</span>
80
+ <span class="cline-any cline-yes">30x</span>
81
81
  <span class="cline-any cline-yes">1x</span>
82
82
  <span class="cline-any cline-yes">1x</span>
83
83
  <span class="cline-any cline-yes">1x</span>
@@ -97,7 +97,7 @@
97
97
  <div class='footer quiet pad2 space-top1 center small'>
98
98
  Code coverage generated by
99
99
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
100
- at 2026-08-03T13:22:45.069Z
100
+ at 2026-08-09T19:41:47.271Z
101
101
  </div>
102
102
  <script src="../../../prettify.js"></script>
103
103
  <script>
@@ -30,16 +30,16 @@
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">100% </span>
33
+ <span class="strong">75% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>2/2</span>
35
+ <span class='fraction'>3/4</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">33.33% </span>
40
+ <span class="strong">50% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>2/6</span>
42
+ <span class='fraction'>3/6</span>
43
43
  </div>
44
44
 
45
45
 
@@ -79,8 +79,8 @@
79
79
  <span class="cline-any cline-yes">1x</span>
80
80
  <span class="cline-any cline-yes">1x</span>
81
81
  <span class="cline-any cline-yes">1x</span>
82
- <span class="cline-any cline-yes">1x</span>
83
- <span class="cline-any cline-yes">1x</span>
82
+ <span class="cline-any cline-yes">30x</span>
83
+ <span class="cline-any cline-yes">30x</span>
84
84
  <span class="cline-any cline-yes">1x</span>
85
85
  <span class="cline-any cline-yes">1x</span>
86
86
  <span class="cline-any cline-yes">1x</span>
@@ -94,7 +94,7 @@
94
94
  this.#client = client;
95
95
  }
96
96
  &nbsp;
97
- <span class="fstat-no" title="function not covered" > get(id = null) { return id ? this.#client.get(`/user-types/${id}`) : this.#client.get('/user-types'); }</span>
97
+ get(id = null) { return id<span class="branch-0 cbranch-no" title="branch not covered" > ? this.#client.get(`/user-types/${id}`) </span>: this.#client.get('/user-types'); }
98
98
  <span class="fstat-no" title="function not covered" > create(data) { return this.#client.put('/user-types', data); }</span>
99
99
  <span class="fstat-no" title="function not covered" > edit(id, data) { return this.#client.patch(`/user-types/${id}`, data); }</span>
100
100
  <span class="fstat-no" title="function not covered" > delete(id) { return this.#client.del(`/user-types/${id}`); }</span>
@@ -106,7 +106,7 @@
106
106
  <div class='footer quiet pad2 space-top1 center small'>
107
107
  Code coverage generated by
108
108
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
109
- at 2026-08-03T13:22:45.069Z
109
+ at 2026-08-09T19:41:47.271Z
110
110
  </div>
111
111
  <script src="../../../prettify.js"></script>
112
112
  <script>
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">45.08% </span>
26
+ <span class="strong">40.48% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>78/173</span>
28
+ <span class='fraction'>83/205</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
33
  <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>2/2</span>
35
+ <span class='fraction'>7/7</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">5.55% </span>
40
+ <span class="strong">13.88% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>2/36</span>
42
+ <span class='fraction'>5/36</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">45.08% </span>
47
+ <span class="strong">40.48% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>78/173</span>
49
+ <span class='fraction'>83/205</span>
50
50
  </div>
51
51
 
52
52
 
@@ -236,12 +236,44 @@
236
236
  <a name='L171'></a><a href='#L171'>171</a>
237
237
  <a name='L172'></a><a href='#L172'>172</a>
238
238
  <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
240
- <span class="cline-any cline-yes">1x</span>
241
- <span class="cline-any cline-yes">1x</span>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
242
272
  <span class="cline-any cline-yes">1x</span>
243
273
  <span class="cline-any cline-yes">1x</span>
244
274
  <span class="cline-any cline-yes">1x</span>
275
+ <span class="cline-any cline-yes">30x</span>
276
+ <span class="cline-any cline-yes">30x</span>
245
277
  <span class="cline-any cline-yes">1x</span>
246
278
  <span class="cline-any cline-yes">1x</span>
247
279
  <span class="cline-any cline-yes">1x</span>
@@ -288,6 +320,38 @@
288
320
  <span class="cline-any cline-yes">1x</span>
289
321
  <span class="cline-any cline-yes">1x</span>
290
322
  <span class="cline-any cline-yes">1x</span>
323
+ <span class="cline-any cline-no">&nbsp;</span>
324
+ <span class="cline-any cline-no">&nbsp;</span>
325
+ <span class="cline-any cline-no">&nbsp;</span>
326
+ <span class="cline-any cline-no">&nbsp;</span>
327
+ <span class="cline-any cline-no">&nbsp;</span>
328
+ <span class="cline-any cline-no">&nbsp;</span>
329
+ <span class="cline-any cline-no">&nbsp;</span>
330
+ <span class="cline-any cline-no">&nbsp;</span>
331
+ <span class="cline-any cline-no">&nbsp;</span>
332
+ <span class="cline-any cline-no">&nbsp;</span>
333
+ <span class="cline-any cline-no">&nbsp;</span>
334
+ <span class="cline-any cline-no">&nbsp;</span>
335
+ <span class="cline-any cline-no">&nbsp;</span>
336
+ <span class="cline-any cline-no">&nbsp;</span>
337
+ <span class="cline-any cline-no">&nbsp;</span>
338
+ <span class="cline-any cline-no">&nbsp;</span>
339
+ <span class="cline-any cline-no">&nbsp;</span>
340
+ <span class="cline-any cline-no">&nbsp;</span>
341
+ <span class="cline-any cline-yes">1x</span>
342
+ <span class="cline-any cline-yes">1x</span>
343
+ <span class="cline-any cline-yes">1x</span>
344
+ <span class="cline-any cline-no">&nbsp;</span>
345
+ <span class="cline-any cline-no">&nbsp;</span>
346
+ <span class="cline-any cline-no">&nbsp;</span>
347
+ <span class="cline-any cline-no">&nbsp;</span>
348
+ <span class="cline-any cline-no">&nbsp;</span>
349
+ <span class="cline-any cline-no">&nbsp;</span>
350
+ <span class="cline-any cline-no">&nbsp;</span>
351
+ <span class="cline-any cline-no">&nbsp;</span>
352
+ <span class="cline-any cline-no">&nbsp;</span>
353
+ <span class="cline-any cline-yes">1x</span>
354
+ <span class="cline-any cline-yes">1x</span>
291
355
  <span class="cline-any cline-yes">1x</span>
292
356
  <span class="cline-any cline-yes">1x</span>
293
357
  <span class="cline-any cline-yes">1x</span>
@@ -416,10 +480,10 @@
416
480
  this.#client = client;
417
481
  }
418
482
  &nbsp;
419
- <span class="fstat-no" title="function not covered" > get(id = null) { return id ? this.#client.get(`/users/${id}`) : this.#client.get('/users'); }</span>
483
+ get(id = null) { return id ? this.#client.get(`/users/${id}`) : this.#client.get('/users'); }
420
484
  <span class="fstat-no" title="function not covered" > getByUsername(username) { return this.#client.get(`/users/username/${username}`); }</span>
421
485
  <span class="fstat-no" title="function not covered" > findByUsername(username) { return this.#client.get(`/users/find/${username}`); }</span>
422
- <span class="fstat-no" title="function not covered" > cashReceivers() { return this.#client.get('/users/cash-receivers'); }</span>
486
+ cashReceivers() { return this.#client.get('/users/cash-receivers'); }
423
487
  /** Seller-type users, for the payment forms' Seller picker (checkout + admin payment create/edit). */
424
488
  <span class="fstat-no" title="function not covered" > sellers() { return this.#client.get('/users/sellers'); }</span>
425
489
  /** Employee-only: users assignable as a course owner (super-admins, education centers, organizations). */
@@ -431,7 +495,7 @@
431
495
  <span class="cstat-no" title="statement not covered" > return this.#client.get('/users/teachers', { page, per_page: perPage });</span>
432
496
  <span class="cstat-no" title="statement not covered" > }</span>
433
497
  /** Employee-only: users eligible to own/reassign an organization (organization-and-above). */
434
- <span class="fstat-no" title="function not covered" > organizationOwners() { return this.#client.get('/users/organization-owners'); }</span>
498
+ organizationOwners() { return this.#client.get('/users/organization-owners'); }
435
499
  <span class="fstat-no" title="function not covered" > edit(id, data) { return this.#client.patch(`/users/${id}`, data); }</span>
436
500
  &nbsp;
437
501
  <span class="fstat-no" title="function not covered" > #nested(userId, path) {</span>
@@ -458,8 +522,40 @@
458
522
  <span class="cstat-no" title="statement not covered" > };</span>
459
523
  <span class="cstat-no" title="statement not covered" > }</span>
460
524
  <span class="fstat-no" title="function not covered" > courseNotes(userId) { return this.#nested(userId, 'course-notes'); }</span>
461
- <span class="fstat-no" title="function not covered" > quizzes(userId) { return this.#nested(userId, 'quizzes'); }</span>
462
- <span class="fstat-no" title="function not covered" > sessions(userId) { return this.#nested(userId, 'sessions'); }</span>
525
+ &nbsp;
526
+ /** get() accepts an optional { courseId } filter to narrow to a single course. */
527
+ <span class="fstat-no" title="function not covered" > quizzes(userId) {</span>
528
+ <span class="cstat-no" title="statement not covered" > const base = `/users/${userId}/quizzes`;</span>
529
+ <span class="cstat-no" title="statement not covered" > const client = this.#client;</span>
530
+ <span class="cstat-no" title="statement not covered" > return {</span>
531
+ <span class="cstat-no" title="statement not covered" > get: (id = null, { courseId } = {}) =&gt; id ? client.get(`${base}/${id}`) : client.get(courseId ? `${base}?course_id=${courseId}` : base),</span>
532
+ <span class="cstat-no" title="statement not covered" > create: (data) =&gt; client.put(base, data),</span>
533
+ <span class="cstat-no" title="statement not covered" > edit: (id, data) =&gt; client.patch(`${base}/${id}`, data),</span>
534
+ <span class="cstat-no" title="statement not covered" > delete: (id) =&gt; client.del(`${base}/${id}`),</span>
535
+ <span class="cstat-no" title="statement not covered" > /**</span>
536
+ <span class="cstat-no" title="statement not covered" > * Upload the file a student attaches as their answer to a</span>
537
+ <span class="cstat-no" title="statement not covered" > * document_upload (PDF) or audio_answer (recording) question</span>
538
+ <span class="cstat-no" title="statement not covered" > * (formData must contain `file`) — the kind is derived server-side</span>
539
+ <span class="cstat-no" title="statement not covered" > * from the question's own flags. The server derives the storage</span>
540
+ <span class="cstat-no" title="statement not covered" > * path/filename — nothing else to pass.</span>
541
+ <span class="cstat-no" title="statement not covered" > */</span>
542
+ <span class="cstat-no" title="statement not covered" > uploadQuestionFile: (quizId, questionId, formData) =&gt;</span>
543
+ <span class="cstat-no" title="statement not covered" > client.upload(`${base}/${quizId}/questions/${questionId}/file`, formData),</span>
544
+ <span class="cstat-no" title="statement not covered" > };</span>
545
+ <span class="cstat-no" title="statement not covered" > }</span>
546
+ &nbsp;
547
+ /** get() accepts an optional { courseId } filter to narrow to a single course. */
548
+ <span class="fstat-no" title="function not covered" > sessions(userId) {</span>
549
+ <span class="cstat-no" title="statement not covered" > const base = `/users/${userId}/sessions`;</span>
550
+ <span class="cstat-no" title="statement not covered" > const client = this.#client;</span>
551
+ <span class="cstat-no" title="statement not covered" > return {</span>
552
+ <span class="cstat-no" title="statement not covered" > get: (id = null, { courseId } = {}) =&gt; id ? client.get(`${base}/${id}`) : client.get(courseId ? `${base}?course_id=${courseId}` : base),</span>
553
+ <span class="cstat-no" title="statement not covered" > create: (data) =&gt; client.put(base, data),</span>
554
+ <span class="cstat-no" title="statement not covered" > edit: (id, data) =&gt; client.patch(`${base}/${id}`, data),</span>
555
+ <span class="cstat-no" title="statement not covered" > delete: (id) =&gt; client.del(`${base}/${id}`),</span>
556
+ <span class="cstat-no" title="statement not covered" > };</span>
557
+ <span class="cstat-no" title="statement not covered" > }</span>
558
+ &nbsp;
463
559
  <span class="fstat-no" title="function not covered" > surveys(userId) { return this.#nested(userId, 'surveys'); }</span>
464
560
  <span class="fstat-no" title="function not covered" > cart(userId) { return this.#nested(userId, 'cart'); }</span>
465
561
  &nbsp;
@@ -589,7 +685,7 @@
589
685
  <div class='footer quiet pad2 space-top1 center small'>
590
686
  Code coverage generated by
591
687
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
592
- at 2026-08-03T13:22:45.069Z
688
+ at 2026-08-09T19:41:47.271Z
593
689
  </div>
594
690
  <script src="../../../prettify.js"></script>
595
691
  <script>
@@ -89,8 +89,8 @@
89
89
  <span class="cline-any cline-yes">1x</span>
90
90
  <span class="cline-any cline-yes">1x</span>
91
91
  <span class="cline-any cline-yes">1x</span>
92
- <span class="cline-any cline-yes">1x</span>
93
- <span class="cline-any cline-yes">1x</span>
92
+ <span class="cline-any cline-yes">30x</span>
93
+ <span class="cline-any cline-yes">30x</span>
94
94
  <span class="cline-any cline-yes">1x</span>
95
95
  <span class="cline-any cline-yes">1x</span>
96
96
  <span class="cline-any cline-yes">1x</span>
@@ -136,7 +136,7 @@
136
136
  <div class='footer quiet pad2 space-top1 center small'>
137
137
  Code coverage generated by
138
138
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
139
- at 2026-08-03T13:22:45.069Z
139
+ at 2026-08-09T19:41:47.271Z
140
140
  </div>
141
141
  <script src="../../../prettify.js"></script>
142
142
  <script>
@@ -111,8 +111,8 @@
111
111
  <span class="cline-any cline-yes">1x</span>
112
112
  <span class="cline-any cline-yes">1x</span>
113
113
  <span class="cline-any cline-yes">1x</span>
114
- <span class="cline-any cline-yes">1x</span>
115
- <span class="cline-any cline-yes">1x</span>
114
+ <span class="cline-any cline-yes">30x</span>
115
+ <span class="cline-any cline-yes">30x</span>
116
116
  <span class="cline-any cline-yes">1x</span>
117
117
  <span class="cline-any cline-yes">1x</span>
118
118
  <span class="cline-any cline-yes">1x</span>
@@ -175,7 +175,7 @@ export default class Webauthn {
175
175
  <div class='footer quiet pad2 space-top1 center small'>
176
176
  Code coverage generated by
177
177
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
178
- at 2026-08-03T13:22:45.069Z
178
+ at 2026-08-09T19:41:47.271Z
179
179
  </div>
180
180
  <script src="../../../prettify.js"></script>
181
181
  <script>