@youversion/platform-react-hooks 1.18.1 → 1.20.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.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +3 -7
  3. package/CHANGELOG.md +32 -0
  4. package/dist/__tests__/mocks/bibles.d.ts +6 -1
  5. package/dist/__tests__/mocks/bibles.d.ts.map +1 -1
  6. package/dist/__tests__/mocks/bibles.js +10 -0
  7. package/dist/__tests__/mocks/bibles.js.map +1 -1
  8. package/dist/__tests__/mocks/core-mock-factory.d.ts +83 -0
  9. package/dist/__tests__/mocks/core-mock-factory.d.ts.map +1 -0
  10. package/dist/__tests__/mocks/core-mock-factory.js +138 -0
  11. package/dist/__tests__/mocks/core-mock-factory.js.map +1 -0
  12. package/dist/context/ReaderContext.d.ts +6 -0
  13. package/dist/context/ReaderContext.d.ts.map +1 -1
  14. package/dist/context/ReaderContext.js +6 -0
  15. package/dist/context/ReaderContext.js.map +1 -1
  16. package/dist/context/ReaderProvider.d.ts +3 -0
  17. package/dist/context/ReaderProvider.d.ts.map +1 -1
  18. package/dist/context/ReaderProvider.js +3 -0
  19. package/dist/context/ReaderProvider.js.map +1 -1
  20. package/dist/context/VerseSelectionContext.d.ts +6 -0
  21. package/dist/context/VerseSelectionContext.d.ts.map +1 -1
  22. package/dist/context/VerseSelectionContext.js +3 -0
  23. package/dist/context/VerseSelectionContext.js.map +1 -1
  24. package/dist/context/VerseSelectionProvider.d.ts +3 -0
  25. package/dist/context/VerseSelectionProvider.d.ts.map +1 -1
  26. package/dist/context/VerseSelectionProvider.js +3 -0
  27. package/dist/context/VerseSelectionProvider.js.map +1 -1
  28. package/dist/test/utils.d.ts +7 -0
  29. package/dist/test/utils.d.ts.map +1 -0
  30. package/dist/test/utils.js +7 -0
  31. package/dist/test/utils.js.map +1 -0
  32. package/dist/useChapterNavigation.d.ts +3 -0
  33. package/dist/useChapterNavigation.d.ts.map +1 -1
  34. package/dist/useChapterNavigation.js +3 -0
  35. package/dist/useChapterNavigation.js.map +1 -1
  36. package/dist/useInitData.d.ts +4 -0
  37. package/dist/useInitData.d.ts.map +1 -1
  38. package/dist/useInitData.js +4 -0
  39. package/dist/useInitData.js.map +1 -1
  40. package/dist/useVerseSelection.d.ts +3 -0
  41. package/dist/useVerseSelection.d.ts.map +1 -1
  42. package/dist/useVerseSelection.js +3 -0
  43. package/dist/useVerseSelection.js.map +1 -1
  44. package/package.json +2 -2
  45. package/src/__tests__/mocks/bibles.ts +18 -1
  46. package/src/__tests__/mocks/core-mock-factory.ts +226 -0
  47. package/src/context/ReaderContext.tsx +6 -0
  48. package/src/context/ReaderProvider.tsx +3 -0
  49. package/src/context/VerseSelectionContext.tsx +6 -0
  50. package/src/context/VerseSelectionProvider.tsx +3 -0
  51. package/src/context/YouVersionAuthProvider.test.tsx +14 -131
  52. package/src/test/utils.tsx +12 -0
  53. package/src/useBibleClient.test.tsx +8 -37
  54. package/src/useBook.test.tsx +158 -0
  55. package/src/useBooks.test.tsx +148 -0
  56. package/src/useChapter.test.tsx +70 -128
  57. package/src/useChapterNavigation.ts +3 -0
  58. package/src/useChapters.test.tsx +80 -150
  59. package/src/useHighlights.test.tsx +33 -104
  60. package/src/useInitData.ts +4 -0
  61. package/src/useLanguage.test.tsx +8 -10
  62. package/src/useLanguageClient.test.tsx +9 -25
  63. package/src/useLanguages.test.tsx +27 -64
  64. package/src/usePassage.test.tsx +304 -0
  65. package/src/useTheme.test.tsx +32 -0
  66. package/src/useVOTD.test.tsx +28 -67
  67. package/src/useVerse.test.tsx +73 -149
  68. package/src/useVerseSelection.ts +3 -0
  69. package/src/useVerses.test.tsx +37 -104
  70. package/src/useVersion.test.tsx +29 -66
  71. package/src/useVersions.test.tsx +72 -154
  72. package/src/useYVAuth.test.tsx +26 -134
  73. package/src/utility/getDayOfYear.test.ts +48 -0
  74. package/vitest.config.ts +12 -0
  75. package/src/context/ReaderProvider.test.tsx +0 -264
  76. package/src/context/VerseSelectionProvider.test.tsx +0 -362
  77. package/src/useChapterNavigation.test.tsx +0 -160
  78. package/src/useVerseSelection.test.tsx +0 -33
  79. package/vitest.setup.ts +0 -1
@@ -0,0 +1,158 @@
1
+ import { renderHook, waitFor, act } from '@testing-library/react';
2
+ import { describe, expect, vi, beforeEach, it } from 'vitest';
3
+ import { useBook } from './useBook';
4
+ import { type BibleClient } from '@youversion/platform-core';
5
+ import { useBibleClient } from './useBibleClient';
6
+ import { createYVWrapper } from './test/utils';
7
+ import { createMockBook } from './__tests__/mocks/bibles';
8
+
9
+ vi.mock('./useBibleClient');
10
+
11
+ describe('useBook', () => {
12
+ const mockGetBook = vi.fn();
13
+ const mockBook = createMockBook();
14
+
15
+ beforeEach(() => {
16
+ mockGetBook.mockResolvedValue(mockBook);
17
+
18
+ const mockClient: Partial<BibleClient> = { getBook: mockGetBook };
19
+ vi.mocked(useBibleClient).mockReturnValue(mockClient as BibleClient);
20
+ });
21
+
22
+ describe('fetching book', () => {
23
+ it('should fetch book with versionId and book params', async () => {
24
+ const wrapper = createYVWrapper();
25
+ const { result } = renderHook(() => useBook(111, 'GEN'), { wrapper });
26
+
27
+ expect(result.current.loading).toBe(true);
28
+ expect(result.current.book).toBe(null);
29
+
30
+ await waitFor(() => {
31
+ expect(result.current.loading).toBe(false);
32
+ });
33
+
34
+ expect.soft(mockGetBook).toHaveBeenCalledWith(111, 'GEN');
35
+ expect.soft(result.current.book).toEqual(mockBook);
36
+ });
37
+
38
+ it.each([
39
+ {
40
+ param: 'versionId',
41
+ HookFn: ({ val }: { val: number | string }) => useBook(val as number, 'GEN'),
42
+ initial: { val: 1 },
43
+ updated: { val: 111 },
44
+ expectedInitial: [1, 'GEN'],
45
+ expectedUpdated: [111, 'GEN'],
46
+ },
47
+ {
48
+ param: 'book',
49
+ HookFn: ({ val }: { val: number | string }) => useBook(1, val as string),
50
+ initial: { val: 'GEN' },
51
+ updated: { val: 'EXO' },
52
+ expectedInitial: [1, 'GEN'],
53
+ expectedUpdated: [1, 'EXO'],
54
+ },
55
+ ])(
56
+ 'should refetch when $param changes',
57
+ async ({ HookFn, initial, updated, expectedInitial, expectedUpdated }) => {
58
+ const wrapper = createYVWrapper();
59
+ const { result, rerender } = renderHook(HookFn, {
60
+ wrapper,
61
+ initialProps: initial,
62
+ });
63
+
64
+ await waitFor(() => {
65
+ expect(result.current.loading).toBe(false);
66
+ });
67
+
68
+ expect.soft(mockGetBook).toHaveBeenCalledTimes(1);
69
+ expect.soft(mockGetBook).toHaveBeenLastCalledWith(...expectedInitial);
70
+
71
+ act(() => {
72
+ rerender(updated);
73
+ });
74
+
75
+ await waitFor(() => {
76
+ expect(result.current.loading).toBe(false);
77
+ });
78
+
79
+ expect.soft(mockGetBook).toHaveBeenCalledTimes(2);
80
+ expect.soft(mockGetBook).toHaveBeenLastCalledWith(...expectedUpdated);
81
+ },
82
+ );
83
+
84
+ it('should not fetch when enabled is false', async () => {
85
+ const wrapper = createYVWrapper();
86
+ const { result } = renderHook(() => useBook(1, 'GEN', { enabled: false }), {
87
+ wrapper,
88
+ });
89
+
90
+ await waitFor(() => {
91
+ expect(result.current.loading).toBe(false);
92
+ });
93
+
94
+ expect.soft(mockGetBook).not.toHaveBeenCalled();
95
+ expect.soft(result.current.book).toBe(null);
96
+ });
97
+
98
+ it('should handle fetch errors', async () => {
99
+ const wrapper = createYVWrapper();
100
+ const error = new Error('Failed to fetch book');
101
+ mockGetBook.mockRejectedValueOnce(error);
102
+
103
+ const { result } = renderHook(() => useBook(1, 'GEN'), { wrapper });
104
+
105
+ await waitFor(() => {
106
+ expect(result.current.loading).toBe(false);
107
+ });
108
+
109
+ expect.soft(result.current.error).toEqual(error);
110
+ expect.soft(result.current.book).toBe(null);
111
+ });
112
+
113
+ it('should clear error on successful refetch', async () => {
114
+ const wrapper = createYVWrapper();
115
+ const error = new Error('Failed to fetch book');
116
+ mockGetBook.mockRejectedValueOnce(error).mockResolvedValueOnce(mockBook);
117
+
118
+ const { result } = renderHook(() => useBook(1, 'GEN'), { wrapper });
119
+
120
+ await waitFor(() => {
121
+ expect(result.current.loading).toBe(false);
122
+ });
123
+
124
+ expect.soft(result.current.error).toEqual(error);
125
+ expect.soft(result.current.book).toBe(null);
126
+
127
+ act(() => {
128
+ result.current.refetch();
129
+ });
130
+
131
+ await waitFor(() => {
132
+ expect(result.current.loading).toBe(false);
133
+ });
134
+
135
+ expect.soft(result.current.error).toBe(null);
136
+ expect.soft(result.current.book).toEqual(mockBook);
137
+ });
138
+
139
+ it('should support manual refetch', async () => {
140
+ const wrapper = createYVWrapper();
141
+ const { result } = renderHook(() => useBook(1, 'GEN'), { wrapper });
142
+
143
+ await waitFor(() => {
144
+ expect(result.current.loading).toBe(false);
145
+ });
146
+
147
+ expect(mockGetBook).toHaveBeenCalledTimes(1);
148
+
149
+ act(() => {
150
+ result.current.refetch();
151
+ });
152
+
153
+ await waitFor(() => {
154
+ expect(mockGetBook).toHaveBeenCalledTimes(2);
155
+ });
156
+ });
157
+ });
158
+ });
@@ -0,0 +1,148 @@
1
+ import { renderHook, waitFor, act } from '@testing-library/react';
2
+ import { describe, expect, vi, beforeEach, it } from 'vitest';
3
+ import { useBooks } from './useBooks';
4
+ import { type BibleClient, type BibleBook, type Collection } from '@youversion/platform-core';
5
+ import { useBibleClient } from './useBibleClient';
6
+ import { createYVWrapper } from './test/utils';
7
+ import { createMockBook } from './__tests__/mocks/bibles';
8
+
9
+ vi.mock('./useBibleClient');
10
+
11
+ describe('useBooks', () => {
12
+ const mockGetBooks = vi.fn();
13
+
14
+ const mockBooks: Collection<BibleBook> = {
15
+ data: [
16
+ createMockBook(),
17
+ createMockBook({
18
+ id: 'EXO',
19
+ title: 'Exodus',
20
+ full_title: 'The Second Book of Moses, Commonly Called Exodus',
21
+ abbreviation: 'Exod',
22
+ }),
23
+ ],
24
+ next_page_token: null,
25
+ };
26
+
27
+ beforeEach(() => {
28
+ mockGetBooks.mockResolvedValue(mockBooks);
29
+
30
+ const mockClient: Partial<BibleClient> = { getBooks: mockGetBooks };
31
+ vi.mocked(useBibleClient).mockReturnValue(mockClient as BibleClient);
32
+ });
33
+
34
+ describe('fetching books', () => {
35
+ it('should fetch all books for a version', async () => {
36
+ const wrapper = createYVWrapper();
37
+ const { result } = renderHook(() => useBooks(111), { wrapper });
38
+
39
+ expect(result.current.loading).toBe(true);
40
+ expect(result.current.books).toBe(null);
41
+
42
+ await waitFor(() => {
43
+ expect(result.current.loading).toBe(false);
44
+ });
45
+
46
+ expect.soft(mockGetBooks).toHaveBeenCalledWith(111);
47
+ expect.soft(result.current.books).toEqual(mockBooks);
48
+ });
49
+
50
+ it('should refetch when versionId changes', async () => {
51
+ const wrapper = createYVWrapper();
52
+ const { result, rerender } = renderHook(({ versionId }) => useBooks(versionId), {
53
+ wrapper,
54
+ initialProps: { versionId: 111 },
55
+ });
56
+
57
+ await waitFor(() => {
58
+ expect(result.current.loading).toBe(false);
59
+ });
60
+
61
+ expect.soft(mockGetBooks).toHaveBeenCalledTimes(1);
62
+ expect.soft(mockGetBooks).toHaveBeenLastCalledWith(111);
63
+
64
+ rerender({ versionId: 1 });
65
+
66
+ await waitFor(() => {
67
+ expect(result.current.loading).toBe(false);
68
+ });
69
+
70
+ expect.soft(mockGetBooks).toHaveBeenCalledTimes(2);
71
+ expect.soft(mockGetBooks).toHaveBeenLastCalledWith(1);
72
+ });
73
+
74
+ it('should not fetch when enabled is false', async () => {
75
+ const wrapper = createYVWrapper();
76
+ const { result } = renderHook(() => useBooks(111, { enabled: false }), {
77
+ wrapper,
78
+ });
79
+
80
+ await waitFor(() => {
81
+ expect(result.current.loading).toBe(false);
82
+ });
83
+
84
+ expect.soft(mockGetBooks).not.toHaveBeenCalled();
85
+ expect.soft(result.current.books).toBe(null);
86
+ });
87
+
88
+ it('should handle fetch errors', async () => {
89
+ const wrapper = createYVWrapper();
90
+ const error = new Error('Failed to fetch books');
91
+ mockGetBooks.mockRejectedValueOnce(error);
92
+
93
+ const { result } = renderHook(() => useBooks(111), { wrapper });
94
+
95
+ await waitFor(() => {
96
+ expect(result.current.loading).toBe(false);
97
+ });
98
+
99
+ expect.soft(result.current.error).toEqual(error);
100
+ expect.soft(result.current.books).toBe(null);
101
+ });
102
+
103
+ it('should clear error on successful refetch', async () => {
104
+ const wrapper = createYVWrapper();
105
+ const error = new Error('Failed to fetch books');
106
+ mockGetBooks.mockRejectedValueOnce(error).mockResolvedValueOnce(mockBooks);
107
+
108
+ const { result } = renderHook(() => useBooks(111), { wrapper });
109
+
110
+ await waitFor(() => {
111
+ expect(result.current.loading).toBe(false);
112
+ });
113
+
114
+ expect.soft(result.current.error).toEqual(error);
115
+ expect.soft(result.current.books).toBe(null);
116
+
117
+ act(() => {
118
+ result.current.refetch();
119
+ });
120
+
121
+ await waitFor(() => {
122
+ expect(result.current.loading).toBe(false);
123
+ });
124
+
125
+ expect.soft(result.current.error).toBe(null);
126
+ expect.soft(result.current.books).toEqual(mockBooks);
127
+ });
128
+
129
+ it('should support manual refetch', async () => {
130
+ const wrapper = createYVWrapper();
131
+ const { result } = renderHook(() => useBooks(111), { wrapper });
132
+
133
+ await waitFor(() => {
134
+ expect(result.current.loading).toBe(false);
135
+ });
136
+
137
+ expect(mockGetBooks).toHaveBeenCalledTimes(1);
138
+
139
+ act(() => {
140
+ result.current.refetch();
141
+ });
142
+
143
+ await waitFor(() => {
144
+ expect(mockGetBooks).toHaveBeenCalledTimes(2);
145
+ });
146
+ });
147
+ });
148
+ });
@@ -1,15 +1,13 @@
1
1
  import { renderHook, waitFor, act } from '@testing-library/react';
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import type { ReactNode } from 'react';
2
+ import { describe, expect, vi, beforeEach, it } from 'vitest';
4
3
  import { useChapter } from './useChapter';
5
- import { YouVersionContext } from './context';
6
4
  import { type BibleClient, type BibleChapter } from '@youversion/platform-core';
7
5
  import { useBibleClient } from './useBibleClient';
6
+ import { createYVWrapper } from './test/utils';
8
7
 
9
8
  vi.mock('./useBibleClient');
10
9
 
11
10
  describe('useChapter', () => {
12
- const mockAppKey = 'test-app-key';
13
11
  const mockGetChapter = vi.fn();
14
12
 
15
13
  const mockChapter: BibleChapter = {
@@ -18,15 +16,7 @@ describe('useChapter', () => {
18
16
  title: 'Matthew 1',
19
17
  };
20
18
 
21
- const createWrapper = (contextValue: { appKey: string }) => {
22
- return ({ children }: { children: ReactNode }) => (
23
- <YouVersionContext.Provider value={contextValue}>{children}</YouVersionContext.Provider>
24
- );
25
- };
26
-
27
19
  beforeEach(() => {
28
- vi.resetAllMocks();
29
-
30
20
  mockGetChapter.mockResolvedValue(mockChapter);
31
21
 
32
22
  const mockClient: Partial<BibleClient> = { getChapter: mockGetChapter };
@@ -35,10 +25,7 @@ describe('useChapter', () => {
35
25
 
36
26
  describe('fetching chapter', () => {
37
27
  it('should fetch chapter with versionId, book, chapter params', async () => {
38
- const wrapper = createWrapper({
39
- appKey: mockAppKey,
40
- });
41
-
28
+ const wrapper = createYVWrapper();
42
29
  const { result } = renderHook(() => useChapter(111, 'MAT', 1), { wrapper });
43
30
 
44
31
  expect(result.current.loading).toBe(true);
@@ -48,102 +35,66 @@ describe('useChapter', () => {
48
35
  expect(result.current.loading).toBe(false);
49
36
  });
50
37
 
51
- expect(mockGetChapter).toHaveBeenCalledWith(111, 'MAT', 1);
52
- expect(result.current.chapter).toEqual(mockChapter);
38
+ expect.soft(mockGetChapter).toHaveBeenCalledWith(111, 'MAT', 1);
39
+ expect.soft(result.current.chapter).toEqual(mockChapter);
53
40
  });
54
41
 
55
- it('should refetch when versionId changes', async () => {
56
- const wrapper = createWrapper({
57
- appKey: mockAppKey,
58
- });
59
-
60
- const { result, rerender } = renderHook(({ versionId }) => useChapter(versionId, 'MAT', 1), {
61
- wrapper,
62
- initialProps: { versionId: 1 },
63
- });
64
-
65
- await waitFor(() => {
66
- expect(result.current.loading).toBe(false);
67
- });
68
-
69
- expect(mockGetChapter).toHaveBeenCalledTimes(1);
70
- expect(mockGetChapter).toHaveBeenLastCalledWith(1, 'MAT', 1);
71
-
72
- act(() => {
73
- rerender({ versionId: 111 });
74
- });
75
-
76
- await waitFor(() => {
77
- expect(result.current.loading).toBe(false);
78
- });
79
-
80
- expect(mockGetChapter).toHaveBeenCalledTimes(2);
81
- expect(mockGetChapter).toHaveBeenLastCalledWith(111, 'MAT', 1);
82
- });
83
-
84
- it('should refetch when book changes', async () => {
85
- const wrapper = createWrapper({
86
- appKey: mockAppKey,
87
- });
88
-
89
- const { result, rerender } = renderHook(({ book }) => useChapter(1, book, 1), {
90
- wrapper,
91
- initialProps: { book: 'MAT' },
92
- });
93
-
94
- await waitFor(() => {
95
- expect(result.current.loading).toBe(false);
96
- });
97
-
98
- expect(mockGetChapter).toHaveBeenCalledTimes(1);
99
- expect(mockGetChapter).toHaveBeenLastCalledWith(1, 'MAT', 1);
100
-
101
- act(() => {
102
- rerender({ book: 'GEN' });
103
- });
104
-
105
- await waitFor(() => {
106
- expect(result.current.loading).toBe(false);
107
- });
108
-
109
- expect(mockGetChapter).toHaveBeenCalledTimes(2);
110
- expect(mockGetChapter).toHaveBeenLastCalledWith(1, 'GEN', 1);
111
- });
112
-
113
- it('should refetch when chapter changes', async () => {
114
- const wrapper = createWrapper({
115
- appKey: mockAppKey,
116
- });
117
-
118
- const { result, rerender } = renderHook(({ chapter }) => useChapter(1, 'MAT', chapter), {
119
- wrapper,
120
- initialProps: { chapter: 1 },
121
- });
122
-
123
- await waitFor(() => {
124
- expect(result.current.loading).toBe(false);
125
- });
126
-
127
- expect(mockGetChapter).toHaveBeenCalledTimes(1);
128
- expect(mockGetChapter).toHaveBeenLastCalledWith(1, 'MAT', 1);
129
-
130
- act(() => {
131
- rerender({ chapter: 5 });
132
- });
133
-
134
- await waitFor(() => {
135
- expect(result.current.loading).toBe(false);
136
- });
137
-
138
- expect(mockGetChapter).toHaveBeenCalledTimes(2);
139
- expect(mockGetChapter).toHaveBeenLastCalledWith(1, 'MAT', 5);
140
- });
42
+ it.each([
43
+ {
44
+ param: 'versionId',
45
+ HookFn: ({ val }: { val: number | string }) => useChapter(val as number, 'MAT', 1),
46
+ initial: { val: 1 },
47
+ updated: { val: 111 },
48
+ expectedInitial: [1, 'MAT', 1],
49
+ expectedUpdated: [111, 'MAT', 1],
50
+ },
51
+ {
52
+ param: 'book',
53
+ HookFn: ({ val }: { val: number | string }) => useChapter(1, val as string, 1),
54
+ initial: { val: 'MAT' },
55
+ updated: { val: 'GEN' },
56
+ expectedInitial: [1, 'MAT', 1],
57
+ expectedUpdated: [1, 'GEN', 1],
58
+ },
59
+ {
60
+ param: 'chapter',
61
+ HookFn: ({ val }: { val: number | string }) => useChapter(1, 'MAT', val as number),
62
+ initial: { val: 1 },
63
+ updated: { val: 5 },
64
+ expectedInitial: [1, 'MAT', 1],
65
+ expectedUpdated: [1, 'MAT', 5],
66
+ },
67
+ ])(
68
+ 'should refetch when $param changes',
69
+ async ({ HookFn, initial, updated, expectedInitial, expectedUpdated }) => {
70
+ const wrapper = createYVWrapper();
71
+ const { result, rerender } = renderHook(HookFn, {
72
+ wrapper,
73
+ initialProps: initial,
74
+ });
75
+
76
+ await waitFor(() => {
77
+ expect(result.current.loading).toBe(false);
78
+ });
79
+
80
+ expect.soft(mockGetChapter).toHaveBeenCalledTimes(1);
81
+ expect.soft(mockGetChapter).toHaveBeenLastCalledWith(...expectedInitial);
82
+
83
+ act(() => {
84
+ rerender(updated);
85
+ });
86
+
87
+ await waitFor(() => {
88
+ expect(result.current.loading).toBe(false);
89
+ });
90
+
91
+ expect.soft(mockGetChapter).toHaveBeenCalledTimes(2);
92
+ expect.soft(mockGetChapter).toHaveBeenLastCalledWith(...expectedUpdated);
93
+ },
94
+ );
141
95
 
142
96
  it('should not fetch when enabled is false', async () => {
143
- const wrapper = createWrapper({
144
- appKey: mockAppKey,
145
- });
146
-
97
+ const wrapper = createYVWrapper();
147
98
  const { result } = renderHook(() => useChapter(1, 'MAT', 1, { enabled: false }), {
148
99
  wrapper,
149
100
  });
@@ -152,44 +103,38 @@ describe('useChapter', () => {
152
103
  expect(result.current.loading).toBe(false);
153
104
  });
154
105
 
155
- expect(mockGetChapter).not.toHaveBeenCalled();
156
- expect(result.current.chapter).toBe(null);
106
+ expect.soft(mockGetChapter).not.toHaveBeenCalled();
107
+ expect.soft(result.current.chapter).toBe(null);
157
108
  });
158
109
 
159
110
  it('should handle fetch errors', async () => {
111
+ const wrapper = createYVWrapper();
160
112
  const error = new Error('Failed to fetch chapter');
161
113
  mockGetChapter.mockRejectedValueOnce(error);
162
114
 
163
- const wrapper = createWrapper({
164
- appKey: mockAppKey,
165
- });
166
-
167
115
  const { result } = renderHook(() => useChapter(1, 'MAT', 1), { wrapper });
168
116
 
169
117
  await waitFor(() => {
170
118
  expect(result.current.loading).toBe(false);
171
119
  });
172
120
 
173
- expect(result.current.error).toEqual(error);
174
- expect(result.current.chapter).toBe(null);
121
+ expect.soft(result.current.error).toEqual(error);
122
+ expect.soft(result.current.chapter).toBe(null);
175
123
  });
176
124
 
177
125
  it('should clear error on successful refetch', async () => {
126
+ const wrapper = createYVWrapper();
178
127
  const error = new Error('Failed to fetch chapter');
179
128
  mockGetChapter.mockRejectedValueOnce(error).mockResolvedValueOnce(mockChapter);
180
129
 
181
- const wrapper = createWrapper({
182
- appKey: mockAppKey,
183
- });
184
-
185
130
  const { result } = renderHook(() => useChapter(1, 'MAT', 1), { wrapper });
186
131
 
187
132
  await waitFor(() => {
188
133
  expect(result.current.loading).toBe(false);
189
134
  });
190
135
 
191
- expect(result.current.error).toEqual(error);
192
- expect(result.current.chapter).toBe(null);
136
+ expect.soft(result.current.error).toEqual(error);
137
+ expect.soft(result.current.chapter).toBe(null);
193
138
 
194
139
  act(() => {
195
140
  result.current.refetch();
@@ -199,15 +144,12 @@ describe('useChapter', () => {
199
144
  expect(result.current.loading).toBe(false);
200
145
  });
201
146
 
202
- expect(result.current.error).toBe(null);
203
- expect(result.current.chapter).toEqual(mockChapter);
147
+ expect.soft(result.current.error).toBe(null);
148
+ expect.soft(result.current.chapter).toEqual(mockChapter);
204
149
  });
205
150
 
206
151
  it('should support manual refetch', async () => {
207
- const wrapper = createWrapper({
208
- appKey: mockAppKey,
209
- });
210
-
152
+ const wrapper = createYVWrapper();
211
153
  const { result } = renderHook(() => useChapter(1, 'MAT', 1), { wrapper });
212
154
 
213
155
  await waitFor(() => {
@@ -16,6 +16,9 @@ interface UseChapterNavigationResult {
16
16
  /**
17
17
  * Provides navigation functionality for chapters across book boundaries,
18
18
  * including intro chapter support.
19
+ *
20
+ * @deprecated This hook will be removed in the next major version.
21
+ * Use `getAdjacentChapter` from `@youversion/platform-core` directly instead.
19
22
  */
20
23
  export function useChapterNavigation(): UseChapterNavigationResult {
21
24
  const { currentChapter, currentVersion, currentBook, setChapter, setBook } = useReaderContext();