@datalayer/core 0.0.9 → 0.0.11

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 (199) hide show
  1. package/lib/__tests__/shared/cleanup-shared.d.ts +4 -0
  2. package/lib/__tests__/shared/cleanup-shared.js +228 -0
  3. package/lib/__tests__/shared/test-config.d.ts +51 -0
  4. package/lib/__tests__/shared/test-config.js +110 -0
  5. package/lib/__tests__/shared/test-constants.d.ts +66 -0
  6. package/lib/__tests__/shared/test-constants.js +79 -0
  7. package/lib/api/DatalayerApi.d.ts +1 -1
  8. package/lib/api/DatalayerApi.js +73 -42
  9. package/lib/api/__tests__/iam.authentication.integration.test.d.ts +1 -0
  10. package/lib/api/__tests__/iam.authentication.integration.test.js +247 -0
  11. package/lib/api/__tests__/iam.healthz.integration.test.d.ts +1 -0
  12. package/lib/api/__tests__/iam.healthz.integration.test.js +63 -0
  13. package/lib/api/__tests__/iam.profile.integration.test.d.ts +1 -0
  14. package/lib/api/__tests__/iam.profile.integration.test.js +252 -0
  15. package/lib/api/__tests__/runtimes.environments.integration.test.d.ts +1 -0
  16. package/lib/api/__tests__/runtimes.environments.integration.test.js +122 -0
  17. package/lib/api/__tests__/runtimes.healthz.integration.test.d.ts +1 -0
  18. package/lib/api/__tests__/runtimes.healthz.integration.test.js +50 -0
  19. package/lib/api/__tests__/runtimes.integration.test.d.ts +1 -0
  20. package/lib/api/__tests__/runtimes.integration.test.js +369 -0
  21. package/lib/api/__tests__/spacer.healthz.integration.test.d.ts +1 -0
  22. package/lib/api/__tests__/spacer.healthz.integration.test.js +50 -0
  23. package/lib/api/__tests__/spacer.integration.test.d.ts +1 -0
  24. package/lib/api/__tests__/spacer.integration.test.js +519 -0
  25. package/lib/api/constants.d.ts +19 -0
  26. package/lib/api/constants.js +23 -0
  27. package/lib/api/iam/__tests__/authentication.unit.test.d.ts +1 -0
  28. package/lib/api/iam/__tests__/authentication.unit.test.js +63 -0
  29. package/lib/api/iam/__tests__/healthz.unit.test.d.ts +1 -0
  30. package/lib/api/iam/__tests__/healthz.unit.test.js +60 -0
  31. package/lib/api/iam/__tests__/profile.unit.test.d.ts +1 -0
  32. package/lib/api/iam/__tests__/profile.unit.test.js +57 -0
  33. package/lib/api/iam/authentication.d.ts +40 -0
  34. package/lib/api/iam/authentication.js +128 -0
  35. package/lib/api/iam/healthz.d.ts +15 -0
  36. package/lib/api/iam/healthz.js +43 -0
  37. package/lib/api/iam/index.d.ts +12 -0
  38. package/lib/api/iam/index.js +17 -0
  39. package/lib/api/iam/profile.d.ts +15 -0
  40. package/lib/api/iam/profile.js +41 -0
  41. package/lib/api/index.d.ts +20 -3
  42. package/lib/api/index.js +22 -3
  43. package/lib/api/runtimes/__tests__/environments.unit.test.d.ts +1 -0
  44. package/lib/api/runtimes/__tests__/environments.unit.test.js +77 -0
  45. package/lib/api/runtimes/__tests__/healthz.unit.test.d.ts +1 -0
  46. package/lib/api/runtimes/__tests__/healthz.unit.test.js +57 -0
  47. package/lib/api/runtimes/__tests__/runtimes.unit.test.d.ts +1 -0
  48. package/lib/api/runtimes/__tests__/runtimes.unit.test.js +139 -0
  49. package/lib/api/runtimes/__tests__/snapshots.unit.test.d.ts +1 -0
  50. package/lib/api/runtimes/__tests__/snapshots.unit.test.js +96 -0
  51. package/lib/api/runtimes/environments.d.ts +9 -0
  52. package/lib/api/runtimes/environments.js +28 -0
  53. package/lib/api/runtimes/healthz.d.ts +25 -0
  54. package/lib/api/runtimes/healthz.js +43 -0
  55. package/lib/api/runtimes/index.d.ts +10 -5
  56. package/lib/api/runtimes/index.js +10 -5
  57. package/lib/api/runtimes/runtimes.d.ts +54 -0
  58. package/lib/api/runtimes/runtimes.js +169 -0
  59. package/lib/api/runtimes/snapshots.d.ts +34 -21
  60. package/lib/api/runtimes/snapshots.js +69 -138
  61. package/lib/api/spacer/__tests__/healthz.unit.test.d.ts +1 -0
  62. package/lib/api/spacer/__tests__/healthz.unit.test.js +57 -0
  63. package/lib/api/spacer/__tests__/items.unit.test.d.ts +1 -0
  64. package/lib/api/spacer/__tests__/items.unit.test.js +165 -0
  65. package/lib/api/spacer/__tests__/lexicals.unit.test.d.ts +1 -0
  66. package/lib/api/spacer/__tests__/lexicals.unit.test.js +323 -0
  67. package/lib/api/spacer/__tests__/notebooks.unit.test.d.ts +1 -0
  68. package/lib/api/spacer/__tests__/notebooks.unit.test.js +224 -0
  69. package/lib/api/spacer/__tests__/users.unit.test.d.ts +1 -0
  70. package/lib/api/spacer/__tests__/users.unit.test.js +132 -0
  71. package/lib/api/spacer/healthz.d.ts +25 -0
  72. package/lib/api/spacer/healthz.js +43 -0
  73. package/lib/api/spacer/index.d.ts +13 -0
  74. package/lib/api/spacer/index.js +17 -0
  75. package/lib/api/spacer/items.d.ts +17 -0
  76. package/lib/api/spacer/items.js +40 -0
  77. package/lib/api/spacer/lexicals.d.ts +26 -0
  78. package/lib/api/spacer/lexicals.js +74 -0
  79. package/lib/api/spacer/notebooks.d.ts +26 -0
  80. package/lib/api/spacer/notebooks.js +74 -0
  81. package/lib/api/spacer/spaces.d.ts +9 -0
  82. package/lib/api/spacer/spaces.js +29 -0
  83. package/lib/api/spacer/users.d.ts +9 -0
  84. package/lib/api/spacer/users.js +28 -0
  85. package/lib/api/types/iam.d.ts +180 -0
  86. package/lib/api/types/index.d.ts +32 -0
  87. package/lib/api/types/index.js +36 -0
  88. package/lib/api/types/runtimes.d.ts +235 -0
  89. package/lib/api/types/runtimes.js +5 -0
  90. package/lib/api/types/spacer.d.ts +271 -0
  91. package/lib/api/types/spacer.js +5 -0
  92. package/lib/api/utils/__tests__/validation.test.d.ts +1 -0
  93. package/lib/api/utils/__tests__/validation.test.js +109 -0
  94. package/lib/api/utils/validation.d.ts +24 -0
  95. package/lib/api/utils/validation.js +133 -0
  96. package/lib/components/display/JupyterDialog.js +4 -8
  97. package/lib/components/progress/CreditsIndicator.d.ts +1 -1
  98. package/lib/components/runtimes/RuntimeCellVariablesDialog.js +2 -2
  99. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +1 -1
  100. package/lib/components/runtimes/RuntimeLauncherDialog.js +5 -2
  101. package/lib/components/runtimes/RuntimePickerBase.d.ts +1 -1
  102. package/lib/components/runtimes/RuntimePickerBase.js +1 -1
  103. package/lib/components/runtimes/RuntimePickerCell.js +2 -1
  104. package/lib/components/runtimes/RuntimePickerNotebook.d.ts +1 -1
  105. package/lib/components/runtimes/RuntimePickerNotebook.js +1 -1
  106. package/lib/components/runtimes/RuntimeSimplePicker.js +2 -1
  107. package/lib/components/runtimes/RuntimeTransfer.d.ts +1 -1
  108. package/lib/components/runtimes/RuntimeUtils.d.ts +1 -1
  109. package/lib/components/snapshots/RuntimeSnapshotMenu.d.ts +1 -1
  110. package/lib/components/snapshots/RuntimeSnapshotMenu.js +2 -2
  111. package/lib/components/snippets/SnippetDialog.js +1 -1
  112. package/lib/components/storage/ContentsBrowser.js +2 -2
  113. package/lib/components/tables/DataTable.js +2 -1
  114. package/lib/hooks/useDatalayer.d.ts +1 -1
  115. package/lib/hooks/useDatalayer.js +1 -1
  116. package/lib/hooks/useIAM.js +1 -1
  117. package/lib/hooks/useRuntimes.js +1 -1
  118. package/lib/index.d.ts +9 -0
  119. package/lib/index.js +10 -0
  120. package/lib/sdk/client/__tests__/sdk.health.integration.test.d.ts +1 -0
  121. package/lib/sdk/client/__tests__/sdk.health.integration.test.js +110 -0
  122. package/lib/sdk/client/__tests__/sdk.iam.integration.test.d.ts +1 -0
  123. package/lib/sdk/client/__tests__/sdk.iam.integration.test.js +179 -0
  124. package/lib/sdk/client/__tests__/sdk.models.integration.test.d.ts +1 -0
  125. package/lib/sdk/client/__tests__/sdk.models.integration.test.js +376 -0
  126. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.d.ts +1 -0
  127. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.js +276 -0
  128. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.d.ts +1 -0
  129. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.js +361 -0
  130. package/lib/sdk/client/base.d.ts +88 -0
  131. package/lib/sdk/client/base.js +112 -0
  132. package/lib/sdk/client/index.d.ts +192 -0
  133. package/lib/sdk/client/index.js +128 -0
  134. package/lib/sdk/client/mixins/HealthMixin.d.ts +100 -0
  135. package/lib/sdk/client/mixins/HealthMixin.js +133 -0
  136. package/lib/sdk/client/mixins/IAMMixin.d.ts +59 -0
  137. package/lib/sdk/client/mixins/IAMMixin.js +83 -0
  138. package/lib/sdk/client/mixins/RuntimesMixin.d.ts +134 -0
  139. package/lib/sdk/client/mixins/RuntimesMixin.js +221 -0
  140. package/lib/sdk/client/mixins/SpacerMixin.d.ts +184 -0
  141. package/lib/sdk/client/mixins/SpacerMixin.js +278 -0
  142. package/lib/sdk/client/models/Lexical.d.ts +156 -0
  143. package/lib/sdk/client/models/Lexical.js +275 -0
  144. package/lib/sdk/client/models/Notebook.d.ts +174 -0
  145. package/lib/sdk/client/models/Notebook.js +311 -0
  146. package/lib/sdk/client/models/Runtime.d.ts +221 -0
  147. package/lib/sdk/client/models/Runtime.js +341 -0
  148. package/lib/sdk/client/models/Snapshot.d.ts +156 -0
  149. package/lib/sdk/client/models/Snapshot.js +244 -0
  150. package/lib/sdk/client/models/Space.d.ts +182 -0
  151. package/lib/sdk/client/models/Space.js +276 -0
  152. package/lib/sdk/client/models/__tests__/Lexical.test.d.ts +1 -0
  153. package/lib/sdk/client/models/__tests__/Lexical.test.js +288 -0
  154. package/lib/sdk/client/models/__tests__/Notebook.test.d.ts +1 -0
  155. package/lib/sdk/client/models/__tests__/Notebook.test.js +206 -0
  156. package/lib/sdk/client/models/__tests__/Runtime.test.d.ts +1 -0
  157. package/lib/sdk/client/models/__tests__/Runtime.test.js +133 -0
  158. package/lib/sdk/client/models/__tests__/Snapshot.test.d.ts +1 -0
  159. package/lib/sdk/client/models/__tests__/Snapshot.test.js +244 -0
  160. package/lib/sdk/client/models/__tests__/Space.test.d.ts +1 -0
  161. package/lib/sdk/client/models/__tests__/Space.test.js +334 -0
  162. package/lib/sdk/client/models/index.d.ts +30 -0
  163. package/lib/sdk/client/models/index.js +30 -0
  164. package/lib/sdk/client/utils/mixins.d.ts +42 -0
  165. package/lib/sdk/client/utils/mixins.js +47 -0
  166. package/lib/sdk/index.d.ts +26 -0
  167. package/lib/sdk/index.js +32 -0
  168. package/lib/sdk/stateful/index.d.ts +3 -0
  169. package/lib/sdk/stateful/index.js +7 -0
  170. package/lib/{api → sdk/stateful}/runtimes/actions.d.ts +1 -1
  171. package/lib/{api → sdk/stateful}/runtimes/actions.js +3 -3
  172. package/lib/{api → sdk/stateful}/runtimes/apis.d.ts +1 -1
  173. package/lib/sdk/stateful/runtimes/apis.js +5 -0
  174. package/lib/sdk/stateful/runtimes/index.d.ts +5 -0
  175. package/lib/sdk/stateful/runtimes/index.js +9 -0
  176. package/lib/sdk/stateful/runtimes/snapshots.d.ts +25 -0
  177. package/lib/sdk/stateful/runtimes/snapshots.js +150 -0
  178. package/lib/services/DatalayerServiceManager.js +1 -1
  179. package/lib/state/substates/IAMState.js +1 -1
  180. package/lib/state/substates/RuntimesState.d.ts +1 -1
  181. package/lib/state/substates/RuntimesState.js +1 -1
  182. package/lib/state/substates/SurveysState.js +1 -1
  183. package/lib/test-setup.js +1 -0
  184. package/package.json +19 -9
  185. /package/lib/api/{runtimes/apis.js → types/iam.js} +0 -0
  186. /package/lib/{api → sdk/stateful}/jupyter/exec/Python.d.ts +0 -0
  187. /package/lib/{api → sdk/stateful}/jupyter/exec/Python.js +0 -0
  188. /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.d.ts +0 -0
  189. /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.js +0 -0
  190. /package/lib/{api → sdk/stateful}/jupyter/exec/index.d.ts +0 -0
  191. /package/lib/{api → sdk/stateful}/jupyter/exec/index.js +0 -0
  192. /package/lib/{api → sdk/stateful}/jupyter/index.d.ts +0 -0
  193. /package/lib/{api → sdk/stateful}/jupyter/index.js +0 -0
  194. /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.d.ts +0 -0
  195. /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.js +0 -0
  196. /package/lib/{api → sdk/stateful}/runtimes/settings.d.ts +0 -0
  197. /package/lib/{api → sdk/stateful}/runtimes/settings.js +0 -0
  198. /package/lib/{api → sdk/stateful}/runtimes/utils.d.ts +0 -0
  199. /package/lib/{api → sdk/stateful}/runtimes/utils.js +0 -0
@@ -0,0 +1,323 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
6
+ import { lexicals } from '..';
7
+ import * as DatalayerApi from '../../DatalayerApi';
8
+ import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../../constants';
9
+ import { MOCK_JWT_TOKEN } from '../../../__tests__/shared/test-constants';
10
+ // Mock the DatalayerApi module
11
+ vi.mock('../../DatalayerApi', () => ({
12
+ requestDatalayerAPI: vi.fn(),
13
+ }));
14
+ describe('Spacer Lexicals Unit Tests', () => {
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+ });
18
+ describe('create', () => {
19
+ const mockCreateResponse = {
20
+ success: true,
21
+ message: 'Document created successfully',
22
+ document: {
23
+ id: 'lexical-123',
24
+ uid: 'uid-lexical-123',
25
+ name: 'Test Document',
26
+ content: {},
27
+ space_id: 'space-456',
28
+ owner_id: 'user-789',
29
+ created_at: '2024-01-01T00:00:00Z',
30
+ },
31
+ };
32
+ it('should successfully create a lexical document with FormData', async () => {
33
+ console.log('Testing lexical document creation with FormData...');
34
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
35
+ mockedRequest.mockResolvedValue(mockCreateResponse);
36
+ const lexicalData = {
37
+ spaceId: 'space-456',
38
+ documentType: 'lexical',
39
+ name: 'Test Document',
40
+ description: 'A test document',
41
+ };
42
+ const result = await lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, DEFAULT_SERVICE_URLS.SPACER);
43
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
44
+ // Check that FormData was passed as the body
45
+ const callArgs = mockedRequest.mock.calls[0][0];
46
+ expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals`);
47
+ expect(callArgs.method).toBe('POST');
48
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
49
+ expect(callArgs.body).toBeInstanceOf(FormData);
50
+ expect(result).toEqual(mockCreateResponse);
51
+ expect(result.success).toBe(true);
52
+ expect(result.document.name).toBe('Test Document');
53
+ console.log('Document created successfully');
54
+ });
55
+ it('should handle FormData with file attachment', async () => {
56
+ console.log('Testing lexical document creation with file...');
57
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
58
+ mockedRequest.mockResolvedValue(mockCreateResponse);
59
+ const file = new File(['test content'], 'test.txt', {
60
+ type: 'text/plain',
61
+ });
62
+ const lexicalData = {
63
+ spaceId: 'space-456',
64
+ documentType: 'lexical',
65
+ name: 'Test Document',
66
+ description: 'A test document with file',
67
+ file,
68
+ };
69
+ await lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, DEFAULT_SERVICE_URLS.SPACER);
70
+ const callArgs = mockedRequest.mock.calls[0][0];
71
+ expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals`);
72
+ expect(callArgs.method).toBe('POST');
73
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
74
+ expect(callArgs.body).toBeInstanceOf(FormData);
75
+ console.log('Document with file created successfully');
76
+ });
77
+ it('should handle different document types', async () => {
78
+ console.log('Testing lexical document with different type...');
79
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
80
+ mockedRequest.mockResolvedValue(mockCreateResponse);
81
+ const lexicalData = {
82
+ spaceId: 'space-456',
83
+ documentType: 'markdown',
84
+ name: 'Markdown Document',
85
+ description: 'A markdown document',
86
+ };
87
+ await lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, DEFAULT_SERVICE_URLS.SPACER);
88
+ const callArgs = mockedRequest.mock.calls[0][0];
89
+ expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals`);
90
+ expect(callArgs.method).toBe('POST');
91
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
92
+ expect(callArgs.body).toBeInstanceOf(FormData);
93
+ console.log('Document with different type created successfully');
94
+ });
95
+ it('should handle API errors during creation', async () => {
96
+ console.log('Testing lexical document creation with API error...');
97
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
98
+ mockedRequest.mockRejectedValue(new Error('API Error'));
99
+ const lexicalData = {
100
+ spaceId: 'space-456',
101
+ documentType: 'lexical',
102
+ name: 'Test Document',
103
+ description: 'A test document',
104
+ };
105
+ await expect(lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('API Error');
106
+ console.log('API error handled correctly');
107
+ });
108
+ it('should use custom base URL when provided', async () => {
109
+ console.log('Testing lexical document creation with custom base URL...');
110
+ const customUrl = 'https://custom.spacer.api';
111
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
112
+ mockedRequest.mockResolvedValue(mockCreateResponse);
113
+ const lexicalData = {
114
+ spaceId: 'space-456',
115
+ documentType: 'lexical',
116
+ name: 'Test Document',
117
+ description: 'A test document',
118
+ };
119
+ await lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, customUrl);
120
+ const callArgs = mockedRequest.mock.calls[0][0];
121
+ expect(callArgs.url).toBe(`${customUrl}${API_BASE_PATHS.SPACER}/lexicals`);
122
+ expect(callArgs.method).toBe('POST');
123
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
124
+ expect(callArgs.body).toBeInstanceOf(FormData);
125
+ console.log('Custom base URL used correctly');
126
+ });
127
+ it('should handle server validation errors', async () => {
128
+ console.log('Testing lexical document creation with validation error...');
129
+ const validationErrorResponse = {
130
+ success: false,
131
+ message: 'Validation failed',
132
+ errors: ['Invalid space ID', 'Document type not supported'],
133
+ };
134
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
135
+ mockedRequest.mockResolvedValue(validationErrorResponse);
136
+ const lexicalData = {
137
+ spaceId: 'invalid-space',
138
+ documentType: 'unknown',
139
+ name: 'Test Document',
140
+ description: 'A test document',
141
+ };
142
+ const result = await lexicals.createLexical(MOCK_JWT_TOKEN, lexicalData, DEFAULT_SERVICE_URLS.SPACER);
143
+ expect(result).toEqual(validationErrorResponse);
144
+ expect(result.success).toBe(false);
145
+ expect(result.message).toBe('Validation failed');
146
+ console.log('Validation error handled correctly');
147
+ });
148
+ });
149
+ describe('get', () => {
150
+ const mockGetResponse = {
151
+ success: true,
152
+ message: 'Document retrieved successfully',
153
+ document: {
154
+ id: 'lexical-123',
155
+ uid: 'uid-lexical-123',
156
+ name: 'Test Document',
157
+ content: {
158
+ root: {
159
+ type: 'root',
160
+ children: [
161
+ {
162
+ type: 'paragraph',
163
+ children: [{ type: 'text', text: 'Test content' }],
164
+ },
165
+ ],
166
+ },
167
+ },
168
+ space_id: 'space-456',
169
+ owner_id: 'user-789',
170
+ created_at: '2024-01-01T00:00:00Z',
171
+ updated_at: '2024-01-02T00:00:00Z',
172
+ },
173
+ };
174
+ it('should successfully get a lexical document by ID', async () => {
175
+ console.log('Testing get lexical document by ID...');
176
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
177
+ mockedRequest.mockResolvedValue(mockGetResponse);
178
+ const result = await lexicals.getLexical(MOCK_JWT_TOKEN, 'lexical-123', DEFAULT_SERVICE_URLS.SPACER);
179
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
180
+ expect(mockedRequest).toHaveBeenCalledWith({
181
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
182
+ method: 'GET',
183
+ token: MOCK_JWT_TOKEN,
184
+ });
185
+ expect(result).toEqual(mockGetResponse);
186
+ expect(result.success).toBe(true);
187
+ expect(result.document?.id).toBe('lexical-123');
188
+ console.log('Document retrieved successfully');
189
+ });
190
+ it('should handle document not found (404)', async () => {
191
+ console.log('Testing get document with 404...');
192
+ const notFoundResponse = {
193
+ success: false,
194
+ message: 'Document not found',
195
+ };
196
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
197
+ mockedRequest.mockResolvedValue(notFoundResponse);
198
+ const result = await lexicals.getLexical(MOCK_JWT_TOKEN, 'nonexistent-document', DEFAULT_SERVICE_URLS.SPACER);
199
+ expect(result).toEqual(notFoundResponse);
200
+ expect(result.success).toBe(false);
201
+ expect(result.document).toBeUndefined();
202
+ console.log('404 response handled correctly');
203
+ });
204
+ it('should handle API errors during get', async () => {
205
+ console.log('Testing get document with API error...');
206
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
207
+ mockedRequest.mockRejectedValue(new Error('Network error'));
208
+ await expect(lexicals.getLexical(MOCK_JWT_TOKEN, 'lexical-123', DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Network error');
209
+ console.log('API error handled correctly');
210
+ });
211
+ it('should use custom base URL when provided', async () => {
212
+ console.log('Testing get document with custom base URL...');
213
+ const customUrl = 'https://custom.spacer.api';
214
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
215
+ mockedRequest.mockResolvedValue(mockGetResponse);
216
+ await lexicals.getLexical(MOCK_JWT_TOKEN, 'lexical-123', customUrl);
217
+ expect(mockedRequest).toHaveBeenCalledWith({
218
+ url: `${customUrl}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
219
+ method: 'GET',
220
+ token: MOCK_JWT_TOKEN,
221
+ });
222
+ console.log('Custom base URL used correctly');
223
+ });
224
+ });
225
+ describe('update', () => {
226
+ const mockUpdateResponse = {
227
+ success: true,
228
+ message: 'Document updated successfully',
229
+ document: {
230
+ id: 'lexical-123',
231
+ uid: 'uid-lexical-123',
232
+ name: 'Updated Document',
233
+ content: {},
234
+ space_id: 'space-456',
235
+ owner_id: 'user-789',
236
+ created_at: '2024-01-01T00:00:00Z',
237
+ updated_at: '2024-01-03T00:00:00Z',
238
+ },
239
+ };
240
+ it('should successfully update a document name', async () => {
241
+ console.log('Testing update document name...');
242
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
243
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
244
+ const updateData = {
245
+ name: 'Updated Document',
246
+ };
247
+ const result = await lexicals.updateLexical(MOCK_JWT_TOKEN, 'lexical-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
248
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
249
+ expect(mockedRequest).toHaveBeenCalledWith({
250
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
251
+ method: 'PUT',
252
+ token: MOCK_JWT_TOKEN,
253
+ body: updateData,
254
+ });
255
+ expect(result).toEqual(mockUpdateResponse);
256
+ expect(result.success).toBe(true);
257
+ expect(result.document.name).toBe('Updated Document');
258
+ console.log('Document name updated successfully');
259
+ });
260
+ it('should successfully update a document description', async () => {
261
+ console.log('Testing update document description...');
262
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
263
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
264
+ const updateData = {
265
+ description: 'Updated description',
266
+ };
267
+ const result = await lexicals.updateLexical(MOCK_JWT_TOKEN, 'lexical-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
268
+ expect(mockedRequest).toHaveBeenCalledWith({
269
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
270
+ method: 'PUT',
271
+ token: MOCK_JWT_TOKEN,
272
+ body: updateData,
273
+ });
274
+ expect(result.success).toBe(true);
275
+ console.log('Document description updated successfully');
276
+ });
277
+ it('should successfully update both name and description', async () => {
278
+ console.log('Testing update document name and description...');
279
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
280
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
281
+ const updateData = {
282
+ name: 'Updated Document',
283
+ description: 'Updated description',
284
+ };
285
+ const result = await lexicals.updateLexical(MOCK_JWT_TOKEN, 'lexical-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
286
+ expect(mockedRequest).toHaveBeenCalledWith({
287
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
288
+ method: 'PUT',
289
+ token: MOCK_JWT_TOKEN,
290
+ body: updateData,
291
+ });
292
+ expect(result.success).toBe(true);
293
+ console.log('Document name and description updated successfully');
294
+ });
295
+ it('should handle API errors during update', async () => {
296
+ console.log('Testing update document with API error...');
297
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
298
+ mockedRequest.mockRejectedValue(new Error('Update failed'));
299
+ const updateData = {
300
+ name: 'Updated Document',
301
+ };
302
+ await expect(lexicals.updateLexical(MOCK_JWT_TOKEN, 'lexical-123', updateData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Update failed');
303
+ console.log('API error handled correctly');
304
+ });
305
+ it('should use custom base URL when provided', async () => {
306
+ console.log('Testing update document with custom base URL...');
307
+ const customUrl = 'https://custom.spacer.api';
308
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
309
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
310
+ const updateData = {
311
+ name: 'Updated Document',
312
+ };
313
+ await lexicals.updateLexical(MOCK_JWT_TOKEN, 'lexical-123', updateData, customUrl);
314
+ expect(mockedRequest).toHaveBeenCalledWith({
315
+ url: `${customUrl}${API_BASE_PATHS.SPACER}/lexicals/lexical-123`,
316
+ method: 'PUT',
317
+ token: MOCK_JWT_TOKEN,
318
+ body: updateData,
319
+ });
320
+ console.log('Custom base URL used correctly');
321
+ });
322
+ });
323
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,224 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
6
+ import { notebooks } from '..';
7
+ import * as DatalayerApi from '../../DatalayerApi';
8
+ import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../../constants';
9
+ import { MOCK_JWT_TOKEN } from '../../../__tests__/shared/test-constants';
10
+ // Mock the DatalayerApi module
11
+ vi.mock('../../DatalayerApi', () => ({
12
+ requestDatalayerAPI: vi.fn(),
13
+ }));
14
+ describe('Spacer Notebooks Unit Tests', () => {
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+ });
18
+ describe('create', () => {
19
+ const mockCreateResponse = {
20
+ success: true,
21
+ message: 'Notebook created successfully',
22
+ notebook: {
23
+ id: 'notebook-123',
24
+ uid: 'uid-notebook-123',
25
+ name: 'Test Notebook',
26
+ path: '/notebooks/test-notebook',
27
+ space_id: 'space-456',
28
+ owner_id: 'user-789',
29
+ created_at: '2024-01-01T00:00:00Z',
30
+ },
31
+ };
32
+ it('should successfully create a notebook with FormData', async () => {
33
+ console.log('Testing notebook creation with FormData...');
34
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
35
+ mockedRequest.mockResolvedValue(mockCreateResponse);
36
+ const notebookData = {
37
+ spaceId: 'space-456',
38
+ notebookType: 'jupyter',
39
+ name: 'Test Notebook',
40
+ description: 'A test notebook',
41
+ };
42
+ const result = await notebooks.createNotebook(MOCK_JWT_TOKEN, notebookData, DEFAULT_SERVICE_URLS.SPACER);
43
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
44
+ // Check that FormData was passed as the body
45
+ const callArgs = mockedRequest.mock.calls[0][0];
46
+ expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks`);
47
+ expect(callArgs.method).toBe('POST');
48
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
49
+ expect(callArgs.body).toBeInstanceOf(FormData);
50
+ expect(result).toEqual(mockCreateResponse);
51
+ expect(result.success).toBe(true);
52
+ expect(result.notebook.name).toBe('Test Notebook');
53
+ console.log('Notebook created successfully');
54
+ });
55
+ it('should handle FormData with file attachment', async () => {
56
+ console.log('Testing notebook creation with file...');
57
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
58
+ mockedRequest.mockResolvedValue(mockCreateResponse);
59
+ const file = new File(['notebook content'], 'test.ipynb', {
60
+ type: 'application/json',
61
+ });
62
+ const notebookData = {
63
+ spaceId: 'space-456',
64
+ notebookType: 'jupyter',
65
+ name: 'Test Notebook',
66
+ description: 'A test notebook',
67
+ file,
68
+ };
69
+ await notebooks.createNotebook(MOCK_JWT_TOKEN, notebookData, DEFAULT_SERVICE_URLS.SPACER);
70
+ const callArgs = mockedRequest.mock.calls[0][0];
71
+ expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks`);
72
+ expect(callArgs.method).toBe('POST');
73
+ expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
74
+ expect(callArgs.body).toBeInstanceOf(FormData);
75
+ console.log('Notebook with file created successfully');
76
+ });
77
+ it('should handle API errors during creation', async () => {
78
+ console.log('Testing notebook creation with API error...');
79
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
80
+ mockedRequest.mockRejectedValue(new Error('API Error'));
81
+ const formData = new FormData();
82
+ formData.append('spaceId', 'space-456');
83
+ formData.append('notebookType', 'jupyter');
84
+ formData.append('name', 'Test Notebook');
85
+ formData.append('description', 'A test notebook');
86
+ await expect(notebooks.createNotebook(MOCK_JWT_TOKEN, formData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('API Error');
87
+ console.log('API error handled correctly');
88
+ });
89
+ });
90
+ describe('get', () => {
91
+ const mockGetResponse = {
92
+ success: true,
93
+ message: 'Notebook retrieved successfully',
94
+ notebook: {
95
+ id: 'notebook-123',
96
+ uid: 'uid-notebook-123',
97
+ name: 'Test Notebook',
98
+ path: '/notebooks/test-notebook',
99
+ space_id: 'space-456',
100
+ owner_id: 'user-789',
101
+ created_at: '2024-01-01T00:00:00Z',
102
+ updated_at: '2024-01-02T00:00:00Z',
103
+ },
104
+ };
105
+ it('should successfully get a notebook by ID', async () => {
106
+ console.log('Testing get notebook by ID...');
107
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
108
+ mockedRequest.mockResolvedValue(mockGetResponse);
109
+ const result = await notebooks.getNotebook(MOCK_JWT_TOKEN, 'notebook-123', DEFAULT_SERVICE_URLS.SPACER);
110
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
111
+ expect(mockedRequest).toHaveBeenCalledWith({
112
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
113
+ method: 'GET',
114
+ token: MOCK_JWT_TOKEN,
115
+ });
116
+ expect(result).toEqual(mockGetResponse);
117
+ expect(result.success).toBe(true);
118
+ expect(result.notebook?.id).toBe('notebook-123');
119
+ console.log('Notebook retrieved successfully');
120
+ });
121
+ it('should handle notebook not found (404)', async () => {
122
+ console.log('Testing get notebook with 404...');
123
+ const notFoundResponse = {
124
+ success: false,
125
+ message: 'Notebook not found',
126
+ };
127
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
128
+ mockedRequest.mockResolvedValue(notFoundResponse);
129
+ const result = await notebooks.getNotebook(MOCK_JWT_TOKEN, 'nonexistent-notebook', DEFAULT_SERVICE_URLS.SPACER);
130
+ expect(result).toEqual(notFoundResponse);
131
+ expect(result.success).toBe(false);
132
+ expect(result.notebook).toBeUndefined();
133
+ console.log('404 response handled correctly');
134
+ });
135
+ it('should handle API errors during get', async () => {
136
+ console.log('Testing get notebook with API error...');
137
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
138
+ mockedRequest.mockRejectedValue(new Error('Network error'));
139
+ await expect(notebooks.getNotebook(MOCK_JWT_TOKEN, 'notebook-123', DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Network error');
140
+ console.log('API error handled correctly');
141
+ });
142
+ });
143
+ describe('update', () => {
144
+ const mockUpdateResponse = {
145
+ success: true,
146
+ message: 'Notebook updated successfully',
147
+ notebook: {
148
+ id: 'notebook-123',
149
+ uid: 'uid-notebook-123',
150
+ name: 'Updated Notebook',
151
+ path: '/notebooks/updated-notebook',
152
+ space_id: 'space-456',
153
+ owner_id: 'user-789',
154
+ created_at: '2024-01-01T00:00:00Z',
155
+ updated_at: '2024-01-03T00:00:00Z',
156
+ },
157
+ };
158
+ it('should successfully update a notebook name', async () => {
159
+ console.log('Testing update notebook name...');
160
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
161
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
162
+ const updateData = {
163
+ name: 'Updated Notebook',
164
+ };
165
+ const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
166
+ expect(mockedRequest).toHaveBeenCalledTimes(1);
167
+ expect(mockedRequest).toHaveBeenCalledWith({
168
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
169
+ method: 'PUT',
170
+ token: MOCK_JWT_TOKEN,
171
+ body: updateData,
172
+ });
173
+ expect(result).toEqual(mockUpdateResponse);
174
+ expect(result.success).toBe(true);
175
+ expect(result.notebook.name).toBe('Updated Notebook');
176
+ console.log('Notebook name updated successfully');
177
+ });
178
+ it('should successfully update a notebook description', async () => {
179
+ console.log('Testing update notebook description...');
180
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
181
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
182
+ const updateData = {
183
+ description: 'Updated description',
184
+ };
185
+ const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
186
+ expect(mockedRequest).toHaveBeenCalledWith({
187
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
188
+ method: 'PUT',
189
+ token: MOCK_JWT_TOKEN,
190
+ body: updateData,
191
+ });
192
+ expect(result.success).toBe(true);
193
+ console.log('Notebook description updated successfully');
194
+ });
195
+ it('should successfully update both name and description', async () => {
196
+ console.log('Testing update notebook name and description...');
197
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
198
+ mockedRequest.mockResolvedValue(mockUpdateResponse);
199
+ const updateData = {
200
+ name: 'Updated Notebook',
201
+ description: 'Updated description',
202
+ };
203
+ const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
204
+ expect(mockedRequest).toHaveBeenCalledWith({
205
+ url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
206
+ method: 'PUT',
207
+ token: MOCK_JWT_TOKEN,
208
+ body: updateData,
209
+ });
210
+ expect(result.success).toBe(true);
211
+ console.log('Notebook name and description updated successfully');
212
+ });
213
+ it('should handle API errors during update', async () => {
214
+ console.log('Testing update notebook with API error...');
215
+ const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
216
+ mockedRequest.mockRejectedValue(new Error('Update failed'));
217
+ const updateData = {
218
+ name: 'Updated Notebook',
219
+ };
220
+ await expect(notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Update failed');
221
+ console.log('API error handled correctly');
222
+ });
223
+ });
224
+ });
@@ -0,0 +1 @@
1
+ export {};