@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.
- package/lib/__tests__/shared/cleanup-shared.d.ts +4 -0
- package/lib/__tests__/shared/cleanup-shared.js +228 -0
- package/lib/__tests__/shared/test-config.d.ts +51 -0
- package/lib/__tests__/shared/test-config.js +110 -0
- package/lib/__tests__/shared/test-constants.d.ts +66 -0
- package/lib/__tests__/shared/test-constants.js +79 -0
- package/lib/api/DatalayerApi.d.ts +1 -1
- package/lib/api/DatalayerApi.js +73 -42
- package/lib/api/__tests__/iam.authentication.integration.test.d.ts +1 -0
- package/lib/api/__tests__/iam.authentication.integration.test.js +247 -0
- package/lib/api/__tests__/iam.healthz.integration.test.d.ts +1 -0
- package/lib/api/__tests__/iam.healthz.integration.test.js +63 -0
- package/lib/api/__tests__/iam.profile.integration.test.d.ts +1 -0
- package/lib/api/__tests__/iam.profile.integration.test.js +252 -0
- package/lib/api/__tests__/runtimes.environments.integration.test.d.ts +1 -0
- package/lib/api/__tests__/runtimes.environments.integration.test.js +122 -0
- package/lib/api/__tests__/runtimes.healthz.integration.test.d.ts +1 -0
- package/lib/api/__tests__/runtimes.healthz.integration.test.js +50 -0
- package/lib/api/__tests__/runtimes.integration.test.d.ts +1 -0
- package/lib/api/__tests__/runtimes.integration.test.js +369 -0
- package/lib/api/__tests__/spacer.healthz.integration.test.d.ts +1 -0
- package/lib/api/__tests__/spacer.healthz.integration.test.js +50 -0
- package/lib/api/__tests__/spacer.integration.test.d.ts +1 -0
- package/lib/api/__tests__/spacer.integration.test.js +519 -0
- package/lib/api/constants.d.ts +19 -0
- package/lib/api/constants.js +23 -0
- package/lib/api/iam/__tests__/authentication.unit.test.d.ts +1 -0
- package/lib/api/iam/__tests__/authentication.unit.test.js +63 -0
- package/lib/api/iam/__tests__/healthz.unit.test.d.ts +1 -0
- package/lib/api/iam/__tests__/healthz.unit.test.js +60 -0
- package/lib/api/iam/__tests__/profile.unit.test.d.ts +1 -0
- package/lib/api/iam/__tests__/profile.unit.test.js +57 -0
- package/lib/api/iam/authentication.d.ts +40 -0
- package/lib/api/iam/authentication.js +128 -0
- package/lib/api/iam/healthz.d.ts +15 -0
- package/lib/api/iam/healthz.js +43 -0
- package/lib/api/iam/index.d.ts +12 -0
- package/lib/api/iam/index.js +17 -0
- package/lib/api/iam/profile.d.ts +15 -0
- package/lib/api/iam/profile.js +41 -0
- package/lib/api/index.d.ts +20 -3
- package/lib/api/index.js +22 -3
- package/lib/api/runtimes/__tests__/environments.unit.test.d.ts +1 -0
- package/lib/api/runtimes/__tests__/environments.unit.test.js +77 -0
- package/lib/api/runtimes/__tests__/healthz.unit.test.d.ts +1 -0
- package/lib/api/runtimes/__tests__/healthz.unit.test.js +57 -0
- package/lib/api/runtimes/__tests__/runtimes.unit.test.d.ts +1 -0
- package/lib/api/runtimes/__tests__/runtimes.unit.test.js +139 -0
- package/lib/api/runtimes/__tests__/snapshots.unit.test.d.ts +1 -0
- package/lib/api/runtimes/__tests__/snapshots.unit.test.js +96 -0
- package/lib/api/runtimes/environments.d.ts +9 -0
- package/lib/api/runtimes/environments.js +28 -0
- package/lib/api/runtimes/healthz.d.ts +25 -0
- package/lib/api/runtimes/healthz.js +43 -0
- package/lib/api/runtimes/index.d.ts +10 -5
- package/lib/api/runtimes/index.js +10 -5
- package/lib/api/runtimes/runtimes.d.ts +54 -0
- package/lib/api/runtimes/runtimes.js +169 -0
- package/lib/api/runtimes/snapshots.d.ts +34 -21
- package/lib/api/runtimes/snapshots.js +69 -138
- package/lib/api/spacer/__tests__/healthz.unit.test.d.ts +1 -0
- package/lib/api/spacer/__tests__/healthz.unit.test.js +57 -0
- package/lib/api/spacer/__tests__/items.unit.test.d.ts +1 -0
- package/lib/api/spacer/__tests__/items.unit.test.js +165 -0
- package/lib/api/spacer/__tests__/lexicals.unit.test.d.ts +1 -0
- package/lib/api/spacer/__tests__/lexicals.unit.test.js +323 -0
- package/lib/api/spacer/__tests__/notebooks.unit.test.d.ts +1 -0
- package/lib/api/spacer/__tests__/notebooks.unit.test.js +224 -0
- package/lib/api/spacer/__tests__/users.unit.test.d.ts +1 -0
- package/lib/api/spacer/__tests__/users.unit.test.js +132 -0
- package/lib/api/spacer/healthz.d.ts +25 -0
- package/lib/api/spacer/healthz.js +43 -0
- package/lib/api/spacer/index.d.ts +13 -0
- package/lib/api/spacer/index.js +17 -0
- package/lib/api/spacer/items.d.ts +17 -0
- package/lib/api/spacer/items.js +40 -0
- package/lib/api/spacer/lexicals.d.ts +26 -0
- package/lib/api/spacer/lexicals.js +74 -0
- package/lib/api/spacer/notebooks.d.ts +26 -0
- package/lib/api/spacer/notebooks.js +74 -0
- package/lib/api/spacer/spaces.d.ts +9 -0
- package/lib/api/spacer/spaces.js +29 -0
- package/lib/api/spacer/users.d.ts +9 -0
- package/lib/api/spacer/users.js +28 -0
- package/lib/api/types/iam.d.ts +180 -0
- package/lib/api/types/index.d.ts +32 -0
- package/lib/api/types/index.js +36 -0
- package/lib/api/types/runtimes.d.ts +235 -0
- package/lib/api/types/runtimes.js +5 -0
- package/lib/api/types/spacer.d.ts +271 -0
- package/lib/api/types/spacer.js +5 -0
- package/lib/api/utils/__tests__/validation.test.d.ts +1 -0
- package/lib/api/utils/__tests__/validation.test.js +109 -0
- package/lib/api/utils/validation.d.ts +24 -0
- package/lib/api/utils/validation.js +133 -0
- package/lib/components/progress/CreditsIndicator.d.ts +1 -1
- package/lib/components/runtimes/RuntimeCellVariablesDialog.js +1 -1
- package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +1 -1
- package/lib/components/runtimes/RuntimeLauncherDialog.js +2 -1
- package/lib/components/runtimes/RuntimePickerBase.d.ts +1 -1
- package/lib/components/runtimes/RuntimePickerBase.js +1 -1
- package/lib/components/runtimes/RuntimePickerCell.js +2 -1
- package/lib/components/runtimes/RuntimePickerNotebook.d.ts +1 -1
- package/lib/components/runtimes/RuntimePickerNotebook.js +1 -1
- package/lib/components/runtimes/RuntimeSimplePicker.js +2 -1
- package/lib/components/runtimes/RuntimeTransfer.d.ts +1 -1
- package/lib/components/runtimes/RuntimeUtils.d.ts +1 -1
- package/lib/components/snapshots/RuntimeSnapshotMenu.d.ts +1 -1
- package/lib/components/snapshots/RuntimeSnapshotMenu.js +1 -1
- package/lib/hooks/useDatalayer.d.ts +1 -1
- package/lib/hooks/useDatalayer.js +1 -1
- package/lib/hooks/useIAM.js +1 -1
- package/lib/hooks/useRuntimes.js +1 -1
- package/lib/index.d.ts +9 -0
- package/lib/index.js +10 -0
- package/lib/sdk/client/__tests__/sdk.health.integration.test.d.ts +1 -0
- package/lib/sdk/client/__tests__/sdk.health.integration.test.js +110 -0
- package/lib/sdk/client/__tests__/sdk.iam.integration.test.d.ts +1 -0
- package/lib/sdk/client/__tests__/sdk.iam.integration.test.js +179 -0
- package/lib/sdk/client/__tests__/sdk.models.integration.test.d.ts +1 -0
- package/lib/sdk/client/__tests__/sdk.models.integration.test.js +376 -0
- package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.d.ts +1 -0
- package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.js +276 -0
- package/lib/sdk/client/__tests__/sdk.spacer.integration.test.d.ts +1 -0
- package/lib/sdk/client/__tests__/sdk.spacer.integration.test.js +361 -0
- package/lib/sdk/client/base.d.ts +88 -0
- package/lib/sdk/client/base.js +112 -0
- package/lib/sdk/client/index.d.ts +192 -0
- package/lib/sdk/client/index.js +128 -0
- package/lib/sdk/client/mixins/HealthMixin.d.ts +100 -0
- package/lib/sdk/client/mixins/HealthMixin.js +133 -0
- package/lib/sdk/client/mixins/IAMMixin.d.ts +59 -0
- package/lib/sdk/client/mixins/IAMMixin.js +83 -0
- package/lib/sdk/client/mixins/RuntimesMixin.d.ts +134 -0
- package/lib/sdk/client/mixins/RuntimesMixin.js +221 -0
- package/lib/sdk/client/mixins/SpacerMixin.d.ts +184 -0
- package/lib/sdk/client/mixins/SpacerMixin.js +278 -0
- package/lib/sdk/client/models/Lexical.d.ts +156 -0
- package/lib/sdk/client/models/Lexical.js +275 -0
- package/lib/sdk/client/models/Notebook.d.ts +174 -0
- package/lib/sdk/client/models/Notebook.js +311 -0
- package/lib/sdk/client/models/Runtime.d.ts +221 -0
- package/lib/sdk/client/models/Runtime.js +341 -0
- package/lib/sdk/client/models/Snapshot.d.ts +156 -0
- package/lib/sdk/client/models/Snapshot.js +244 -0
- package/lib/sdk/client/models/Space.d.ts +182 -0
- package/lib/sdk/client/models/Space.js +276 -0
- package/lib/sdk/client/models/__tests__/Lexical.test.d.ts +1 -0
- package/lib/sdk/client/models/__tests__/Lexical.test.js +288 -0
- package/lib/sdk/client/models/__tests__/Notebook.test.d.ts +1 -0
- package/lib/sdk/client/models/__tests__/Notebook.test.js +206 -0
- package/lib/sdk/client/models/__tests__/Runtime.test.d.ts +1 -0
- package/lib/sdk/client/models/__tests__/Runtime.test.js +133 -0
- package/lib/sdk/client/models/__tests__/Snapshot.test.d.ts +1 -0
- package/lib/sdk/client/models/__tests__/Snapshot.test.js +244 -0
- package/lib/sdk/client/models/__tests__/Space.test.d.ts +1 -0
- package/lib/sdk/client/models/__tests__/Space.test.js +334 -0
- package/lib/sdk/client/models/index.d.ts +30 -0
- package/lib/sdk/client/models/index.js +30 -0
- package/lib/sdk/client/utils/mixins.d.ts +42 -0
- package/lib/sdk/client/utils/mixins.js +47 -0
- package/lib/sdk/index.d.ts +26 -0
- package/lib/sdk/index.js +32 -0
- package/lib/sdk/stateful/index.d.ts +3 -0
- package/lib/sdk/stateful/index.js +7 -0
- package/lib/{api → sdk/stateful}/runtimes/actions.d.ts +1 -1
- package/lib/{api → sdk/stateful}/runtimes/actions.js +3 -3
- package/lib/{api → sdk/stateful}/runtimes/apis.d.ts +1 -1
- package/lib/sdk/stateful/runtimes/apis.js +5 -0
- package/lib/sdk/stateful/runtimes/index.d.ts +5 -0
- package/lib/sdk/stateful/runtimes/index.js +9 -0
- package/lib/sdk/stateful/runtimes/snapshots.d.ts +25 -0
- package/lib/sdk/stateful/runtimes/snapshots.js +150 -0
- package/lib/services/DatalayerServiceManager.js +1 -1
- package/lib/state/substates/IAMState.js +1 -1
- package/lib/state/substates/RuntimesState.d.ts +1 -1
- package/lib/state/substates/RuntimesState.js +1 -1
- package/lib/state/substates/SurveysState.js +1 -1
- package/lib/test-setup.js +1 -0
- package/package.json +19 -9
- /package/lib/api/{runtimes/apis.js → types/iam.js} +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/Python.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/Python.js +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/Snippets.js +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/index.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/exec/index.js +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/index.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/index.js +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/jupyter/kernelsHandler.js +0 -0
- /package/lib/{api → sdk/stateful}/runtimes/settings.d.ts +0 -0
- /package/lib/{api → sdk/stateful}/runtimes/settings.js +0 -0
- /package/lib/{api → sdk/stateful}/runtimes/utils.d.ts +0 -0
- /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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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 {};
|