musora-content-services 2.160.3 → 2.160.4

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.
@@ -0,0 +1,23 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npx jest *)",
5
+ "Bash(npx tsc *)",
6
+ "Skill(counselors)",
7
+ "Bash(counselors ls *)",
8
+ "Bash(counselors groups *)",
9
+ "Bash(counselors run *)",
10
+ "Bash(npm test *)",
11
+ "Bash(gh pr *)",
12
+ "Bash(gh api *)",
13
+ "Bash(mkdir -p /tmp/pr-review-v2)",
14
+ "Read(//tmp/pr-review-v2/**)",
15
+ "Bash(cat /home/alesevero/railenvironment/applications/musora-content-services/AGENTS.md)",
16
+ "Bash(echo \"no AGENTS.md\")",
17
+ "Bash(echo \"exit=$?\")",
18
+ "Bash(git checkout *)",
19
+ "Skill(pr)",
20
+ "Skill(create-decision)"
21
+ ]
22
+ }
23
+ }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
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.160.4](https://github.com/railroadmedia/musora-content-services/compare/v2.160.3...v2.160.4) (2026-05-20)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **MU2-1510:** process need access for live events ([#964](https://github.com/railroadmedia/musora-content-services/issues/964)) ([66aa2b5](https://github.com/railroadmedia/musora-content-services/commit/66aa2b596b28c272b938672522b9c4024f9e328d))
11
+ * **MU2-1511:** add need access to upcoming live events ([#965](https://github.com/railroadmedia/musora-content-services/issues/965)) ([9366907](https://github.com/railroadmedia/musora-content-services/commit/936690752529d25d80df0192e80b57ad90921445))
12
+ * **MU2-1512:** add child data to new and upcoming ([#960](https://github.com/railroadmedia/musora-content-services/issues/960)) ([329f5c8](https://github.com/railroadmedia/musora-content-services/commit/329f5c8b98ea11f1d456dd53e81b705f55b4f346))
13
+
5
14
  ### [2.160.3](https://github.com/railroadmedia/musora-content-services/compare/v2.160.2...v2.160.3) (2026-05-14)
6
15
 
7
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.160.3",
3
+ "version": "2.160.4",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -698,6 +698,7 @@ export let contentTypeConfig = {
698
698
  'show_in_new_feed',
699
699
  isLiveField(),
700
700
  ],
701
+ includeChildFields: true,
701
702
  },
702
703
  }
703
704
 
@@ -404,7 +404,7 @@ export async function fetchUpcomingEvents(brand, { page = 1, limit = 10 } = {})
404
404
  end: end,
405
405
  },
406
406
  )
407
- return fetchSanity(query, true)
407
+ return fetchSanity(query, true, { processNeedAccess: true })
408
408
  }
409
409
 
410
410
  /**
@@ -1211,7 +1211,7 @@ export async function fetchLiveEvent(brand, forcedContentId = null) {
1211
1211
  // This query finds the first scheduled event (sorted by start_time) that ends after now()
1212
1212
  const query = `*[${filter}]{${fieldsString}} | order(live_event_start_time)[0...1]`
1213
1213
 
1214
- return await fetchSanity(query, false, { processNeedAccess: false })
1214
+ return await fetchSanity(query, false, { processNeedAccess: true })
1215
1215
  }
1216
1216
 
1217
1217
  /**
@@ -0,0 +1,116 @@
1
+ import { initializeTestService } from '../initializeTests.js'
2
+ import {getContentRows, getNewAndUpcoming, getScheduleContentRows, getTabResults} from '../../src/index.js'
3
+
4
+ // Mock fetchContentProgress before other modules load
5
+ jest.mock('../../src/services/railcontent.js', () => ({
6
+ ...jest.requireActual('../../src/services/railcontent.js'),
7
+ fetchContentProgress: jest.fn().mockResolvedValue({ version: 1, data: {} })
8
+ }))
9
+
10
+ const railContentModule = require('../../src/services/railcontent.js')
11
+
12
+ describe('content', function () {
13
+ beforeAll(async () => {
14
+ await initializeTestService(true)
15
+ })
16
+
17
+ test('getTabResults-Singles', async () => {
18
+ const results = await getTabResults('drumeo','lessons','Individuals', {selectedFilters:['difficulty,All','difficulty,Beginner'], sort:'-published_on'})
19
+ console.log(results)
20
+ expect(results.type).toBeDefined()
21
+ expect(results.type).toBe('catalog')
22
+ expect(results.data).toBeDefined()
23
+ expect(results.meta).toBeDefined()
24
+ expect(results.meta.filters).toBeDefined()
25
+ expect(results.meta.sort).toBeDefined()
26
+ })
27
+
28
+ test('getTabResults-Courses', async () => {
29
+ const results = await getTabResults('pianote','lessons','Collections', {selectedFilters:['difficulty,Expert'], sort:'slug'})
30
+ console.log(results)
31
+ expect(results.type).toBeDefined()
32
+ expect(results.type).toBe('catalog')
33
+ expect(results.data).toBeDefined()
34
+ expect(results.meta).toBeDefined()
35
+ expect(results.meta.filters).toBeDefined()
36
+ expect(results.meta.sort).toBeDefined()
37
+ })
38
+
39
+ test('getTabResults-Filters', async () => {
40
+ const results = await getTabResults('pianote','lessons','Explore All', {selectedFilters:['difficulty,Expert'], sort:'slug'})
41
+ console.log(results)
42
+ expect(results.type).toBeDefined()
43
+ expect(results.data).toBeDefined()
44
+ expect(results.meta).toBeDefined()
45
+ expect(results.meta.filters).toBeDefined()
46
+ expect(results.meta.sort).toBeDefined()
47
+ })
48
+
49
+ test('getTabResults-Type-Filter', async () => {
50
+ const results = await getTabResults('drumeo','lessons','Explore All', {selectedFilters:['type,Courses', 'type,Documentaries'], sort:'slug'})
51
+ console.log(results)
52
+ expect(results.type).toBeDefined()
53
+ expect(results.data).toBeDefined()
54
+ expect(results.meta).toBeDefined()
55
+ expect(results.meta.filters).toBeDefined()
56
+ expect(results.meta.sort).toBeDefined()
57
+ })
58
+
59
+ test('getTabResults-Type-Explore-All', async () => {
60
+ const results = await getTabResults('drumeo','lessons','Explore All', {selectedFilters:[], sort:'slug'})
61
+ console.log(results)
62
+ expect(results.type).toBeDefined()
63
+ expect(results.data).toBeDefined()
64
+ expect(results.meta).toBeDefined()
65
+ expect(results.meta.filters).toBeDefined()
66
+ expect(results.meta.sort).toBeDefined()
67
+ })
68
+
69
+ test('getContentRows', async () => {
70
+ const results = await getContentRows('drumeo', 'lessons', 'Your-Daily-Warmup')
71
+ console.log(results)
72
+ })
73
+
74
+ // test('getTabResults-Songs-For-You', async () => {
75
+ // const results = await getTabResults('drumeo','songs','For You')
76
+ // console.log(results)
77
+ // expect(results.type).toBeDefined()
78
+ // expect(results.type).toBe('sections')
79
+ // expect(results.data).toBeDefined()
80
+ // expect(results.meta).toBeDefined()
81
+ // expect(results.meta.filters).toBeDefined()
82
+ // expect(results.meta.sort).toBeDefined()
83
+ // })
84
+ test('getNewAndUpcoming', async () => {
85
+ const results = await getNewAndUpcoming('drumeo')
86
+ expect(results).not.toBeNull()
87
+ expect(Array.isArray(results.data)).toBe(true)
88
+
89
+ const childAwareParentTypes = ['course', 'song-tutorial', 'skill-pack']
90
+ const parentItems = results.data.filter((item) => childAwareParentTypes.includes(item.type))
91
+
92
+ parentItems.forEach((item) => {
93
+ expect(item.navigateTo).not.toBeNull()
94
+ expect(item.navigateTo.child).not.toBeNull()
95
+ expect(typeof item.navigateTo.child.id).toBe('number')
96
+ })
97
+ })
98
+
99
+ test('getScheduleContentRows', async () => {
100
+ const results = await getScheduleContentRows('drumeo')
101
+ console.log(results.data[1])
102
+ expect(results.type).toBeDefined()
103
+ expect(results.type).toBe('sections')
104
+ expect(results.data).toBeDefined()
105
+ expect(results.meta).toBeDefined()
106
+ })
107
+
108
+ test('getSpecificScheduleContentRow', async () => {
109
+ const results = await getScheduleContentRows('drumeo', 'Leaving-Soon')
110
+ console.log(results)
111
+ expect(results.type).toBeDefined()
112
+ expect(results.type).toBe('catalog')
113
+ expect(results.data).toBeDefined()
114
+ expect(results.meta).toBeDefined()
115
+ })
116
+ })
@@ -2,6 +2,7 @@ import { initializeTestService } from '../initializeTests.js'
2
2
  import { getSortOrder } from '../../src/services/sanity.js'
3
3
  import { processMetadata } from '../../src/contentMetaData.js'
4
4
  import { FilterBuilder } from '../../src/filterBuilder.js'
5
+ import { getFieldsForContentTypeWithFilteredChildren } from '../../src/contentTypeConfig.js'
5
6
 
6
7
  jest.mock('../../src/services/permissions/index.ts', () => ({
7
8
  ...jest.requireActual('../../src/services/permissions/index.ts'),
@@ -186,4 +187,14 @@ describe('Sanity Queries', function() {
186
187
  const metaData = processMetadata('guitareo', 'not a real type')
187
188
  expect(metaData).toBeNull()
188
189
  })
190
+
191
+ test('newAndScheduledProjectionIncludesChildren', async () => {
192
+ const projection = await getFieldsForContentTypeWithFilteredChildren('new-and-scheduled')
193
+ expect(projection).toContain('"children": child[')
194
+ })
195
+
196
+ test('newAndScheduledProjectionIncludesParentFields', async () => {
197
+ const projection = await getFieldsForContentTypeWithFilteredChildren('new-and-scheduled')
198
+ expect(projection).toContain('show_in_new_feed')
199
+ })
189
200
  })