musora-content-services 1.0.105 → 1.0.108
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.
- package/.github/workflows/node.js.yml +0 -0
- package/CHANGELOG.md +6 -0
- package/README.md +0 -0
- package/babel.config.js +0 -0
- package/docs/config.js.html +2 -2
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/index.html +2 -2
- package/docs/module-Config.html +2 -2
- package/docs/module-Railcontent-Services.html +2 -2
- package/docs/module-Sanity-Services.html +393 -42
- package/docs/railcontent.js.html +2 -2
- package/docs/sanity.js.html +307 -86
- package/docs/scripts/collapse.js +0 -0
- package/docs/scripts/commonNav.js +0 -0
- package/docs/scripts/linenumber.js +0 -0
- package/docs/scripts/nav.js +0 -0
- package/docs/scripts/polyfill.js +0 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
- package/docs/scripts/prettify/lang-css.js +0 -0
- package/docs/scripts/prettify/prettify.js +0 -0
- package/docs/scripts/search.js +0 -0
- package/docs/styles/jsdoc.css +0 -0
- package/docs/styles/prettify.css +0 -0
- package/jest.config.js +0 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +1331 -12
- package/src/filterBuilder.js +122 -0
- package/src/index.d.ts +0 -0
- package/src/index.js +0 -0
- package/src/services/config.js +0 -0
- package/src/services/railcontent.js +0 -0
- package/src/services/sanity.js +267 -87
- package/src/services/userContext.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/sanityQueryService.test.js +222 -17
- package/test/userContext.test.js +0 -0
|
@@ -9,33 +9,36 @@ const {
|
|
|
9
9
|
fetchAllSongs,
|
|
10
10
|
fetchSongFilterOptions,
|
|
11
11
|
fetchSongCount,
|
|
12
|
-
fetchWorkouts,
|
|
13
12
|
fetchNewReleases,
|
|
14
13
|
fetchUpcomingEvents,
|
|
15
14
|
fetchByRailContentId,
|
|
16
15
|
fetchByRailContentIds,
|
|
17
16
|
fetchAll,
|
|
18
17
|
fetchAllFilterOptions,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
fetchFoundation,
|
|
19
|
+
fetchMethods,
|
|
20
|
+
fetchMethod,
|
|
22
21
|
fetchRelatedLessons,
|
|
22
|
+
fetchAllPacks,
|
|
23
23
|
fetchPackAll,
|
|
24
|
-
fetchPackChildren,
|
|
25
24
|
fetchLessonContent,
|
|
26
|
-
|
|
27
|
-
fetchParentByRailContentId,
|
|
25
|
+
fetchCourseOverview,
|
|
28
26
|
fetchChildren,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
fetchAllPacks,
|
|
33
|
-
fetchPacksAll,
|
|
27
|
+
fetchParentByRailContentId,
|
|
28
|
+
fetchLiveEvent,
|
|
29
|
+
fetchChallengeOverview,
|
|
34
30
|
fetchCoachLessons,
|
|
35
31
|
fetchByReference,
|
|
36
|
-
fetchScheduledReleases
|
|
32
|
+
fetchScheduledReleases,
|
|
33
|
+
getSortOrder,
|
|
34
|
+
fetchShowsData,
|
|
35
|
+
fetchMetadata
|
|
37
36
|
} = require('../src/services/sanity.js');
|
|
38
37
|
|
|
38
|
+
const {
|
|
39
|
+
FilterBuilder,
|
|
40
|
+
} = require('../src/filterBuilder.js');
|
|
41
|
+
|
|
39
42
|
describe('Sanity Queries', function () {
|
|
40
43
|
beforeEach(() => {
|
|
41
44
|
const config = {
|
|
@@ -73,7 +76,14 @@ describe('Sanity Queries', function () {
|
|
|
73
76
|
|
|
74
77
|
test('fetchByRailContentId', async () => {
|
|
75
78
|
const id = 380094;
|
|
76
|
-
const response = await fetchByRailContentId(id);
|
|
79
|
+
const response = await fetchByRailContentId(id, "song");
|
|
80
|
+
expect(response.id).toBe(id);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('fetchChallengeOverview', async () => {
|
|
84
|
+
const id = 402197;
|
|
85
|
+
const response = await fetchChallengeOverview(id);
|
|
86
|
+
expect(response.lessons).toBeDefined();
|
|
77
87
|
expect(response.id).toBe(id);
|
|
78
88
|
});
|
|
79
89
|
|
|
@@ -88,12 +98,36 @@ describe('Sanity Queries', function () {
|
|
|
88
98
|
|
|
89
99
|
});
|
|
90
100
|
|
|
101
|
+
test('fetchUpcomingEvents', async () => {
|
|
102
|
+
const response = await fetchUpcomingEvents('drumeo', {});
|
|
103
|
+
expect(response.length).toBeGreaterThan(0);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('fetchUpcomingNewReleases', async () => {
|
|
107
|
+
const response = await fetchNewReleases('drumeo');
|
|
108
|
+
expect(response.length).toBeGreaterThan(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
|
|
91
112
|
test('fetchLessonContent', async () => {
|
|
92
113
|
const id = 380094;
|
|
93
114
|
const response = await fetchLessonContent(id);
|
|
94
115
|
expect(response.id).toBe(id);
|
|
95
116
|
});
|
|
96
117
|
|
|
118
|
+
|
|
119
|
+
test('fetchCourseOverview', async () => {
|
|
120
|
+
const id = 310414;
|
|
121
|
+
const response = await fetchCourseOverview(id);
|
|
122
|
+
expect(response.id).toBe(id);
|
|
123
|
+
expect(response.type).toBe('course');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('fetchSongCount', async () => {
|
|
127
|
+
const response = await fetchSongCount('drumeo');
|
|
128
|
+
expect(response).toBeGreaterThan(1000);
|
|
129
|
+
});
|
|
130
|
+
|
|
97
131
|
test('fetchAllSongs', async () => {
|
|
98
132
|
const response = await fetchAllSongs('drumeo', {});
|
|
99
133
|
log(response);
|
|
@@ -102,6 +136,13 @@ describe('Sanity Queries', function () {
|
|
|
102
136
|
expect(response.entity[0].instrumentless).toBeDefined();
|
|
103
137
|
});
|
|
104
138
|
|
|
139
|
+
test('fetchSongFilterOptions', async () => {
|
|
140
|
+
const response = await fetchSongFilterOptions('drumeo', {});
|
|
141
|
+
log(response);
|
|
142
|
+
expect(response.genre).toBeDefined();
|
|
143
|
+
expect(response.difficulty).toBeDefined();
|
|
144
|
+
});
|
|
145
|
+
|
|
105
146
|
test('fetchAllSongsGroupByArtist', async () => {
|
|
106
147
|
const response = await fetchAllSongs('drumeo', {groupBy:"artist"});
|
|
107
148
|
expect(response.entity[0].lessons[0].soundslice).toBeDefined();
|
|
@@ -110,6 +151,12 @@ describe('Sanity Queries', function () {
|
|
|
110
151
|
}, 100000);
|
|
111
152
|
|
|
112
153
|
|
|
154
|
+
test('fetchNewReleases', async () => {
|
|
155
|
+
const response = await fetchNewReleases('drumeo');
|
|
156
|
+
log(response);
|
|
157
|
+
expect(response[0].id).toBeDefined();
|
|
158
|
+
});
|
|
159
|
+
|
|
113
160
|
test('fetchAllWorkouts', async () => {
|
|
114
161
|
const response = await fetchAll('drumeo', 'workout',{});
|
|
115
162
|
log(response);
|
|
@@ -159,10 +206,10 @@ describe('Sanity Queries', function () {
|
|
|
159
206
|
|
|
160
207
|
test('fetchRelatedLessons', async () => {
|
|
161
208
|
const id = 380094;
|
|
162
|
-
const document = await fetchByRailContentId(id);
|
|
209
|
+
const document = await fetchByRailContentId(id, 'song');
|
|
163
210
|
let artist = document.artist.name;
|
|
164
211
|
const response = await fetchRelatedLessons(id, 'singeo');
|
|
165
|
-
let relatedDoc = await fetchByRailContentId(response.related_lessons[0].id);
|
|
212
|
+
let relatedDoc = await fetchByRailContentId(response.related_lessons[0].id, 'song');
|
|
166
213
|
// match on artist or any genre
|
|
167
214
|
let isMatch = artist === relatedDoc.artist.name;
|
|
168
215
|
isMatch = isMatch || document.genre.some((genre) => {
|
|
@@ -274,7 +321,7 @@ describe('Sanity Queries', function () {
|
|
|
274
321
|
});
|
|
275
322
|
|
|
276
323
|
test('fetchCoachLessons', async () => {
|
|
277
|
-
const response = await fetchCoachLessons('drumeo',
|
|
324
|
+
const response = await fetchCoachLessons('drumeo',411493, {});
|
|
278
325
|
expect(response.entity.length).toBeGreaterThan(0);
|
|
279
326
|
});
|
|
280
327
|
|
|
@@ -310,4 +357,162 @@ describe('Sanity Queries', function () {
|
|
|
310
357
|
log(response);
|
|
311
358
|
expect(response.entity[0].web_url_path).toContain('/drumeo/coaches/');
|
|
312
359
|
});
|
|
360
|
+
|
|
361
|
+
test('fetchShowsData', async () => {
|
|
362
|
+
const response = await fetchShowsData('singeo');
|
|
363
|
+
log(response);
|
|
364
|
+
expect(response.length).toBeGreaterThan(0);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('fetchMetadata', async () => {
|
|
368
|
+
const response = await fetchMetadata('drumeo','song');
|
|
369
|
+
log(response);
|
|
370
|
+
expect(response.tabs.length).toBeGreaterThan(0);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe('Filter Builder', function () {
|
|
376
|
+
|
|
377
|
+
test('baseConstructor', async () => {
|
|
378
|
+
const filter = 'railcontent_id = 111'
|
|
379
|
+
let builder = new FilterBuilder(filter);
|
|
380
|
+
let finalFilter = builder.buildFilter(filter);
|
|
381
|
+
let clauses = spliceFilterForAnds(finalFilter);
|
|
382
|
+
expect(clauses[0].phrase).toBe(filter);
|
|
383
|
+
expect(clauses[1].field).toBe('published_on');
|
|
384
|
+
|
|
385
|
+
builder = new FilterBuilder();
|
|
386
|
+
finalFilter = builder.buildFilter(filter);
|
|
387
|
+
clauses = spliceFilterForAnds(finalFilter);
|
|
388
|
+
expect(clauses[0].field).toBe('published_on');
|
|
389
|
+
expect(clauses[0].operator).toBe('<=');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test('withOnlyFilterAvailableStatuses', async () => {
|
|
393
|
+
const filter = 'railcontent_id = 111'
|
|
394
|
+
const builder = FilterBuilder.withOnlyFilterAvailableStatuses(filter,['published', 'unlisted']);
|
|
395
|
+
const finalFilter = builder.buildFilter();
|
|
396
|
+
const clauses = spliceFilterForAnds(finalFilter);
|
|
397
|
+
expect(clauses[0].phrase).toBe(filter);
|
|
398
|
+
expect(clauses[1].field).toBe('status');
|
|
399
|
+
expect(clauses[1].operator).toBe('in');
|
|
400
|
+
// not sure I like this
|
|
401
|
+
expect(clauses[1].condition).toBe("['published','unlisted']");
|
|
402
|
+
expect(clauses[2].field).toBe('published_on');
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test('withContentStatusAndFutureScheduledContent', async () => {
|
|
406
|
+
const filter = 'railcontent_id = 111'
|
|
407
|
+
const builder = new FilterBuilder(filter,{
|
|
408
|
+
availableContentStatuses: ['published', 'unlisted', 'scheduled'],
|
|
409
|
+
getFutureScheduledContentsOnly: true});
|
|
410
|
+
const finalFilter = builder.buildFilter();
|
|
411
|
+
const clauses = spliceFilterForAnds(finalFilter);
|
|
412
|
+
expect(clauses[0].phrase).toBe(filter);
|
|
413
|
+
expect(clauses[1].field).toBe('(status'); // extra ( because it's a multi part filter
|
|
414
|
+
expect(clauses[1].operator).toBe('in');
|
|
415
|
+
// getFutureScheduledContentsOnly doesn't make a filter that's splicable, so we match on the more static string
|
|
416
|
+
const expected = "['published','unlisted'] || (status == 'scheduled' && published_on >=";
|
|
417
|
+
console.log(clauses[1].condition);
|
|
418
|
+
console.log(expected)
|
|
419
|
+
const isMatch = finalFilter.includes(expected);
|
|
420
|
+
expect(isMatch).toBeTruthy();
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test('withUserPermissions', async () => {
|
|
424
|
+
const filter = 'railcontent_id = 111'
|
|
425
|
+
const builder = new FilterBuilder(filter,
|
|
426
|
+
{ user: {
|
|
427
|
+
user: {},
|
|
428
|
+
permissions: [91, 92],
|
|
429
|
+
}});
|
|
430
|
+
const finalFilter = builder.buildFilter();
|
|
431
|
+
const expected = "references(*[_type == 'permission' && railcontent_id in [91,92]]._id)"
|
|
432
|
+
const isMatch = finalFilter.includes(expected);
|
|
433
|
+
expect(isMatch).toBeTruthy();
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
test('withUserPermissionsForPlusUser', async () => {
|
|
437
|
+
const filter = 'railcontent_id = 111'
|
|
438
|
+
const builder = new FilterBuilder(filter,
|
|
439
|
+
{
|
|
440
|
+
user: getPlusUser()
|
|
441
|
+
});
|
|
442
|
+
const finalFilter = builder.buildFilter();
|
|
443
|
+
const expected = "references(*[_type == 'permission' && railcontent_id in [91,92]]._id)"
|
|
444
|
+
const isMatch = finalFilter.includes(expected);
|
|
445
|
+
expect(isMatch).toBeTruthy();
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test('withPermissionBypass', async () => {
|
|
449
|
+
const filter = 'railcontent_id = 111'
|
|
450
|
+
const builder = new FilterBuilder(filter,
|
|
451
|
+
{
|
|
452
|
+
user: getPlusUser(),
|
|
453
|
+
bypassPermissions:true
|
|
454
|
+
});
|
|
455
|
+
const finalFilter = builder.buildFilter();
|
|
456
|
+
const expected = "references(*[_type == 'permission' && railcontent_id in [91,92]]._id)"
|
|
457
|
+
const isMatch = finalFilter.includes(expected);
|
|
458
|
+
expect(isMatch).toBeFalsy();
|
|
459
|
+
const clauses = spliceFilterForAnds(finalFilter);
|
|
460
|
+
expect(clauses[0].field).toBe('railcontent_id');
|
|
461
|
+
expect(clauses[1].field).toBe('published_on');
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
test('withPublishOnRestrictions', async () => {
|
|
466
|
+
// testing dates is a pain more frustration than I'm willing to deal with, so I'm just testing operators.
|
|
467
|
+
|
|
468
|
+
const filter = 'railcontent_id = 111'
|
|
469
|
+
let builder = new FilterBuilder(filter, {
|
|
470
|
+
user: {},
|
|
471
|
+
pullFutureContent: true,
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
let finalFilter = builder.buildFilter();
|
|
475
|
+
let clauses = spliceFilterForAnds(finalFilter);
|
|
476
|
+
expect(clauses[0].phrase).toBe(filter);
|
|
477
|
+
|
|
478
|
+
expect(clauses[1].field).toBe('published_on');
|
|
479
|
+
expect(clauses[1].operator).toBe('<=');
|
|
480
|
+
const restrictionDate = new Date(clauses[1].condition)
|
|
481
|
+
const now = new Date();
|
|
482
|
+
expect(now.getTime()).toBeLessThan(restrictionDate.getTime());
|
|
483
|
+
|
|
484
|
+
builder = new FilterBuilder(filter,
|
|
485
|
+
{
|
|
486
|
+
user: {},
|
|
487
|
+
getFutureContentOnly: true,
|
|
488
|
+
});
|
|
489
|
+
finalFilter = builder.buildFilter();
|
|
490
|
+
clauses = spliceFilterForAnds(finalFilter);
|
|
491
|
+
expect(clauses[0].phrase).toBe(filter);
|
|
492
|
+
expect(clauses[1].field).toBe('published_on');
|
|
493
|
+
expect(clauses[1].operator).toBe('>=');
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
function getPlusUser() {
|
|
497
|
+
return {
|
|
498
|
+
permissions: [91,92],
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function spliceFilterForAnds(filter) {
|
|
503
|
+
// this will not correctly split complex filters with && and || conditions.
|
|
504
|
+
let phrases = filter.split(' && ');
|
|
505
|
+
let clauses= [];
|
|
506
|
+
phrases.forEach((phrase) => {
|
|
507
|
+
let field = phrase.substring(0, phrase.indexOf(' '));
|
|
508
|
+
//if(field.charAt(0) === '(' ) field = field.substring(1);
|
|
509
|
+
const temp = phrase.substring(phrase.indexOf(' ') + 1);
|
|
510
|
+
const operator = temp.substring(0, temp.indexOf(' '));
|
|
511
|
+
let condition = temp.substring(temp.indexOf(' ') + 1);
|
|
512
|
+
//if(condition.charAt(condition.length) === ')') condition = condition.slice(-1);
|
|
513
|
+
clauses.push({phrase, field, operator, condition});
|
|
514
|
+
});
|
|
515
|
+
return clauses;
|
|
516
|
+
}
|
|
517
|
+
|
|
313
518
|
});
|
package/test/userContext.test.js
CHANGED
|
File without changes
|