@youversion/platform-core 0.5.0 → 0.5.5

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.
@@ -120,33 +120,30 @@ describe('URLBuilder - Input Validation', () => {
120
120
  });
121
121
 
122
122
  it('should include required permissions when provided', () => {
123
- const permissions = new Set<SignInWithYouVersionPermissionValues>([
124
- 'plans.read',
125
- 'user.read',
126
- ]);
123
+ const permissions = new Set<SignInWithYouVersionPermissionValues>(['bibles', 'votd']);
127
124
  const url = URLBuilder.authURL('test-app', permissions);
128
125
 
129
126
  const requiredPerms = url.searchParams.get('required_perms');
130
127
  expect(requiredPerms).toBeTruthy();
131
- expect(requiredPerms?.split(',')).toContain('plans.read');
132
- expect(requiredPerms?.split(',')).toContain('user.read');
128
+ expect(requiredPerms?.split(',')).toContain('bibles');
129
+ expect(requiredPerms?.split(',')).toContain('votd');
133
130
  });
134
131
 
135
132
  it('should include optional permissions when provided', () => {
136
- const optionalPermissions = new Set<SignInWithYouVersionPermissionValues>(['moments.read']);
133
+ const optionalPermissions = new Set<SignInWithYouVersionPermissionValues>(['demographics']);
137
134
  const url = URLBuilder.authURL('test-app', new Set(), optionalPermissions);
138
135
 
139
136
  const optPerms = url.searchParams.get('opt_perms');
140
- expect(optPerms).toBe('moments.read');
137
+ expect(optPerms).toBe('demographics');
141
138
  });
142
139
 
143
140
  it('should include both required and optional permissions', () => {
144
- const required = new Set<SignInWithYouVersionPermissionValues>(['user.read']);
145
- const optional = new Set<SignInWithYouVersionPermissionValues>(['plans.read']);
141
+ const required = new Set<SignInWithYouVersionPermissionValues>(['bibles']);
142
+ const optional = new Set<SignInWithYouVersionPermissionValues>(['bible_activity']);
146
143
  const url = URLBuilder.authURL('test-app', required, optional);
147
144
 
148
- expect(url.searchParams.get('required_perms')).toBe('user.read');
149
- expect(url.searchParams.get('opt_perms')).toBe('plans.read');
145
+ expect(url.searchParams.get('required_perms')).toBe('bibles');
146
+ expect(url.searchParams.get('opt_perms')).toBe('bible_activity');
150
147
  });
151
148
 
152
149
  it('should handle empty permission sets', () => {
@@ -38,7 +38,7 @@ describe('AuthClient', () => {
38
38
  headers: {
39
39
  get: vi.fn((name: string) => (name === 'content-type' ? 'application/json' : null)),
40
40
  },
41
- } as Response);
41
+ } as unknown as Response);
42
42
 
43
43
  const user = await authClient.getUser('test-token');
44
44
 
@@ -58,14 +58,23 @@ describe('WebAuthenticationStrategy', () => {
58
58
  beforeEach(() => {
59
59
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
60
60
  delete (window as any).location;
61
- window.location = {
62
- ...oldWindowLocation,
63
- href: 'http://localhost:3000',
64
- origin: 'http://localhost:3000',
65
- pathname: '/',
66
- assign: vi.fn(),
67
- replace: vi.fn(),
68
- } as Location;
61
+ const newLocation = new URL('http://localhost:3000');
62
+ // Add mocked functions with proper descriptors
63
+ Object.defineProperty(newLocation, 'assign', {
64
+ configurable: true,
65
+ value: vi.fn(),
66
+ });
67
+
68
+ Object.defineProperty(newLocation, 'replace', {
69
+ configurable: true,
70
+ value: vi.fn(),
71
+ });
72
+
73
+ // Assign the new location object to window.location
74
+ Object.defineProperty(window, 'location', {
75
+ configurable: true,
76
+ value: newLocation,
77
+ });
69
78
 
70
79
  const sessionStorageMock = (() => {
71
80
  let store: Record<string, string> = {};
@@ -97,7 +106,10 @@ describe('WebAuthenticationStrategy', () => {
97
106
  });
98
107
 
99
108
  afterEach(() => {
100
- window.location = oldWindowLocation;
109
+ Object.defineProperty(window, 'location', {
110
+ configurable: true,
111
+ value: oldWindowLocation,
112
+ });
101
113
  WebAuthenticationStrategy.cleanup();
102
114
  vi.clearAllMocks();
103
115
  });
@@ -112,7 +124,7 @@ describe('WebAuthenticationStrategy', () => {
112
124
  // eslint-disable-next-line @typescript-eslint/unbound-method
113
125
  expect(sessionStorage.setItem).toHaveBeenCalledWith(
114
126
  'youversion-auth-return',
115
- 'http://localhost:3000',
127
+ 'http://localhost:3000/',
116
128
  );
117
129
  });
118
130
  });
@@ -1,6 +1,20 @@
1
1
  import { http, HttpResponse } from 'msw';
2
2
  import type { Collection, Highlight, Language } from '../types';
3
3
  import { mockLanguages } from './MockLangauges';
4
+ import { mockVersions, mockVersionKJV } from './MockVersions';
5
+ import { mockBibleGenesis, mockBibleBooks } from './MockBibles';
6
+ import { mockChapterGenesis1, mockGenesisChapters } from './MockChapters';
7
+ import { mockGen1Verse1, mockGen1Verses } from './MockVerses';
8
+ import {
9
+ mockNIVGen1PassageHTML,
10
+ mockNIVGen1PassageText,
11
+ mockNIVGen1Verse1PassageHTML,
12
+ mockNIVGen1Verse1PassageText,
13
+ mockNIVRom1PassageHTMLHeadings,
14
+ mockNIVRom1PassageHTMLHeadingsNotes,
15
+ mockNIVRom1PassageHTMLNotes,
16
+ } from './MockPassages';
17
+ import { mockAllVOTDs } from './MockVOTDs';
4
18
 
5
19
  const apiHost = process.env.YVP_API_HOST;
6
20
  if (!apiHost) {
@@ -90,4 +104,88 @@ export const handlers = [
90
104
  http.delete(`https://${apiHost}/v1/highlights/:passageId`, () => {
91
105
  return new HttpResponse(null, { status: 204 });
92
106
  }),
107
+
108
+ // Versions endpoints
109
+ http.get(`https://${apiHost}/v1/bibles`, () => {
110
+ return HttpResponse.json({
111
+ data: mockVersions,
112
+ next_page_token: null,
113
+ total_size: 14,
114
+ });
115
+ }),
116
+
117
+ http.get(`https://${apiHost}/v1/bibles/:id`, () => {
118
+ return HttpResponse.json(mockVersionKJV);
119
+ }),
120
+
121
+ // Bible endpoints
122
+ http.get(`https://${apiHost}/v1/bibles/:id/books`, () => {
123
+ return HttpResponse.json({ data: mockBibleBooks });
124
+ }),
125
+
126
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/books/:book_id`, () => {
127
+ return HttpResponse.json(mockBibleGenesis);
128
+ }),
129
+
130
+ // Chaper endpoints
131
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/books/:book_id/chapters`, () => {
132
+ return HttpResponse.json({ data: mockGenesisChapters });
133
+ }),
134
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/books/:book_id/chapters/:chapter_id`, () => {
135
+ return HttpResponse.json(mockChapterGenesis1);
136
+ }),
137
+
138
+ // Verse endpoints
139
+ http.get(
140
+ `https://${apiHost}/v1/bibles/:bible_id/books/:book_id/chapters/:chapter_id/verses`,
141
+ () => {
142
+ return HttpResponse.json({ data: mockGen1Verses });
143
+ },
144
+ ),
145
+ http.get(
146
+ `https://${apiHost}/v1/bibles/:bible_id/books/:book_id/chapters/:chapter_id/verses/:verse_id`,
147
+ () => {
148
+ return HttpResponse.json(mockGen1Verse1);
149
+ },
150
+ ),
151
+
152
+ // Passage endpoints
153
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/passages/GEN.1`, ({ request }) => {
154
+ const url = new URL(request.url);
155
+ const format = url.searchParams.get('format');
156
+ if (format === 'html') {
157
+ return HttpResponse.json(mockNIVGen1PassageHTML);
158
+ }
159
+ return HttpResponse.json(mockNIVGen1PassageText);
160
+ }),
161
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/passages/GEN.1.1`, ({ request }) => {
162
+ const url = new URL(request.url);
163
+ const format = url.searchParams.get('format');
164
+ if (format === 'html') {
165
+ return HttpResponse.json(mockNIVGen1Verse1PassageHTML);
166
+ }
167
+ return HttpResponse.json(mockNIVGen1Verse1PassageText);
168
+ }),
169
+ http.get(`https://${apiHost}/v1/bibles/:bible_id/passages/ROM.1`, ({ request }) => {
170
+ const url = new URL(request.url);
171
+ const includeHeadings = url.searchParams.get('include_headings') === 'true';
172
+ const includeNotes = url.searchParams.get('include_notes') === 'true';
173
+ if (includeHeadings && !includeNotes) {
174
+ return HttpResponse.json(mockNIVRom1PassageHTMLHeadings);
175
+ } else if (!includeHeadings && includeNotes) {
176
+ return HttpResponse.json(mockNIVRom1PassageHTMLNotes);
177
+ } else if (includeNotes && includeHeadings) {
178
+ return HttpResponse.json(mockNIVRom1PassageHTMLHeadingsNotes);
179
+ }
180
+ }),
181
+
182
+ // Verse Of The Day endpoints
183
+ http.get(`https://${apiHost}/v1/verse_of_the_days/:day`, ({ params }) => {
184
+ const { day } = params;
185
+ const votd = mockAllVOTDs.find((v) => v.day === Number(day));
186
+ return HttpResponse.json(votd || mockAllVOTDs[0]);
187
+ }),
188
+ http.get(`https://${apiHost}/v1/verse_of_the_days`, () => {
189
+ return HttpResponse.json({ data: mockAllVOTDs });
190
+ }),
93
191
  ];
@@ -7,9 +7,9 @@ export const BibleVersionSchema = z.object({
7
7
  /** Bible version abbreviation */
8
8
  abbreviation: z.string(),
9
9
  /** Long copyright text */
10
- copyright_long: z.string(),
10
+ copyright_long: z.string().nullable().optional(),
11
11
  /** Short copyright text */
12
- copyright_short: z.string(),
12
+ copyright_short: z.string().nullable().optional(),
13
13
  /** Bible information text */
14
14
  info: z.string().nullable().optional(),
15
15
  /** Publisher URL */
@@ -20,6 +20,8 @@ export const BibleVersionSchema = z.object({
20
20
  local_abbreviation: z.string(),
21
21
  /** Localized title */
22
22
  local_title: z.string(),
23
+ /** Organization ID of publisher */
24
+ organization_id: z.string().nullable().optional(),
23
25
  /** Full title */
24
26
  title: z.string(),
25
27
  /** Array of book identifiers (e.g., ["GEN", "EXO", "LEV"]) */