musora-content-services 2.0.8 → 2.1.0
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/.prettierignore +0 -0
- package/.prettierrc +0 -0
- package/CHANGELOG.md +7 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- 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/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/package.json +1 -1
- package/src/contentTypeConfig.js +6 -0
- package/src/index.d.ts +9 -3
- package/src/index.js +9 -3
- package/src/services/contentLikes.js +0 -0
- package/src/services/railcontent.js +3 -3
- package/src/services/recommendations.js +2 -2
- package/src/services/sanity.js +76 -3
- package/test/initializeTests.js +2 -2
- package/test/live/contentProgressLive.test.js +0 -0
- package/test/live/railcontentLive.test.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/sanityQueryService.test.js +142 -102
|
File without changes
|
package/.prettierignore
CHANGED
|
File without changes
|
package/.prettierrc
CHANGED
|
File without changes
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [2.1.0](https://github.com/railroadmedia/musora-content-services/compare/v2.0.8...v2.1.0) (2025-03-26)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **BEH-326:** update routing for top/all comment endpoints ([#203](https://github.com/railroadmedia/musora-content-services/issues/203)) ([1f4807f](https://github.com/railroadmedia/musora-content-services/commit/1f4807fcef3cb7ce0b03202519b4ccb4fbd6232f))
|
|
11
|
+
|
|
5
12
|
### [2.0.8](https://github.com/railroadmedia/musora-content-services/compare/v2.0.7...v2.0.8) (2025-03-25)
|
|
6
13
|
|
|
7
14
|
### [2.0.7](https://github.com/railroadmedia/musora-content-services/compare/v2.0.6...v2.0.7) (2025-03-21)
|
package/README.md
CHANGED
|
File without changes
|
package/babel.config.cjs
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/scripts/collapse.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/scripts/nav.js
CHANGED
|
File without changes
|
package/docs/scripts/polyfill.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/scripts/search.js
CHANGED
|
File without changes
|
package/docs/styles/jsdoc.css
CHANGED
|
File without changes
|
package/docs/styles/prettify.css
CHANGED
|
File without changes
|
package/jest.config.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/src/contentTypeConfig.js
CHANGED
|
@@ -3,6 +3,12 @@ import {Tabs} from "./contentMetaData.js";
|
|
|
3
3
|
|
|
4
4
|
export const AWSUrl = 'https://s3.us-east-1.amazonaws.com/musora-web-platform'
|
|
5
5
|
export const CloudFrontURl = 'https://d3fzm1tzeyr5n3.cloudfront.net'
|
|
6
|
+
|
|
7
|
+
export const SONG_TYPES = ['song', 'play-along', 'jam-track', 'song-tutorial-children']
|
|
8
|
+
// Challenges are excluded for the moment as they're still in design flex
|
|
9
|
+
// Single hierarchy refers to only one element in the hierarchy has video lessons, not that they have a single parent
|
|
10
|
+
export const SINGLE_PARENT_TYPES = ['course-part', 'pack-bundle-lesson', 'song-tutorial-children']
|
|
11
|
+
|
|
6
12
|
export const DEFAULT_FIELDS = [
|
|
7
13
|
"'sanity_id' : _id",
|
|
8
14
|
"'id': railcontent_id",
|
package/src/index.d.ts
CHANGED
|
@@ -119,10 +119,10 @@ import {
|
|
|
119
119
|
} from './services/railcontent.js';
|
|
120
120
|
|
|
121
121
|
import {
|
|
122
|
+
fetchSimilarItems,
|
|
122
123
|
rankCategories,
|
|
123
124
|
rankItems,
|
|
124
|
-
recommendations
|
|
125
|
-
similarItems
|
|
125
|
+
recommendations
|
|
126
126
|
} from './services/recommendations.js';
|
|
127
127
|
|
|
128
128
|
import {
|
|
@@ -143,6 +143,7 @@ import {
|
|
|
143
143
|
fetchHierarchy,
|
|
144
144
|
fetchLeaving,
|
|
145
145
|
fetchLessonContent,
|
|
146
|
+
fetchLessonsFeaturingThisContent,
|
|
146
147
|
fetchLiveEvent,
|
|
147
148
|
fetchMetadata,
|
|
148
149
|
fetchMethod,
|
|
@@ -151,12 +152,14 @@ import {
|
|
|
151
152
|
fetchMethodPreviousNextLesson,
|
|
152
153
|
fetchNewReleases,
|
|
153
154
|
fetchNextPreviousLesson,
|
|
155
|
+
fetchOtherSongVersions,
|
|
154
156
|
fetchPackAll,
|
|
155
157
|
fetchPackData,
|
|
156
158
|
fetchParentForDownload,
|
|
157
159
|
fetchPlayAlongsCount,
|
|
158
160
|
fetchRecent,
|
|
159
161
|
fetchRelatedLessons,
|
|
162
|
+
fetchRelatedRecommendedContent,
|
|
160
163
|
fetchRelatedSongs,
|
|
161
164
|
fetchReturning,
|
|
162
165
|
fetchSanity,
|
|
@@ -236,6 +239,7 @@ declare module 'musora-content-services' {
|
|
|
236
239
|
fetchHierarchy,
|
|
237
240
|
fetchLeaving,
|
|
238
241
|
fetchLessonContent,
|
|
242
|
+
fetchLessonsFeaturingThisContent,
|
|
239
243
|
fetchLiveEvent,
|
|
240
244
|
fetchMetadata,
|
|
241
245
|
fetchMethod,
|
|
@@ -245,6 +249,7 @@ declare module 'musora-content-services' {
|
|
|
245
249
|
fetchNewReleases,
|
|
246
250
|
fetchNextContentDataForParent,
|
|
247
251
|
fetchNextPreviousLesson,
|
|
252
|
+
fetchOtherSongVersions,
|
|
248
253
|
fetchOwnedChallenges,
|
|
249
254
|
fetchPackAll,
|
|
250
255
|
fetchPackData,
|
|
@@ -256,12 +261,14 @@ declare module 'musora-content-services' {
|
|
|
256
261
|
fetchPlaylistItems,
|
|
257
262
|
fetchRecent,
|
|
258
263
|
fetchRelatedLessons,
|
|
264
|
+
fetchRelatedRecommendedContent,
|
|
259
265
|
fetchRelatedSongs,
|
|
260
266
|
fetchReturning,
|
|
261
267
|
fetchSanity,
|
|
262
268
|
fetchScheduledAndNewReleases,
|
|
263
269
|
fetchScheduledReleases,
|
|
264
270
|
fetchShowsData,
|
|
271
|
+
fetchSimilarItems,
|
|
265
272
|
fetchSongArtistCount,
|
|
266
273
|
fetchSongById,
|
|
267
274
|
fetchSongsInProgress,
|
|
@@ -328,7 +335,6 @@ declare module 'musora-content-services' {
|
|
|
328
335
|
reportPlaylist,
|
|
329
336
|
reset,
|
|
330
337
|
setStudentViewForUser,
|
|
331
|
-
similarItems,
|
|
332
338
|
unassignModeratorToComment,
|
|
333
339
|
unlikeComment,
|
|
334
340
|
unlikeContent,
|
package/src/index.js
CHANGED
|
@@ -119,10 +119,10 @@ import {
|
|
|
119
119
|
} from './services/railcontent.js';
|
|
120
120
|
|
|
121
121
|
import {
|
|
122
|
+
fetchSimilarItems,
|
|
122
123
|
rankCategories,
|
|
123
124
|
rankItems,
|
|
124
|
-
recommendations
|
|
125
|
-
similarItems
|
|
125
|
+
recommendations
|
|
126
126
|
} from './services/recommendations.js';
|
|
127
127
|
|
|
128
128
|
import {
|
|
@@ -143,6 +143,7 @@ import {
|
|
|
143
143
|
fetchHierarchy,
|
|
144
144
|
fetchLeaving,
|
|
145
145
|
fetchLessonContent,
|
|
146
|
+
fetchLessonsFeaturingThisContent,
|
|
146
147
|
fetchLiveEvent,
|
|
147
148
|
fetchMetadata,
|
|
148
149
|
fetchMethod,
|
|
@@ -151,12 +152,14 @@ import {
|
|
|
151
152
|
fetchMethodPreviousNextLesson,
|
|
152
153
|
fetchNewReleases,
|
|
153
154
|
fetchNextPreviousLesson,
|
|
155
|
+
fetchOtherSongVersions,
|
|
154
156
|
fetchPackAll,
|
|
155
157
|
fetchPackData,
|
|
156
158
|
fetchParentForDownload,
|
|
157
159
|
fetchPlayAlongsCount,
|
|
158
160
|
fetchRecent,
|
|
159
161
|
fetchRelatedLessons,
|
|
162
|
+
fetchRelatedRecommendedContent,
|
|
160
163
|
fetchRelatedSongs,
|
|
161
164
|
fetchReturning,
|
|
162
165
|
fetchSanity,
|
|
@@ -235,6 +238,7 @@ export {
|
|
|
235
238
|
fetchHierarchy,
|
|
236
239
|
fetchLeaving,
|
|
237
240
|
fetchLessonContent,
|
|
241
|
+
fetchLessonsFeaturingThisContent,
|
|
238
242
|
fetchLiveEvent,
|
|
239
243
|
fetchMetadata,
|
|
240
244
|
fetchMethod,
|
|
@@ -244,6 +248,7 @@ export {
|
|
|
244
248
|
fetchNewReleases,
|
|
245
249
|
fetchNextContentDataForParent,
|
|
246
250
|
fetchNextPreviousLesson,
|
|
251
|
+
fetchOtherSongVersions,
|
|
247
252
|
fetchOwnedChallenges,
|
|
248
253
|
fetchPackAll,
|
|
249
254
|
fetchPackData,
|
|
@@ -255,12 +260,14 @@ export {
|
|
|
255
260
|
fetchPlaylistItems,
|
|
256
261
|
fetchRecent,
|
|
257
262
|
fetchRelatedLessons,
|
|
263
|
+
fetchRelatedRecommendedContent,
|
|
258
264
|
fetchRelatedSongs,
|
|
259
265
|
fetchReturning,
|
|
260
266
|
fetchSanity,
|
|
261
267
|
fetchScheduledAndNewReleases,
|
|
262
268
|
fetchScheduledReleases,
|
|
263
269
|
fetchShowsData,
|
|
270
|
+
fetchSimilarItems,
|
|
264
271
|
fetchSongArtistCount,
|
|
265
272
|
fetchSongById,
|
|
266
273
|
fetchSongsInProgress,
|
|
@@ -326,7 +333,6 @@ export {
|
|
|
326
333
|
reportPlaylist,
|
|
327
334
|
reset,
|
|
328
335
|
setStudentViewForUser,
|
|
329
|
-
similarItems,
|
|
330
336
|
unassignModeratorToComment,
|
|
331
337
|
unlikeComment,
|
|
332
338
|
unlikeContent,
|
|
File without changes
|
|
@@ -1072,7 +1072,7 @@ export async function playback(playlistId) {
|
|
|
1072
1072
|
* Set a user's StudentView Flag
|
|
1073
1073
|
*
|
|
1074
1074
|
* @param {int|string} userId - id of the user (must be currently authenticated)
|
|
1075
|
-
* @param {bool} enable -
|
|
1075
|
+
* @param {bool} enable - truthy value to enable student view
|
|
1076
1076
|
* @returns {Promise<any|null>}
|
|
1077
1077
|
*/
|
|
1078
1078
|
export async function setStudentViewForUser(userId, enable) {
|
|
@@ -1088,7 +1088,7 @@ export async function setStudentViewForUser(userId, enable) {
|
|
|
1088
1088
|
* @returns {Promise<Object|null>} - A promise that resolves to an comment object
|
|
1089
1089
|
*/
|
|
1090
1090
|
export async function fetchTopComment(railcontentId) {
|
|
1091
|
-
const url = `/api/content/v1
|
|
1091
|
+
const url = `/api/content/v1/${railcontentId}/comments?filter=top`
|
|
1092
1092
|
return await fetchHandler(url)
|
|
1093
1093
|
}
|
|
1094
1094
|
|
|
@@ -1100,7 +1100,7 @@ export async function fetchTopComment(railcontentId) {
|
|
|
1100
1100
|
* @returns {Promise<*|null>}
|
|
1101
1101
|
*/
|
|
1102
1102
|
export async function fetchComments(railcontentId, page = 1, limit = 20) {
|
|
1103
|
-
const url = `/api/content/v1
|
|
1103
|
+
const url = `/api/content/v1/${railcontentId}/comments?page=${page}&limit=${limit}`
|
|
1104
1104
|
return await fetchHandler(url)
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
@@ -14,8 +14,8 @@ const excludeFromGeneratedIndex = []
|
|
|
14
14
|
/**
|
|
15
15
|
* Fetches similar content to the provided content id
|
|
16
16
|
*
|
|
17
|
-
* @param {brand} brand - brand of the content to filter
|
|
18
17
|
* @param {integer} content_id - The ID of the content to find similar items for
|
|
18
|
+
* @param {brand} brand - brand of the content to filter
|
|
19
19
|
* @param {integer} count - number of items to return
|
|
20
20
|
* @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first)
|
|
21
21
|
* @example
|
|
@@ -23,7 +23,7 @@ const excludeFromGeneratedIndex = []
|
|
|
23
23
|
* .then(status => console.log(status))
|
|
24
24
|
* .catch(error => console.error(error));
|
|
25
25
|
*/
|
|
26
|
-
export async function
|
|
26
|
+
export async function fetchSimilarItems(content_id, brand, count = 10) {
|
|
27
27
|
if (!content_id) {
|
|
28
28
|
return []
|
|
29
29
|
}
|
package/src/services/sanity.js
CHANGED
|
@@ -15,8 +15,9 @@ import {
|
|
|
15
15
|
getNewReleasesTypes,
|
|
16
16
|
coachLessonsTypes,
|
|
17
17
|
getChildFieldsForContentType,
|
|
18
|
+
SONG_TYPES
|
|
18
19
|
} from '../contentTypeConfig.js'
|
|
19
|
-
|
|
20
|
+
import { fetchSimilarItems } from './recommendations.js'
|
|
20
21
|
import { processMetadata, typeWithSortOrder } from '../contentMetaData.js'
|
|
21
22
|
|
|
22
23
|
import { globalConfig } from './config.js'
|
|
@@ -36,7 +37,7 @@ import { getAllCompleted, getAllStarted, getAllStartedOrCompleted } from './cont
|
|
|
36
37
|
*
|
|
37
38
|
* @type {string[]}
|
|
38
39
|
*/
|
|
39
|
-
const excludeFromGeneratedIndex = ['handleCustomFetchAll']
|
|
40
|
+
const excludeFromGeneratedIndex = ['handleCustomFetchAll', 'fetchRelatedByLicense']
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* Fetch a song by its document ID from Sanity.
|
|
@@ -1313,6 +1314,78 @@ export async function fetchLessonContent(railContentId) {
|
|
|
1313
1314
|
return fetchSanity(query, false, { customPostProcess: chapterProcess })
|
|
1314
1315
|
}
|
|
1315
1316
|
|
|
1317
|
+
/**
|
|
1318
|
+
*
|
|
1319
|
+
* @param railContentId
|
|
1320
|
+
* @param brand
|
|
1321
|
+
* @param count
|
|
1322
|
+
* @returns {Promise<Array<Object>|null>}
|
|
1323
|
+
*/
|
|
1324
|
+
export async function fetchRelatedRecommendedContent(railContentId, brand, count=10) {
|
|
1325
|
+
const recommendedItems = await fetchSimilarItems(railContentId, brand, count)
|
|
1326
|
+
return fetchByRailContentIds(recommendedItems)
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/**
|
|
1330
|
+
* Get song type (transcriptions, jam packs, play alongs, tutorial children) content documents that share content information with the provided railcontent document.
|
|
1331
|
+
* These are linked through content that shares a license with the provided railcontent document
|
|
1332
|
+
*
|
|
1333
|
+
* @param railcontentId
|
|
1334
|
+
* @param brand
|
|
1335
|
+
* @param count
|
|
1336
|
+
* @returns {Promise<*>}
|
|
1337
|
+
*/
|
|
1338
|
+
export async function fetchOtherSongVersions(railcontentId, brand, count=3){
|
|
1339
|
+
return fetchRelatedByLicense(railcontentId, brand, true, count)
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* Get non-song content documents that share content information with the provided railcontent document.
|
|
1344
|
+
* These are linked through content that shares a license with the provided railcontent document
|
|
1345
|
+
*
|
|
1346
|
+
* @param {integer} railcontentId
|
|
1347
|
+
* @param {string} brand
|
|
1348
|
+
* @param {integer:3} count
|
|
1349
|
+
* @returns {Promise<*>}
|
|
1350
|
+
*/
|
|
1351
|
+
export async function fetchLessonsFeaturingThisContent(railcontentId, brand, count=3){
|
|
1352
|
+
return fetchRelatedByLicense(railcontentId, brand, false, count)
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Get content documents that share license information with the provided railcontent id
|
|
1357
|
+
*
|
|
1358
|
+
* @param {integer} railcontentId
|
|
1359
|
+
* @param {string} brand
|
|
1360
|
+
* @param {boolean} onlyUseSongTypes - if true, only return the song type documents. If false, return everything except those
|
|
1361
|
+
* @param {integer:3} count
|
|
1362
|
+
* @returns {Promise<*[]>}
|
|
1363
|
+
*/
|
|
1364
|
+
async function fetchRelatedByLicense(railcontentId, brand, onlyUseSongTypes, count) {
|
|
1365
|
+
const typeCheck = `@->_type in [${arrayJoinWithQuotes(SONG_TYPES)}]`
|
|
1366
|
+
const typeCheckString = onlyUseSongTypes ? `${typeCheck}` : `!(${typeCheck})`
|
|
1367
|
+
const contentFromLicenseFilter =`_type == 'license' && references(^._id)].content[${typeCheckString} && @->railcontent_id != ${railcontentId}`
|
|
1368
|
+
let filterSongTypesWithSameLicense = await new FilterBuilder(
|
|
1369
|
+
contentFromLicenseFilter,
|
|
1370
|
+
{isChildrenFilter: true},
|
|
1371
|
+
).buildFilter()
|
|
1372
|
+
let queryFields = getFieldsForContentType()
|
|
1373
|
+
const baseParentQuery = `railcontent_id == ${railcontentId}`
|
|
1374
|
+
let parentQuery = await new FilterBuilder(baseParentQuery).buildFilter()
|
|
1375
|
+
|
|
1376
|
+
// queryFields = 'railcontent_id, title'
|
|
1377
|
+
// parentQuery = baseParentQuery
|
|
1378
|
+
// filterSongTypesWithSameLicense = contentFromLicenseFilter
|
|
1379
|
+
const query = `*[${parentQuery}]{
|
|
1380
|
+
_type, railcontent_id,
|
|
1381
|
+
"related_by_license" :
|
|
1382
|
+
*[${filterSongTypesWithSameLicense}]->{${queryFields}}|order(published_on desc, title asc)[0...${count}],
|
|
1383
|
+
}[0...1]`
|
|
1384
|
+
|
|
1385
|
+
const results = await fetchSanity(query, false)
|
|
1386
|
+
return results['related_by_license'] ?? [];
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1316
1389
|
/**
|
|
1317
1390
|
* Fetch related lessons for a specific lesson by RailContent ID and type.
|
|
1318
1391
|
* @param {string} railContentId - The RailContent ID of the current lesson.
|
|
@@ -2272,9 +2345,9 @@ export async function fetchScheduledAndNewReleases(
|
|
|
2272
2345
|
published_on,
|
|
2273
2346
|
"type": _type,
|
|
2274
2347
|
show_in_new_feed,
|
|
2275
|
-
web_url_path,
|
|
2276
2348
|
"permission_id": permission[]->railcontent_id
|
|
2277
2349
|
}`
|
|
2278
2350
|
|
|
2279
2351
|
return fetchSanity(query, true)
|
|
2280
2352
|
}
|
|
2353
|
+
|
package/test/initializeTests.js
CHANGED
|
@@ -5,7 +5,7 @@ const railContentModule = require('../src/services/railcontent.js')
|
|
|
5
5
|
let token = null
|
|
6
6
|
let userId = process.env.RAILCONTENT_USER_ID ?? null
|
|
7
7
|
|
|
8
|
-
export async function initializeTestService(useLive = false) {
|
|
8
|
+
export async function initializeTestService(useLive = false, isAdmin = false) {
|
|
9
9
|
if (useLive && !token && process.env.RAILCONTENT_BASE_URL) {
|
|
10
10
|
let data = await fetchLoginToken(
|
|
11
11
|
process.env.RAILCONTENT_EMAIL,
|
|
@@ -39,7 +39,7 @@ export async function initializeTestService(useLive = false) {
|
|
|
39
39
|
initializeService(config)
|
|
40
40
|
|
|
41
41
|
let mock = jest.spyOn(railContentModule, 'fetchUserPermissionsData')
|
|
42
|
-
let testData = { permissions: [78, 91, 92], isAdmin:
|
|
42
|
+
let testData = { permissions: [78, 91, 92], isAdmin: isAdmin }
|
|
43
43
|
mock.mockImplementation(() => testData)
|
|
44
44
|
}
|
|
45
45
|
|
|
File without changes
|
|
File without changes
|
package/test/localStorageMock.js
CHANGED
|
File without changes
|
package/test/log.js
CHANGED
|
File without changes
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { getFieldsForContentType} from '../src/contentTypeConfig'
|
|
1
|
+
import { getFieldsForContentType, SONG_TYPES } from '../src/contentTypeConfig'
|
|
2
|
+
|
|
2
3
|
const railContentModule = require('../src/services/railcontent.js')
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
fetchCommentModContentData,
|
|
6
|
-
fetchMethodPreviousNextLesson,
|
|
7
|
-
fetchSanity,
|
|
8
|
-
} from '../src/services/sanity'
|
|
9
5
|
import { log } from './log.js'
|
|
10
6
|
import { initializeTestService } from './initializeTests'
|
|
11
7
|
import { dataContext } from '../src/services/contentProgress'
|
|
12
|
-
import {fetchOwnedChallenges, getRecommendedForYou, globalConfig, recommendations} from '../src'
|
|
8
|
+
import { fetchOwnedChallenges, getRecommendedForYou, globalConfig, recommendations } from '../src'
|
|
9
|
+
import { fetchLessonsFeaturingThisContent } from '../src/services/sanity.js'
|
|
13
10
|
|
|
14
11
|
const {
|
|
15
12
|
fetchSongById,
|
|
@@ -42,13 +39,17 @@ const {
|
|
|
42
39
|
fetchNextPreviousLesson,
|
|
43
40
|
fetchHierarchy,
|
|
44
41
|
fetchTopLevelParentId,
|
|
42
|
+
fetchOtherSongVersions,
|
|
43
|
+
fetchCommentModContentData,
|
|
44
|
+
fetchMethodPreviousNextLesson,
|
|
45
|
+
fetchSanity,
|
|
45
46
|
} = require('../src/services/sanity.js')
|
|
46
47
|
|
|
47
48
|
const { FilterBuilder } = require('../src/filterBuilder.js')
|
|
48
49
|
|
|
49
50
|
const { processMetadata } = require('../src/contentMetaData.js')
|
|
50
51
|
|
|
51
|
-
describe('Sanity Queries', function
|
|
52
|
+
describe('Sanity Queries', function() {
|
|
52
53
|
beforeEach(() => {
|
|
53
54
|
initializeTestService()
|
|
54
55
|
})
|
|
@@ -62,21 +63,21 @@ describe('Sanity Queries', function () {
|
|
|
62
63
|
test('fetchReturning', async () => {
|
|
63
64
|
const brand = 'guitareo'
|
|
64
65
|
const page = 1
|
|
65
|
-
const response = await fetchReturning(brand, {pageNumber: 1})
|
|
66
|
+
const response = await fetchReturning(brand, { pageNumber: 1 })
|
|
66
67
|
expect(response).toBeDefined()
|
|
67
|
-
})
|
|
68
|
+
})
|
|
68
69
|
|
|
69
70
|
test('fetchLeaving', async () => {
|
|
70
71
|
const brand = 'guitareo'
|
|
71
|
-
const response = await fetchLeaving(brand, {pageNumber: 1})
|
|
72
|
+
const response = await fetchLeaving(brand, { pageNumber: 1 })
|
|
72
73
|
expect(response).toBeDefined()
|
|
73
|
-
})
|
|
74
|
+
})
|
|
74
75
|
|
|
75
76
|
test('fetchComingSoon', async () => {
|
|
76
77
|
const brand = 'guitareo'
|
|
77
|
-
const response = await fetchComingSoon(brand, {pageNumber: 2, contentPerPage: 20})
|
|
78
|
+
const response = await fetchComingSoon(brand, { pageNumber: 2, contentPerPage: 20 })
|
|
78
79
|
expect(response).toBeDefined()
|
|
79
|
-
})
|
|
80
|
+
})
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
test('fetchArtists', async () => {
|
|
@@ -154,9 +155,7 @@ describe('Sanity Queries', function () {
|
|
|
154
155
|
|
|
155
156
|
test('fetchAllSongsInProgress', async () => {
|
|
156
157
|
var mock = jest.spyOn(dataContext, 'fetchData')
|
|
157
|
-
var json = JSON.parse(
|
|
158
|
-
`{"version":1,"config":{"key":1,"enabled":1,"checkInterval":1,"refreshInterval":2},"data":{"412941":{"s":"started","p":6,"t":20,"u":1731108082}}}`
|
|
159
|
-
)
|
|
158
|
+
var json = JSON.parse(`{"version":1,"config":{"key":1,"enabled":1,"checkInterval":1,"refreshInterval":2},"data":{"412941":{"s":"started","p":6,"t":20,"u":1731108082}}}`)
|
|
160
159
|
mock.mockImplementation(() => json)
|
|
161
160
|
const response = await fetchAll('drumeo', 'song', { progress: 'in progress' })
|
|
162
161
|
expect(response.entity[0].id).toBe(412941)
|
|
@@ -262,8 +261,7 @@ describe('Sanity Queries', function () {
|
|
|
262
261
|
expect(response.entity[0].id).toBeDefined()
|
|
263
262
|
|
|
264
263
|
response = await fetchAll('drumeo', 'challenge', {
|
|
265
|
-
useDefaultFields: false,
|
|
266
|
-
customFields: ['garbage'],
|
|
264
|
+
useDefaultFields: false, customFields: ['garbage'],
|
|
267
265
|
})
|
|
268
266
|
log(response)
|
|
269
267
|
expect(response.entity[0].garbage).toBeDefined()
|
|
@@ -278,13 +276,11 @@ describe('Sanity Queries', function () {
|
|
|
278
276
|
let relatedDoc = await fetchByRailContentId(response.related_lessons[0].id, 'song')
|
|
279
277
|
// match on artist or any genre
|
|
280
278
|
let isMatch = artist === relatedDoc.artist.name
|
|
281
|
-
isMatch =
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return relatedDoc.genre.some((relatedGenre) => {
|
|
285
|
-
return genre._ref === relatedGenre._ref
|
|
286
|
-
})
|
|
279
|
+
isMatch = isMatch || document.genre.some((genre) => {
|
|
280
|
+
return relatedDoc.genre.some((relatedGenre) => {
|
|
281
|
+
return genre._ref === relatedGenre._ref
|
|
287
282
|
})
|
|
283
|
+
})
|
|
288
284
|
expect(isMatch).toBeTruthy()
|
|
289
285
|
})
|
|
290
286
|
|
|
@@ -347,16 +343,14 @@ describe('Sanity Queries', function () {
|
|
|
347
343
|
test('fetchAll-WithProgress', async () => {
|
|
348
344
|
const ids = [410213, 410215]
|
|
349
345
|
let response = await fetchAll('drumeo', 'song', {
|
|
350
|
-
sort: 'slug',
|
|
351
|
-
progressIds: ids,
|
|
346
|
+
sort: 'slug', progressIds: ids,
|
|
352
347
|
})
|
|
353
348
|
expect(response.entity.length).toBe(2)
|
|
354
349
|
expect((response.entity[0].id = 410215))
|
|
355
350
|
expect((response.entity[1].id = 410213))
|
|
356
351
|
// change the type and we expect no results
|
|
357
352
|
response = await fetchAll('drumeo', 'quick-tip', {
|
|
358
|
-
sort: 'slug',
|
|
359
|
-
progressIds: ids,
|
|
353
|
+
sort: 'slug', progressIds: ids,
|
|
360
354
|
})
|
|
361
355
|
expect(response.entity.length).toBe(0)
|
|
362
356
|
})
|
|
@@ -400,16 +394,7 @@ describe('Sanity Queries', function () {
|
|
|
400
394
|
expect(response.entity.length).toBeGreaterThan(0)
|
|
401
395
|
})
|
|
402
396
|
test('fetchCoachLessons-WithTypeFilters', async () => {
|
|
403
|
-
const response = await fetchAllFilterOptions(
|
|
404
|
-
'drumeo',
|
|
405
|
-
['type,course', 'type,live'],
|
|
406
|
-
'',
|
|
407
|
-
'',
|
|
408
|
-
'coach-lessons',
|
|
409
|
-
'',
|
|
410
|
-
[],
|
|
411
|
-
31880
|
|
412
|
-
)
|
|
397
|
+
const response = await fetchAllFilterOptions('drumeo', ['type,course', 'type,live'], '', '', 'coach-lessons', '', [], 31880)
|
|
413
398
|
log(response)
|
|
414
399
|
expect(response.meta.filterOptions.difficulty).toBeDefined()
|
|
415
400
|
expect(response.meta.filterOptions.type).toBeDefined()
|
|
@@ -422,18 +407,7 @@ describe('Sanity Queries', function () {
|
|
|
422
407
|
const coachId = 31880
|
|
423
408
|
const invalidContentType = 'course' // Not 'coach-lessons'
|
|
424
409
|
|
|
425
|
-
await expect(
|
|
426
|
-
fetchAllFilterOptions(
|
|
427
|
-
brand,
|
|
428
|
-
['type,course', 'type,live'],
|
|
429
|
-
'',
|
|
430
|
-
'',
|
|
431
|
-
invalidContentType,
|
|
432
|
-
'',
|
|
433
|
-
[],
|
|
434
|
-
coachId
|
|
435
|
-
)
|
|
436
|
-
).rejects.toThrow("Invalid contentType: 'course' for coachId. It must be 'coach-lessons'.")
|
|
410
|
+
await expect(fetchAllFilterOptions(brand, ['type,course', 'type,live'], '', '', invalidContentType, '', [], coachId)).rejects.toThrow(`Invalid contentType: 'course' for coachId. It must be 'coach-lessons'.`)
|
|
437
411
|
})
|
|
438
412
|
|
|
439
413
|
test('fetchCoachLessons-IncludedFields', async () => {
|
|
@@ -637,15 +611,13 @@ describe('Sanity Queries', function () {
|
|
|
637
611
|
let data = await fetchCommentModContentData([241251, 241252, 211153])
|
|
638
612
|
expect(data[241251].title).toBe('Setting Up Your Space')
|
|
639
613
|
expect(data[241251].type).toBe('learning-path-lesson')
|
|
640
|
-
expect(data[241251].url).toBe(
|
|
641
|
-
'/drumeo/method/drumeo-method/241247/getting-started-on-the-drums/241248/gear/241249/setting-up-your-space/241251'
|
|
642
|
-
)
|
|
614
|
+
expect(data[241251].url).toBe('/drumeo/method/drumeo-method/241247/getting-started-on-the-drums/241248/gear/241249/setting-up-your-space/241251')
|
|
643
615
|
expect(data[241251].parentTitle).toBe('Gear')
|
|
644
616
|
expect(data[241252].title).toBe('Setting Up Your Pedals & Throne')
|
|
645
617
|
})
|
|
646
618
|
})
|
|
647
619
|
|
|
648
|
-
describe('Filter Builder', function
|
|
620
|
+
describe('Filter Builder', function() {
|
|
649
621
|
beforeEach(() => {
|
|
650
622
|
initializeTestService()
|
|
651
623
|
})
|
|
@@ -670,26 +642,21 @@ describe('Filter Builder', function () {
|
|
|
670
642
|
|
|
671
643
|
test('withOnlyFilterAvailableStatuses', async () => {
|
|
672
644
|
const filter = 'railcontent_id = 111'
|
|
673
|
-
const builder = FilterBuilder.withOnlyFilterAvailableStatuses(
|
|
674
|
-
filter,
|
|
675
|
-
['published', 'unlisted'],
|
|
676
|
-
true
|
|
677
|
-
)
|
|
645
|
+
const builder = FilterBuilder.withOnlyFilterAvailableStatuses(filter, ['published', 'unlisted'], true)
|
|
678
646
|
const finalFilter = await builder.buildFilter()
|
|
679
647
|
const clauses = spliceFilterForAnds(finalFilter)
|
|
680
648
|
expect(clauses[0].phrase).toBe(filter)
|
|
681
649
|
expect(clauses[1].field).toBe('status')
|
|
682
650
|
expect(clauses[1].operator).toBe('in')
|
|
683
651
|
// not sure I like this
|
|
684
|
-
expect(clauses[1].condition).toBe(
|
|
652
|
+
expect(clauses[1].condition).toBe(`['published','unlisted']`)
|
|
685
653
|
expect(clauses[2].field).toBe('published_on')
|
|
686
654
|
})
|
|
687
655
|
|
|
688
656
|
test('withContentStatusAndFutureScheduledContent', async () => {
|
|
689
657
|
const filter = 'railcontent_id = 111'
|
|
690
658
|
const builder = new FilterBuilder(filter, {
|
|
691
|
-
availableContentStatuses: ['published', 'unlisted', 'scheduled'],
|
|
692
|
-
getFutureScheduledContentsOnly: true,
|
|
659
|
+
availableContentStatuses: ['published', 'unlisted', 'scheduled'], getFutureScheduledContentsOnly: true,
|
|
693
660
|
})
|
|
694
661
|
const finalFilter = await builder.buildFilter()
|
|
695
662
|
const clauses = spliceFilterForAnds(finalFilter)
|
|
@@ -697,8 +664,7 @@ describe('Filter Builder', function () {
|
|
|
697
664
|
expect(clauses[1].field).toBe('(status') // extra ( because it's a multi part filter
|
|
698
665
|
expect(clauses[1].operator).toBe('in')
|
|
699
666
|
// getFutureScheduledContentsOnly doesn't make a filter that's splicable, so we match on the more static string
|
|
700
|
-
const expected =
|
|
701
|
-
"['published','unlisted'] || (status == 'scheduled' && defined(published_on) && published_on >="
|
|
667
|
+
const expected = `['published','unlisted'] || (status == 'scheduled' && defined(published_on) && published_on >=`
|
|
702
668
|
const isMatch = finalFilter.includes(expected)
|
|
703
669
|
expect(isMatch).toBeTruthy()
|
|
704
670
|
})
|
|
@@ -707,7 +673,7 @@ describe('Filter Builder', function () {
|
|
|
707
673
|
const filter = 'railcontent_id = 111'
|
|
708
674
|
const builder = new FilterBuilder(filter)
|
|
709
675
|
const finalFilter = await builder.buildFilter()
|
|
710
|
-
const expected =
|
|
676
|
+
const expected = `references(*[_type == 'permission' && railcontent_id in [78,91,92]]._id)`
|
|
711
677
|
const isMatch = finalFilter.includes(expected)
|
|
712
678
|
expect(isMatch).toBeTruthy()
|
|
713
679
|
})
|
|
@@ -716,7 +682,7 @@ describe('Filter Builder', function () {
|
|
|
716
682
|
const filter = 'railcontent_id = 111'
|
|
717
683
|
const builder = new FilterBuilder(filter)
|
|
718
684
|
const finalFilter = await builder.buildFilter()
|
|
719
|
-
const expected =
|
|
685
|
+
const expected = `references(*[_type == 'permission' && railcontent_id in [78,91,92]]._id)`
|
|
720
686
|
const isMatch = finalFilter.includes(expected)
|
|
721
687
|
expect(isMatch).toBeTruthy()
|
|
722
688
|
})
|
|
@@ -724,11 +690,10 @@ describe('Filter Builder', function () {
|
|
|
724
690
|
test('withPermissionBypass', async () => {
|
|
725
691
|
const filter = 'railcontent_id = 111'
|
|
726
692
|
const builder = new FilterBuilder(filter, {
|
|
727
|
-
bypassPermissions: true,
|
|
728
|
-
pullFutureContent: false,
|
|
693
|
+
bypassPermissions: true, pullFutureContent: false,
|
|
729
694
|
})
|
|
730
695
|
const finalFilter = await builder.buildFilter()
|
|
731
|
-
const expected =
|
|
696
|
+
const expected = `references(*[_type == 'permission' && railcontent_id in [78,91,92]]._id)`
|
|
732
697
|
const isMatch = finalFilter.includes(expected)
|
|
733
698
|
expect(isMatch).toBeFalsy()
|
|
734
699
|
const clauses = spliceFilterForAnds(finalFilter)
|
|
@@ -742,8 +707,7 @@ describe('Filter Builder', function () {
|
|
|
742
707
|
|
|
743
708
|
const filter = 'railcontent_id = 111'
|
|
744
709
|
let builder = new FilterBuilder(filter, {
|
|
745
|
-
pullFutureContent: true,
|
|
746
|
-
bypassPermissions: true,
|
|
710
|
+
pullFutureContent: true, bypassPermissions: true,
|
|
747
711
|
})
|
|
748
712
|
|
|
749
713
|
let finalFilter = await builder.buildFilter()
|
|
@@ -755,8 +719,7 @@ describe('Filter Builder', function () {
|
|
|
755
719
|
expect(clauses[3].field).toBe('published_on')
|
|
756
720
|
|
|
757
721
|
builder = new FilterBuilder(filter, {
|
|
758
|
-
getFutureContentOnly: true,
|
|
759
|
-
bypassPermissions: true,
|
|
722
|
+
getFutureContentOnly: true, bypassPermissions: true,
|
|
760
723
|
})
|
|
761
724
|
finalFilter = await builder.buildFilter()
|
|
762
725
|
clauses = spliceFilterForAnds(finalFilter)
|
|
@@ -815,28 +778,13 @@ describe('Filter Builder', function () {
|
|
|
815
778
|
})
|
|
816
779
|
|
|
817
780
|
test('fetchAllFilterOptions-filter-selected', async () => {
|
|
818
|
-
let response = await fetchAllFilterOptions(
|
|
819
|
-
'drumeo',
|
|
820
|
-
[
|
|
821
|
-
'theory,notation',
|
|
822
|
-
'theory,time signatures',
|
|
823
|
-
'creativity,Grooves',
|
|
824
|
-
'creativity,Fills & Chops',
|
|
825
|
-
'difficulty,Beginner',
|
|
826
|
-
'difficulty,Intermediate',
|
|
827
|
-
'difficulty,Expert',
|
|
828
|
-
],
|
|
829
|
-
'',
|
|
830
|
-
'',
|
|
831
|
-
'course',
|
|
832
|
-
''
|
|
833
|
-
)
|
|
781
|
+
let response = await fetchAllFilterOptions('drumeo', ['theory,notation', 'theory,time signatures', 'creativity,Grooves', 'creativity,Fills & Chops', 'difficulty,Beginner', 'difficulty,Intermediate', 'difficulty,Expert'], '', '', 'course', '')
|
|
834
782
|
log(response)
|
|
835
783
|
expect(response.meta.filterOptions).toBeDefined()
|
|
836
784
|
})
|
|
837
785
|
})
|
|
838
786
|
|
|
839
|
-
describe('MetaData', function
|
|
787
|
+
describe('MetaData', function() {
|
|
840
788
|
test('customBrandTypeExists', async () => {
|
|
841
789
|
const metaData = processMetadata('guitareo', 'recording')
|
|
842
790
|
expect(metaData.type).toBe('recording')
|
|
@@ -871,7 +819,7 @@ describe('MetaData', function () {
|
|
|
871
819
|
})
|
|
872
820
|
})
|
|
873
821
|
|
|
874
|
-
describe('
|
|
822
|
+
describe('api.v1', function() {
|
|
875
823
|
beforeEach(() => {
|
|
876
824
|
initializeTestService()
|
|
877
825
|
})
|
|
@@ -892,19 +840,13 @@ describe('v2', function () {
|
|
|
892
840
|
})
|
|
893
841
|
|
|
894
842
|
test('fetchAllFilterOptionsLessons', async () => {
|
|
895
|
-
const response = await fetchAllFilterOptions(
|
|
896
|
-
'pianote',
|
|
897
|
-
[],null,null,'lessons'
|
|
898
|
-
)
|
|
843
|
+
const response = await fetchAllFilterOptions('pianote', [], null, null, 'lessons')
|
|
899
844
|
log(response)
|
|
900
845
|
expect(response.meta.filters).toBeDefined()
|
|
901
846
|
})
|
|
902
847
|
|
|
903
848
|
test('fetchAllFilterOptionsSongs', async () => {
|
|
904
|
-
const response = await fetchAllFilterOptions(
|
|
905
|
-
'pianote',
|
|
906
|
-
[],null,null,'songs'
|
|
907
|
-
)
|
|
849
|
+
const response = await fetchAllFilterOptions('pianote', [], null, null, 'songs')
|
|
908
850
|
log(response)
|
|
909
851
|
expect(response.meta.filters).toBeDefined()
|
|
910
852
|
})
|
|
@@ -914,9 +856,105 @@ describe('v2', function () {
|
|
|
914
856
|
log(liveEvent)
|
|
915
857
|
//expect(metaData).toBeNull()
|
|
916
858
|
})
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
test('fetchRelatedLessons-pack-bundle-lessons', async () => {
|
|
863
|
+
//https://www.musora.com/singeo/packs/sing-harmony-in-30-days/410537/sing-harmony-in-30-days/410538/day-2/410541
|
|
864
|
+
const railContentId = 410541
|
|
865
|
+
const relatedLessons = await fetchRelatedLessons(railContentId, 'singeo')
|
|
866
|
+
log(relatedLessons)
|
|
867
|
+
const expectedPath = ['', 'singeo', 'packs', 'sing-harmony-in-30-days', '410537', 'sing-harmony-in-30-days', '410538']
|
|
868
|
+
expect(relatedLessons['related_lessons'].length).toBeGreaterThanOrEqual(1)
|
|
869
|
+
relatedLessons['related_lessons'].forEach(document => {
|
|
870
|
+
expect('pack-bundle-lesson').toStrictEqual(document.type)
|
|
871
|
+
// there are other ways to check that these all have the same parent, but I don't want to write it
|
|
872
|
+
let web_url_path = document.web_url_path.split('/')
|
|
873
|
+
// remove id and slug
|
|
874
|
+
web_url_path.pop()
|
|
875
|
+
web_url_path.pop()
|
|
876
|
+
expect(web_url_path).toEqual(expectedPath)
|
|
877
|
+
})
|
|
878
|
+
})
|
|
879
|
+
|
|
880
|
+
test('fetchRelatedLessons-course-parts', async () => {
|
|
881
|
+
///drumeo/courses/ultra-compact-drum-set-gear-guide/295177/gigpig-standard-and-extendable/297929
|
|
882
|
+
const railContentId = 297929
|
|
883
|
+
const relatedLessons = await fetchRelatedLessons(railContentId, 'drumeo')
|
|
884
|
+
log(relatedLessons)
|
|
885
|
+
const expectedPath = ['', 'drumeo', 'courses', 'ultra-compact-drum-set-gear-guide', '295177']
|
|
886
|
+
expect(relatedLessons['related_lessons'].length).toBeGreaterThanOrEqual(1)
|
|
887
|
+
relatedLessons['related_lessons'].forEach(document => {
|
|
888
|
+
expect('course-part').toStrictEqual(document.type)
|
|
889
|
+
// there are other ways to check that these all have the same parent, but I don't want to write it
|
|
890
|
+
let web_url_path = document.web_url_path.split('/')
|
|
891
|
+
// remove id and slug
|
|
892
|
+
web_url_path.pop()
|
|
893
|
+
web_url_path.pop()
|
|
894
|
+
expect(web_url_path).toEqual(expectedPath)
|
|
895
|
+
})
|
|
896
|
+
})
|
|
897
|
+
})
|
|
898
|
+
|
|
899
|
+
describe('api.v1.admin', function() {
|
|
900
|
+
beforeEach(() => {
|
|
901
|
+
initializeTestService(false, true)
|
|
902
|
+
})
|
|
903
|
+
|
|
904
|
+
test('fetchOtherSongVersions', async () => {
|
|
905
|
+
// much of the licensed content is currently drafted, so this must be run in the admin test-suite
|
|
906
|
+
const railContentId = 386901
|
|
907
|
+
const licenseQuery = `*[railcontent_id == ${railContentId}]{
|
|
908
|
+
'content_ids': *[_type == 'license' && references(^._id)].content[]->railcontent_id
|
|
909
|
+
}[0]`
|
|
910
|
+
const otherReferencedContent = (await fetchSanity(licenseQuery, true))['content_ids']
|
|
911
|
+
log(otherReferencedContent)
|
|
912
|
+
const relatedSongsTypes = await fetchOtherSongVersions(railContentId, 'drumeo', 100)
|
|
913
|
+
log(relatedSongsTypes)
|
|
914
|
+
expect(relatedSongsTypes.length).toBeGreaterThanOrEqual(1)
|
|
915
|
+
relatedSongsTypes.forEach(document => {
|
|
916
|
+
expect(SONG_TYPES).toContain(document.type)
|
|
917
|
+
expect(document.id).not.toStrictEqual(railContentId)
|
|
918
|
+
expect(otherReferencedContent).toContain(document.id)
|
|
919
|
+
})
|
|
920
|
+
})
|
|
921
|
+
|
|
922
|
+
test('fetchLessonsFeaturingThisContent', async () => {
|
|
923
|
+
// much of the licensed content is currently drafted, so this must be run in the admin test-suite
|
|
924
|
+
const railContentId = 386901
|
|
925
|
+
const licenseQuery = `*[railcontent_id == ${railContentId}]{
|
|
926
|
+
'content_ids': *[_type == 'license' && references(^._id)].content[]->railcontent_id
|
|
927
|
+
}[0]`
|
|
928
|
+
const otherReferencedContent = (await fetchSanity(licenseQuery, true))['content_ids']
|
|
929
|
+
const relatedNotSongs = await fetchLessonsFeaturingThisContent(railContentId, 'drumeo', 100)
|
|
930
|
+
log(relatedNotSongs)
|
|
931
|
+
expect(relatedNotSongs.length).toBeGreaterThanOrEqual(1)
|
|
932
|
+
relatedNotSongs.forEach(document => {
|
|
933
|
+
expect(SONG_TYPES).not.toContain(document.type)
|
|
934
|
+
expect(document.id).not.toStrictEqual(railContentId)
|
|
935
|
+
expect(otherReferencedContent).toContain(document.id)
|
|
936
|
+
})
|
|
937
|
+
})
|
|
938
|
+
|
|
939
|
+
test('fetchRelatedLessons-song-tutorial-children', async () => {
|
|
940
|
+
// When I wrote this it didn't need admin, but something changed. Shrug
|
|
941
|
+
const railContentId = 222633
|
|
942
|
+
const relatedLessons = await fetchRelatedLessons(railContentId, 'pianote')
|
|
943
|
+
log(relatedLessons)
|
|
944
|
+
const expectedPath = ['', 'pianote', 'song-tutorials', 'hallelujah', '221831']
|
|
945
|
+
expect(relatedLessons['related_lessons'].length).toBeGreaterThanOrEqual(1)
|
|
946
|
+
relatedLessons['related_lessons'].forEach(document => {
|
|
947
|
+
expect('song-tutorial-children').toStrictEqual(document.type)
|
|
948
|
+
let web_url_path = document.web_url_path.split('/')
|
|
949
|
+
// remove id, slug
|
|
950
|
+
web_url_path.pop()
|
|
951
|
+
web_url_path.pop()
|
|
952
|
+
expect(web_url_path).toEqual(expectedPath)
|
|
953
|
+
})
|
|
954
|
+
})
|
|
917
955
|
})
|
|
918
956
|
|
|
919
|
-
describe('Recommended System', function
|
|
957
|
+
describe('Recommended System', function() {
|
|
920
958
|
beforeEach(() => {
|
|
921
959
|
initializeTestService()
|
|
922
960
|
})
|
|
@@ -931,7 +969,7 @@ describe('Recommended System', function () {
|
|
|
931
969
|
})
|
|
932
970
|
|
|
933
971
|
test('getRecommendedForYou-SeeAll', async () => {
|
|
934
|
-
const results = await getRecommendedForYou('drumeo', 'recommended', {page: 1, limit:20})
|
|
972
|
+
const results = await getRecommendedForYou('drumeo', 'recommended', { page: 1, limit: 20 })
|
|
935
973
|
log(results)
|
|
936
974
|
expect(results.type).toBeDefined()
|
|
937
975
|
expect(results.data).toBeDefined()
|
|
@@ -939,3 +977,5 @@ describe('Recommended System', function () {
|
|
|
939
977
|
expect(results.data.length).toBeGreaterThanOrEqual(1)
|
|
940
978
|
})
|
|
941
979
|
})
|
|
980
|
+
|
|
981
|
+
|