@datalayer/core 0.0.10 → 0.0.12

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 (195) 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/progress/CreditsIndicator.d.ts +1 -1
  97. package/lib/components/runtimes/RuntimeCellVariablesDialog.js +1 -1
  98. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +1 -1
  99. package/lib/components/runtimes/RuntimeLauncherDialog.js +2 -1
  100. package/lib/components/runtimes/RuntimePickerBase.d.ts +1 -1
  101. package/lib/components/runtimes/RuntimePickerBase.js +1 -1
  102. package/lib/components/runtimes/RuntimePickerCell.js +2 -1
  103. package/lib/components/runtimes/RuntimePickerNotebook.d.ts +1 -1
  104. package/lib/components/runtimes/RuntimePickerNotebook.js +1 -1
  105. package/lib/components/runtimes/RuntimeSimplePicker.js +2 -1
  106. package/lib/components/runtimes/RuntimeTransfer.d.ts +1 -1
  107. package/lib/components/runtimes/RuntimeUtils.d.ts +1 -1
  108. package/lib/components/snapshots/RuntimeSnapshotMenu.d.ts +1 -1
  109. package/lib/components/snapshots/RuntimeSnapshotMenu.js +1 -1
  110. package/lib/hooks/useDatalayer.d.ts +1 -1
  111. package/lib/hooks/useDatalayer.js +1 -1
  112. package/lib/hooks/useIAM.js +1 -1
  113. package/lib/hooks/useRuntimes.js +1 -1
  114. package/lib/index.d.ts +9 -0
  115. package/lib/index.js +10 -0
  116. package/lib/sdk/client/__tests__/sdk.health.integration.test.d.ts +1 -0
  117. package/lib/sdk/client/__tests__/sdk.health.integration.test.js +110 -0
  118. package/lib/sdk/client/__tests__/sdk.iam.integration.test.d.ts +1 -0
  119. package/lib/sdk/client/__tests__/sdk.iam.integration.test.js +179 -0
  120. package/lib/sdk/client/__tests__/sdk.models.integration.test.d.ts +1 -0
  121. package/lib/sdk/client/__tests__/sdk.models.integration.test.js +376 -0
  122. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.d.ts +1 -0
  123. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.js +276 -0
  124. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.d.ts +1 -0
  125. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.js +361 -0
  126. package/lib/sdk/client/base.d.ts +88 -0
  127. package/lib/sdk/client/base.js +112 -0
  128. package/lib/sdk/client/index.d.ts +192 -0
  129. package/lib/sdk/client/index.js +128 -0
  130. package/lib/sdk/client/mixins/HealthMixin.d.ts +100 -0
  131. package/lib/sdk/client/mixins/HealthMixin.js +133 -0
  132. package/lib/sdk/client/mixins/IAMMixin.d.ts +59 -0
  133. package/lib/sdk/client/mixins/IAMMixin.js +83 -0
  134. package/lib/sdk/client/mixins/RuntimesMixin.d.ts +134 -0
  135. package/lib/sdk/client/mixins/RuntimesMixin.js +221 -0
  136. package/lib/sdk/client/mixins/SpacerMixin.d.ts +184 -0
  137. package/lib/sdk/client/mixins/SpacerMixin.js +278 -0
  138. package/lib/sdk/client/models/Lexical.d.ts +156 -0
  139. package/lib/sdk/client/models/Lexical.js +275 -0
  140. package/lib/sdk/client/models/Notebook.d.ts +174 -0
  141. package/lib/sdk/client/models/Notebook.js +311 -0
  142. package/lib/sdk/client/models/Runtime.d.ts +221 -0
  143. package/lib/sdk/client/models/Runtime.js +341 -0
  144. package/lib/sdk/client/models/Snapshot.d.ts +156 -0
  145. package/lib/sdk/client/models/Snapshot.js +244 -0
  146. package/lib/sdk/client/models/Space.d.ts +182 -0
  147. package/lib/sdk/client/models/Space.js +276 -0
  148. package/lib/sdk/client/models/__tests__/Lexical.test.d.ts +1 -0
  149. package/lib/sdk/client/models/__tests__/Lexical.test.js +288 -0
  150. package/lib/sdk/client/models/__tests__/Notebook.test.d.ts +1 -0
  151. package/lib/sdk/client/models/__tests__/Notebook.test.js +206 -0
  152. package/lib/sdk/client/models/__tests__/Runtime.test.d.ts +1 -0
  153. package/lib/sdk/client/models/__tests__/Runtime.test.js +133 -0
  154. package/lib/sdk/client/models/__tests__/Snapshot.test.d.ts +1 -0
  155. package/lib/sdk/client/models/__tests__/Snapshot.test.js +244 -0
  156. package/lib/sdk/client/models/__tests__/Space.test.d.ts +1 -0
  157. package/lib/sdk/client/models/__tests__/Space.test.js +334 -0
  158. package/lib/sdk/client/models/index.d.ts +30 -0
  159. package/lib/sdk/client/models/index.js +30 -0
  160. package/lib/sdk/client/utils/mixins.d.ts +42 -0
  161. package/lib/sdk/client/utils/mixins.js +47 -0
  162. package/lib/sdk/index.d.ts +26 -0
  163. package/lib/sdk/index.js +32 -0
  164. package/lib/sdk/stateful/index.d.ts +3 -0
  165. package/lib/sdk/stateful/index.js +7 -0
  166. package/lib/{api → sdk/stateful}/runtimes/actions.d.ts +1 -1
  167. package/lib/{api → sdk/stateful}/runtimes/actions.js +3 -3
  168. package/lib/{api → sdk/stateful}/runtimes/apis.d.ts +1 -1
  169. package/lib/sdk/stateful/runtimes/apis.js +5 -0
  170. package/lib/sdk/stateful/runtimes/index.d.ts +5 -0
  171. package/lib/sdk/stateful/runtimes/index.js +9 -0
  172. package/lib/sdk/stateful/runtimes/snapshots.d.ts +25 -0
  173. package/lib/sdk/stateful/runtimes/snapshots.js +150 -0
  174. package/lib/services/DatalayerServiceManager.js +1 -1
  175. package/lib/state/substates/IAMState.js +1 -1
  176. package/lib/state/substates/RuntimesState.d.ts +1 -1
  177. package/lib/state/substates/RuntimesState.js +1 -1
  178. package/lib/state/substates/SurveysState.js +1 -1
  179. package/lib/test-setup.js +1 -0
  180. package/package.json +19 -9
  181. /package/lib/api/{runtimes/apis.js → types/iam.js} +0 -0
  182. /package/lib/{api → sdk/stateful}/jupyter/exec/Python.d.ts +0 -0
  183. /package/lib/{api → sdk/stateful}/jupyter/exec/Python.js +0 -0
  184. /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.d.ts +0 -0
  185. /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.js +0 -0
  186. /package/lib/{api → sdk/stateful}/jupyter/exec/index.d.ts +0 -0
  187. /package/lib/{api → sdk/stateful}/jupyter/exec/index.js +0 -0
  188. /package/lib/{api → sdk/stateful}/jupyter/index.d.ts +0 -0
  189. /package/lib/{api → sdk/stateful}/jupyter/index.js +0 -0
  190. /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.d.ts +0 -0
  191. /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.js +0 -0
  192. /package/lib/{api → sdk/stateful}/runtimes/settings.d.ts +0 -0
  193. /package/lib/{api → sdk/stateful}/runtimes/settings.js +0 -0
  194. /package/lib/{api → sdk/stateful}/runtimes/utils.d.ts +0 -0
  195. /package/lib/{api → sdk/stateful}/runtimes/utils.js +0 -0
@@ -0,0 +1,252 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { describe, it, expect, beforeAll } from 'vitest';
6
+ import { authentication, profile } from '../iam';
7
+ import { testConfig, debugLog, skipIfNoToken, } from '../../__tests__/shared/test-config';
8
+ let DATALAYER_TOKEN;
9
+ let SESSION_TOKEN;
10
+ let BASE_URL;
11
+ // Skip all tests if no token is available
12
+ const skipTests = skipIfNoToken();
13
+ beforeAll(async () => {
14
+ if (skipTests) {
15
+ console.log('WARNING: Skipping profile integration tests: No Datalayer API token configured');
16
+ console.log(' Set DATALAYER_API_TOKEN env var or DATALAYER_TEST_TOKEN in .env.test');
17
+ return;
18
+ }
19
+ // Get token and base URL from test config
20
+ DATALAYER_TOKEN = testConfig.getToken();
21
+ BASE_URL = testConfig.getBaseUrl('IAM');
22
+ debugLog('Test configuration loaded');
23
+ debugLog('Base URL:', BASE_URL);
24
+ debugLog('Token available:', !!DATALAYER_TOKEN);
25
+ // Login to get a session token for profile tests
26
+ try {
27
+ const loginResponse = await authentication.login({
28
+ token: DATALAYER_TOKEN,
29
+ });
30
+ SESSION_TOKEN = loginResponse.token;
31
+ debugLog('Successfully logged in, got session token');
32
+ }
33
+ catch (error) {
34
+ console.error('Failed to login for profile tests:', error);
35
+ throw error;
36
+ }
37
+ });
38
+ describe.skipIf(skipTests)('IAM Profile Integration Tests', () => {
39
+ describe('me', () => {
40
+ it('should successfully get current user profile with token', async () => {
41
+ console.log('Testing /me endpoint with session token...');
42
+ const response = await profile.me(SESSION_TOKEN, BASE_URL);
43
+ console.log('Profile response:', JSON.stringify(response, null, 2));
44
+ // Verify response structure
45
+ expect(response).toBeDefined();
46
+ expect(response.success).toBe(true);
47
+ expect(response.message).toBeDefined();
48
+ expect(typeof response.message).toBe('string');
49
+ // Verify me object structure
50
+ expect(response.me).toBeDefined();
51
+ expect(response.me.id).toBeDefined();
52
+ expect(typeof response.me.id).toBe('string');
53
+ expect(response.me.uid).toBeDefined();
54
+ expect(typeof response.me.uid).toBe('string');
55
+ expect(response.me.handle).toBeDefined();
56
+ expect(typeof response.me.handle).toBe('string');
57
+ expect(response.me.email).toBeDefined();
58
+ expect(typeof response.me.email).toBe('string');
59
+ expect(response.me.firstName).toBeDefined();
60
+ expect(typeof response.me.firstName).toBe('string');
61
+ expect(response.me.lastName).toBeDefined();
62
+ expect(typeof response.me.lastName).toBe('string');
63
+ expect(response.me.avatarUrl).toBeDefined();
64
+ expect(typeof response.me.avatarUrl).toBe('string');
65
+ expect(response.me.roles).toBeDefined();
66
+ expect(Array.isArray(response.me.roles)).toBe(true);
67
+ console.log('Successfully retrieved user profile');
68
+ console.log('ID:', response.me.id);
69
+ console.log('UID:', response.me.uid);
70
+ console.log('Email:', response.me.email);
71
+ console.log('Handle:', response.me.handle);
72
+ console.log('Name:', response.me.firstName, response.me.lastName);
73
+ console.log('Roles:', response.me.roles.join(', '));
74
+ });
75
+ it('should successfully get current user profile using default URL', async () => {
76
+ console.log('Testing /me endpoint with default URL...');
77
+ const response = await profile.me(SESSION_TOKEN);
78
+ console.log('Profile response with default URL:', JSON.stringify(response, null, 2));
79
+ // Verify response structure
80
+ expect(response).toBeDefined();
81
+ expect(response.success).toBe(true);
82
+ expect(response.message).toBeDefined();
83
+ expect(response.me).toBeDefined();
84
+ expect(response.me.uid).toBeDefined();
85
+ expect(response.me.handle).toBeDefined();
86
+ expect(response.me.email).toBeDefined();
87
+ expect(Array.isArray(response.me.roles)).toBe(true);
88
+ console.log('Successfully retrieved user profile with default URL');
89
+ console.log('UID:', response.me.uid);
90
+ console.log('Handle:', response.me.handle);
91
+ });
92
+ it('should fail when using invalid token', async () => {
93
+ console.log('Testing /me endpoint with invalid token...');
94
+ const invalidToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpbnZhbGlkIiwiaWF0IjoxNTE2MjM5MDIyfQ.invalid_signature_here';
95
+ try {
96
+ await profile.me(invalidToken, BASE_URL);
97
+ // If we get here, the API accepted an invalid token (shouldn't happen)
98
+ throw new Error('Expected API to reject invalid token');
99
+ }
100
+ catch (error) {
101
+ console.log('API correctly rejected invalid token:', error.message);
102
+ expect(error).toBeDefined();
103
+ expect(error.message).toBeDefined();
104
+ // The error message should indicate server error or authentication failure
105
+ expect(error.message.includes('401') ||
106
+ error.message.includes('Unauthorized') ||
107
+ error.message.includes('Invalid') ||
108
+ error.message.includes('credentials') ||
109
+ error.message.includes('Server Error') ||
110
+ error.message.includes('500')).toBe(true);
111
+ }
112
+ });
113
+ it('should fail when no token is provided', async () => {
114
+ console.log('Testing /me endpoint without token...');
115
+ try {
116
+ // @ts-expect-error Testing missing required parameter
117
+ await profile.me();
118
+ // Should not reach here
119
+ throw new Error('Expected function to throw for missing token');
120
+ }
121
+ catch (error) {
122
+ console.log('Correctly rejected request without token:', error.message);
123
+ expect(error).toBeDefined();
124
+ expect(error.message).toBe('Authentication token is required');
125
+ }
126
+ });
127
+ it('should fail when empty token is provided', async () => {
128
+ console.log('Testing /me endpoint with empty token...');
129
+ try {
130
+ await profile.me('', BASE_URL);
131
+ // Should not reach here
132
+ throw new Error('Expected function to throw for empty token');
133
+ }
134
+ catch (error) {
135
+ console.log('Correctly rejected request with empty token:', error.message);
136
+ expect(error).toBeDefined();
137
+ expect(error.message).toBe('Authentication token is required');
138
+ }
139
+ });
140
+ });
141
+ describe('whoami', () => {
142
+ it('should successfully get current user identity with token', async () => {
143
+ console.log('Testing /whoami endpoint with session token...');
144
+ const response = await profile.whoami(SESSION_TOKEN, BASE_URL);
145
+ console.log('WhoAmI response:', JSON.stringify(response, null, 2));
146
+ // Verify response structure
147
+ expect(response).toBeDefined();
148
+ expect(response.success).toBe(true);
149
+ expect(response.message).toBeDefined();
150
+ expect(typeof response.message).toBe('string');
151
+ // Verify profile object structure
152
+ expect(response.profile).toBeDefined();
153
+ expect(response.profile.id).toBeDefined();
154
+ expect(typeof response.profile.id).toBe('string');
155
+ expect(response.profile.uid).toBeDefined();
156
+ expect(typeof response.profile.uid).toBe('string');
157
+ expect(response.profile.handle_s).toBeDefined();
158
+ expect(typeof response.profile.handle_s).toBe('string');
159
+ expect(response.profile.email_s).toBeDefined();
160
+ expect(typeof response.profile.email_s).toBe('string');
161
+ expect(response.profile.first_name_t).toBeDefined();
162
+ expect(typeof response.profile.first_name_t).toBe('string');
163
+ expect(response.profile.last_name_t).toBeDefined();
164
+ expect(typeof response.profile.last_name_t).toBe('string');
165
+ expect(response.profile.type_s).toBeDefined();
166
+ expect(typeof response.profile.type_s).toBe('string');
167
+ expect(response.profile.origin_s).toBeDefined();
168
+ expect(typeof response.profile.origin_s).toBe('string');
169
+ expect(response.profile.creation_ts_dt).toBeDefined();
170
+ expect(typeof response.profile.creation_ts_dt).toBe('string');
171
+ expect(response.profile.last_update_ts_dt).toBeDefined();
172
+ expect(typeof response.profile.last_update_ts_dt).toBe('string');
173
+ expect(response.profile.join_ts_dt).toBeDefined();
174
+ expect(typeof response.profile.join_ts_dt).toBe('string');
175
+ // join_request_ts_dt can be null
176
+ if (response.profile.join_request_ts_dt !== null) {
177
+ expect(typeof response.profile.join_request_ts_dt).toBe('string');
178
+ }
179
+ console.log('Successfully retrieved user identity');
180
+ console.log('ID:', response.profile.id);
181
+ console.log('UID:', response.profile.uid);
182
+ console.log('Email:', response.profile.email_s);
183
+ console.log('Handle:', response.profile.handle_s);
184
+ console.log('Name:', response.profile.first_name_t, response.profile.last_name_t);
185
+ console.log('Type:', response.profile.type_s);
186
+ });
187
+ it('should successfully get current user identity using default URL', async () => {
188
+ console.log('Testing /whoami endpoint with default URL...');
189
+ const response = await profile.whoami(SESSION_TOKEN);
190
+ console.log('WhoAmI response with default URL:', JSON.stringify(response, null, 2));
191
+ // Verify response structure
192
+ expect(response).toBeDefined();
193
+ expect(response.success).toBe(true);
194
+ expect(response.message).toBeDefined();
195
+ expect(response.profile).toBeDefined();
196
+ expect(response.profile.uid).toBeDefined();
197
+ expect(response.profile.handle_s).toBeDefined();
198
+ expect(response.profile.email_s).toBeDefined();
199
+ console.log('Successfully retrieved user identity with default URL');
200
+ console.log('UID:', response.profile.uid);
201
+ console.log('Handle:', response.profile.handle_s);
202
+ });
203
+ it('should fail whoami when using invalid token', async () => {
204
+ console.log('Testing /whoami endpoint with invalid token...');
205
+ const invalidToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpbnZhbGlkIiwiaWF0IjoxNTE2MjM5MDIyfQ.invalid_signature_here';
206
+ try {
207
+ await profile.whoami(invalidToken, BASE_URL);
208
+ // If we get here, the API accepted an invalid token (shouldn't happen)
209
+ throw new Error('Expected API to reject invalid token');
210
+ }
211
+ catch (error) {
212
+ console.log('API correctly rejected invalid token:', error.message);
213
+ expect(error).toBeDefined();
214
+ expect(error.message).toBeDefined();
215
+ // The error message should indicate server error or authentication failure
216
+ expect(error.message.includes('401') ||
217
+ error.message.includes('Unauthorized') ||
218
+ error.message.includes('Invalid') ||
219
+ error.message.includes('credentials') ||
220
+ error.message.includes('Server Error') ||
221
+ error.message.includes('500')).toBe(true);
222
+ }
223
+ });
224
+ it('should fail whoami when no token is provided', async () => {
225
+ console.log('Testing /whoami endpoint without token...');
226
+ try {
227
+ // @ts-expect-error Testing missing required parameter
228
+ await profile.whoami();
229
+ // Should not reach here
230
+ throw new Error('Expected function to throw for missing token');
231
+ }
232
+ catch (error) {
233
+ console.log('Correctly rejected request without token:', error.message);
234
+ expect(error).toBeDefined();
235
+ expect(error.message).toBe('Authentication token is required');
236
+ }
237
+ });
238
+ it('should fail whoami when empty token is provided', async () => {
239
+ console.log('Testing /whoami endpoint with empty token...');
240
+ try {
241
+ await profile.whoami('', BASE_URL);
242
+ // Should not reach here
243
+ throw new Error('Expected function to throw for empty token');
244
+ }
245
+ catch (error) {
246
+ console.log('Correctly rejected request with empty token:', error.message);
247
+ expect(error).toBeDefined();
248
+ expect(error.message).toBe('Authentication token is required');
249
+ }
250
+ });
251
+ });
252
+ });
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { describe, it, expect, beforeAll } from 'vitest';
6
+ import { environments } from '../runtimes';
7
+ import { testConfig, debugLog, skipIfNoToken, } from '../../__tests__/shared/test-config';
8
+ let DATALAYER_TOKEN;
9
+ let BASE_URL;
10
+ // Skip all tests if no token is available
11
+ const skipTests = skipIfNoToken();
12
+ beforeAll(async () => {
13
+ if (skipTests) {
14
+ console.log('WARNING: Skipping Runtimes Environments integration tests: No Datalayer API token configured');
15
+ console.log(' Set DATALAYER_API_TOKEN env var or DATALAYER_TEST_TOKEN in .env.test');
16
+ return;
17
+ }
18
+ // Get token and base URL from test config
19
+ DATALAYER_TOKEN = testConfig.getToken();
20
+ BASE_URL = testConfig.getBaseUrl('RUNTIMES');
21
+ debugLog('Test configuration loaded');
22
+ debugLog('Base URL:', BASE_URL);
23
+ debugLog('Token available:', !!DATALAYER_TOKEN);
24
+ });
25
+ describe.skipIf(skipTests)('Runtimes Environments Integration Tests', () => {
26
+ describe('list', () => {
27
+ it('should successfully list available environments', async () => {
28
+ console.log('Testing list environments endpoint...');
29
+ const response = await environments.listEnvironments(DATALAYER_TOKEN, BASE_URL);
30
+ console.log('Environments response:', JSON.stringify(response, null, 2));
31
+ // Verify the response structure
32
+ expect(response).toBeDefined();
33
+ expect(response).toHaveProperty('success');
34
+ expect(response.success).toBe(true);
35
+ expect(response).toHaveProperty('message');
36
+ expect(response).toHaveProperty('environments');
37
+ expect(Array.isArray(response.environments)).toBe(true);
38
+ // Check that we have at least some environments
39
+ console.log(`Found ${response.environments.length} available environments`);
40
+ // If we have environments, check the structure of the first one
41
+ if (response.environments.length > 0) {
42
+ const firstEnv = response.environments[0];
43
+ console.log('First environment:', firstEnv.title);
44
+ // Verify environment structure
45
+ expect(firstEnv).toHaveProperty('title');
46
+ expect(firstEnv).toHaveProperty('description');
47
+ expect(firstEnv).toHaveProperty('dockerImage');
48
+ expect(firstEnv).toHaveProperty('language');
49
+ expect(firstEnv).toHaveProperty('burning_rate');
50
+ expect(typeof firstEnv.burning_rate).toBe('number');
51
+ }
52
+ });
53
+ it('should work with default URL if not specified', async () => {
54
+ console.log('Testing list environments with default URL...');
55
+ // Call without specifying URL to use default
56
+ const response = await environments.listEnvironments(DATALAYER_TOKEN);
57
+ console.log('Default URL environments response:', JSON.stringify(response, null, 2));
58
+ // Should still get valid response
59
+ expect(response).toBeDefined();
60
+ expect(response.success).toBe(true);
61
+ expect(response).toHaveProperty('environments');
62
+ expect(Array.isArray(response.environments)).toBe(true);
63
+ });
64
+ it('should include environment resource information', async () => {
65
+ console.log('Testing environment resource information...');
66
+ const response = await environments.listEnvironments(DATALAYER_TOKEN, BASE_URL);
67
+ // Check if any environment has resource information
68
+ const envWithResources = response.environments.find(env => env.resources || env.resourcesRanges);
69
+ if (envWithResources) {
70
+ console.log('Found environment with resources:', envWithResources.title);
71
+ if (envWithResources.resources) {
72
+ console.log('Resources:', envWithResources.resources);
73
+ expect(envWithResources.resources).toHaveProperty('cpu');
74
+ expect(envWithResources.resources).toHaveProperty('memory');
75
+ }
76
+ if (envWithResources.resourcesRanges) {
77
+ console.log('Resource ranges:', envWithResources.resourcesRanges);
78
+ }
79
+ }
80
+ else {
81
+ console.log('No environments with explicit resource information found');
82
+ }
83
+ });
84
+ it('should include environment snippets if available', async () => {
85
+ console.log('Testing environment snippets...');
86
+ const response = await environments.listEnvironments(DATALAYER_TOKEN, BASE_URL);
87
+ // Check if any environment has snippets
88
+ const envWithSnippets = response.environments.find(env => env.snippets && env.snippets.length > 0);
89
+ if (envWithSnippets) {
90
+ console.log('Found environment with snippets:', envWithSnippets.title);
91
+ console.log('Number of snippets:', envWithSnippets.snippets?.length);
92
+ const firstSnippet = envWithSnippets.snippets[0];
93
+ expect(firstSnippet).toHaveProperty('title');
94
+ // Description might be optional
95
+ if (firstSnippet.description) {
96
+ expect(firstSnippet).toHaveProperty('description');
97
+ }
98
+ expect(firstSnippet).toHaveProperty('code');
99
+ }
100
+ else {
101
+ console.log('No environments with snippets found');
102
+ }
103
+ });
104
+ });
105
+ describe('error handling', () => {
106
+ it('should handle invalid token gracefully', async () => {
107
+ console.log('Testing with invalid token...');
108
+ const invalidToken = 'invalid-token-123';
109
+ try {
110
+ await environments.listEnvironments(invalidToken, BASE_URL);
111
+ // If we get here, the API accepted the invalid token (shouldn't happen)
112
+ console.log('WARNING: API accepted invalid token');
113
+ }
114
+ catch (error) {
115
+ console.log('Error with invalid token:', error.message);
116
+ // We expect an error with invalid token
117
+ expect(error).toBeDefined();
118
+ expect(error.message).toBeDefined();
119
+ }
120
+ });
121
+ });
122
+ });
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { describe, it, expect } from 'vitest';
6
+ import { healthz } from '../runtimes';
7
+ import { testConfig, skipIfNoToken } from '../../__tests__/shared/test-config';
8
+ /**
9
+ * Integration tests for Runtimes health check API
10
+ * These tests run against the actual Datalayer Runtimes API
11
+ */
12
+ describe('Runtimes Healthz Integration Tests', () => {
13
+ describe.skipIf(skipIfNoToken())('ping endpoint', () => {
14
+ it('should successfully ping the Runtimes service', async () => {
15
+ console.log('Testing health check ping endpoint for Runtimes...');
16
+ const response = await healthz.ping(testConfig.getBaseUrl('RUNTIMES'));
17
+ // Log response for debugging
18
+ console.log('Ping response:', JSON.stringify(response, null, 2));
19
+ // Verify response structure
20
+ expect(response).toBeDefined();
21
+ expect(response.success).toBe(true);
22
+ expect(response.message).toBeDefined();
23
+ // Log success
24
+ console.log('Runtimes health check successful');
25
+ console.log('Success:', response.success);
26
+ console.log('Message:', response.message);
27
+ if (response.status) {
28
+ console.log('Status:', response.status.status);
29
+ }
30
+ if (response.version) {
31
+ console.log('Version:', response.version);
32
+ }
33
+ });
34
+ it('should work with default URL if not specified', async () => {
35
+ console.log('Testing health check with default URL...');
36
+ // Use default URL (should use production)
37
+ const response = await healthz.ping();
38
+ expect(response).toBeDefined();
39
+ expect(response.success).toBe(true);
40
+ expect(response.message).toBeDefined();
41
+ console.log('Successfully pinged Runtimes service with default URL');
42
+ });
43
+ it('should fail with invalid URL', async () => {
44
+ console.log('Testing health check with invalid URL...');
45
+ const invalidUrl = 'https://invalid.datalayer.run';
46
+ await expect(healthz.ping(invalidUrl)).rejects.toThrow('Health check failed');
47
+ console.log('Correctly failed with invalid URL');
48
+ });
49
+ });
50
+ });
@@ -0,0 +1 @@
1
+ export {};