@datalayer/core 0.0.12 → 0.0.13
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/README.md +2 -2
- package/lib/api/DatalayerApi.d.ts +38 -26
- package/lib/api/DatalayerApi.js +35 -8
- package/lib/api/iam/authentication.d.ts +8 -7
- package/lib/api/iam/authentication.js +14 -15
- package/lib/api/iam/healthz.d.ts +3 -2
- package/lib/api/iam/healthz.js +5 -3
- package/lib/api/iam/index.d.ts +9 -4
- package/lib/api/iam/index.js +9 -4
- package/lib/api/iam/oauth2.d.ts +115 -0
- package/lib/api/iam/oauth2.js +309 -0
- package/lib/api/iam/profile.d.ts +8 -1
- package/lib/api/iam/profile.js +17 -2
- package/lib/api/iam/usage.d.ts +56 -0
- package/lib/api/iam/usage.js +39 -0
- package/lib/api/index.d.ts +6 -5
- package/lib/api/index.js +6 -5
- package/lib/api/runtimes/environments.js +3 -2
- package/lib/api/runtimes/healthz.d.ts +3 -13
- package/lib/api/runtimes/healthz.js +4 -3
- package/lib/api/runtimes/index.d.ts +3 -2
- package/lib/api/runtimes/index.js +3 -2
- package/lib/api/runtimes/runtimes.js +17 -6
- package/lib/api/runtimes/snapshots.js +3 -2
- package/lib/api/spacer/documents.d.ts +12 -0
- package/lib/api/spacer/documents.js +43 -0
- package/lib/api/spacer/healthz.d.ts +3 -13
- package/lib/api/spacer/healthz.js +4 -3
- package/lib/api/spacer/index.d.ts +4 -2
- package/lib/api/spacer/index.js +4 -2
- package/lib/api/spacer/items.d.ts +9 -1
- package/lib/api/spacer/items.js +17 -2
- package/lib/api/spacer/lexicals.js +3 -2
- package/lib/api/spacer/notebooks.js +3 -2
- package/lib/api/spacer/spaces.js +3 -2
- package/lib/api/spacer/users.js +3 -2
- package/lib/api/types/common.d.ts +64 -0
- package/lib/api/types/iam.d.ts +88 -65
- package/lib/api/types/index.d.ts +4 -2
- package/lib/api/types/index.js +4 -2
- package/lib/api/types/runtimes.d.ts +9 -39
- package/lib/api/types/spacer.d.ts +37 -65
- package/lib/api/utils/validation.d.ts +24 -1
- package/lib/api/utils/validation.js +62 -1
- package/lib/client/base.d.ts +75 -0
- package/lib/client/base.js +199 -0
- package/lib/client/constants.d.ts +22 -0
- package/lib/client/constants.js +22 -0
- package/lib/client/index.d.ts +108 -0
- package/lib/client/index.js +79 -0
- package/lib/client/mixins/IAMMixin.d.ts +54 -0
- package/lib/client/mixins/IAMMixin.js +181 -0
- package/lib/client/mixins/RuntimesMixin.d.ts +93 -0
- package/lib/client/mixins/RuntimesMixin.js +229 -0
- package/lib/client/mixins/SpacerMixin.d.ts +111 -0
- package/lib/client/mixins/SpacerMixin.js +340 -0
- package/lib/client/models/Credits.d.ts +91 -0
- package/lib/client/models/Credits.js +130 -0
- package/lib/client/models/Environment.d.ts +73 -0
- package/lib/client/models/Environment.js +88 -0
- package/lib/client/models/HealthCheck.d.ts +72 -0
- package/lib/client/models/HealthCheck.js +107 -0
- package/lib/client/models/Item.d.ts +69 -0
- package/lib/client/models/Item.js +191 -0
- package/lib/client/models/Lexical.d.ts +83 -0
- package/lib/client/models/Lexical.js +152 -0
- package/lib/client/models/Notebook.d.ts +87 -0
- package/lib/client/models/Notebook.js +153 -0
- package/lib/client/models/Runtime.d.ts +122 -0
- package/lib/client/models/Runtime.js +204 -0
- package/lib/client/models/Snapshot.d.ts +92 -0
- package/lib/client/models/Snapshot.js +139 -0
- package/lib/client/models/Space.d.ts +135 -0
- package/lib/client/models/Space.js +234 -0
- package/lib/client/models/User.d.ts +64 -0
- package/lib/client/models/User.js +83 -0
- package/lib/client/models/index.d.ts +26 -0
- package/lib/client/models/index.js +25 -0
- package/lib/client/utils/mixins.d.ts +12 -0
- package/lib/{sdk/client → client}/utils/mixins.js +0 -28
- package/lib/client/utils/spacerUtils.d.ts +18 -0
- package/lib/client/utils/spacerUtils.js +32 -0
- package/lib/collaboration/DatalayerCollaboration.d.ts +6 -1
- package/lib/collaboration/DatalayerCollaboration.js +2 -2
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +5 -0
- package/lib/collaboration/DatalayerCollaborationProvider.js +10 -9
- 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/RuntimePickerBase.d.ts +1 -1
- package/lib/components/runtimes/RuntimePickerBase.js +1 -1
- package/lib/components/runtimes/RuntimePickerCell.js +2 -2
- package/lib/components/runtimes/RuntimePickerNotebook.d.ts +1 -1
- package/lib/components/runtimes/RuntimePickerNotebook.js +1 -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 +27 -20
- package/lib/config/Configuration.d.ts +8 -0
- package/lib/hooks/useDatalayer.js +1 -1
- package/lib/hooks/useRuntimes.js +1 -1
- package/lib/hooks/useToast.js +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +4 -2
- package/lib/sdk/index.d.ts +5 -4
- package/lib/sdk/index.js +6 -5
- package/lib/services/DatalayerServiceManager.js +1 -1
- package/lib/state/substates/CoreState.js +2 -0
- package/lib/state/substates/RuntimesState.d.ts +1 -1
- package/lib/state/substates/RuntimesState.js +1 -1
- package/lib/{sdk/stateful → stateful}/index.d.ts +1 -1
- package/lib/{sdk/stateful → stateful}/index.js +1 -1
- package/lib/{sdk/stateful → stateful}/jupyter/exec/Snippets.d.ts +1 -41
- package/lib/{sdk/stateful → stateful}/jupyter/exec/Snippets.js +1 -20
- package/lib/{sdk/stateful → stateful}/runtimes/actions.d.ts +3 -3
- package/lib/{sdk/stateful → stateful}/runtimes/actions.js +8 -8
- package/lib/{sdk/stateful → stateful}/runtimes/apis.d.ts +8 -8
- package/lib/stateful/runtimes/apis.js +5 -0
- package/package.json +12 -10
- package/lib/__tests__/hooks.test.d.ts +0 -1
- package/lib/__tests__/hooks.test.js +0 -19
- package/lib/__tests__/index.test.d.ts +0 -1
- package/lib/__tests__/index.test.js +0 -27
- package/lib/__tests__/integration.test.d.ts +0 -1
- package/lib/__tests__/integration.test.js +0 -57
- package/lib/__tests__/shared/cleanup-shared.d.ts +0 -4
- package/lib/__tests__/shared/cleanup-shared.js +0 -228
- package/lib/__tests__/shared/test-config.d.ts +0 -51
- package/lib/__tests__/shared/test-config.js +0 -110
- package/lib/__tests__/shared/test-constants.d.ts +0 -66
- package/lib/__tests__/shared/test-constants.js +0 -79
- package/lib/__tests__/utils.test.d.ts +0 -1
- package/lib/__tests__/utils.test.js +0 -59
- package/lib/api/__tests__/iam.authentication.integration.test.d.ts +0 -1
- package/lib/api/__tests__/iam.authentication.integration.test.js +0 -247
- package/lib/api/__tests__/iam.healthz.integration.test.d.ts +0 -1
- package/lib/api/__tests__/iam.healthz.integration.test.js +0 -63
- package/lib/api/__tests__/iam.profile.integration.test.d.ts +0 -1
- package/lib/api/__tests__/iam.profile.integration.test.js +0 -252
- package/lib/api/__tests__/runtimes.environments.integration.test.d.ts +0 -1
- package/lib/api/__tests__/runtimes.environments.integration.test.js +0 -122
- package/lib/api/__tests__/runtimes.healthz.integration.test.d.ts +0 -1
- package/lib/api/__tests__/runtimes.healthz.integration.test.js +0 -50
- package/lib/api/__tests__/runtimes.integration.test.d.ts +0 -1
- package/lib/api/__tests__/runtimes.integration.test.js +0 -369
- package/lib/api/__tests__/spacer.healthz.integration.test.d.ts +0 -1
- package/lib/api/__tests__/spacer.healthz.integration.test.js +0 -50
- package/lib/api/__tests__/spacer.integration.test.d.ts +0 -1
- package/lib/api/__tests__/spacer.integration.test.js +0 -519
- package/lib/api/iam/__tests__/authentication.unit.test.d.ts +0 -1
- package/lib/api/iam/__tests__/authentication.unit.test.js +0 -63
- package/lib/api/iam/__tests__/healthz.unit.test.d.ts +0 -1
- package/lib/api/iam/__tests__/healthz.unit.test.js +0 -60
- package/lib/api/iam/__tests__/profile.unit.test.d.ts +0 -1
- package/lib/api/iam/__tests__/profile.unit.test.js +0 -57
- package/lib/api/runtimes/__tests__/environments.unit.test.d.ts +0 -1
- package/lib/api/runtimes/__tests__/environments.unit.test.js +0 -77
- package/lib/api/runtimes/__tests__/healthz.unit.test.d.ts +0 -1
- package/lib/api/runtimes/__tests__/healthz.unit.test.js +0 -57
- package/lib/api/runtimes/__tests__/runtimes.unit.test.d.ts +0 -1
- package/lib/api/runtimes/__tests__/runtimes.unit.test.js +0 -139
- package/lib/api/runtimes/__tests__/snapshots.unit.test.d.ts +0 -1
- package/lib/api/runtimes/__tests__/snapshots.unit.test.js +0 -96
- package/lib/api/spacer/__tests__/healthz.unit.test.d.ts +0 -1
- package/lib/api/spacer/__tests__/healthz.unit.test.js +0 -57
- package/lib/api/spacer/__tests__/items.unit.test.d.ts +0 -1
- package/lib/api/spacer/__tests__/items.unit.test.js +0 -165
- package/lib/api/spacer/__tests__/lexicals.unit.test.d.ts +0 -1
- package/lib/api/spacer/__tests__/lexicals.unit.test.js +0 -323
- package/lib/api/spacer/__tests__/notebooks.unit.test.d.ts +0 -1
- package/lib/api/spacer/__tests__/notebooks.unit.test.js +0 -224
- package/lib/api/spacer/__tests__/users.unit.test.d.ts +0 -1
- package/lib/api/spacer/__tests__/users.unit.test.js +0 -132
- package/lib/api/utils/__tests__/validation.test.d.ts +0 -1
- package/lib/api/utils/__tests__/validation.test.js +0 -109
- package/lib/sdk/client/__tests__/sdk.health.integration.test.d.ts +0 -1
- package/lib/sdk/client/__tests__/sdk.health.integration.test.js +0 -110
- package/lib/sdk/client/__tests__/sdk.iam.integration.test.d.ts +0 -1
- package/lib/sdk/client/__tests__/sdk.iam.integration.test.js +0 -179
- package/lib/sdk/client/__tests__/sdk.models.integration.test.d.ts +0 -1
- package/lib/sdk/client/__tests__/sdk.models.integration.test.js +0 -376
- package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.d.ts +0 -1
- package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.js +0 -276
- package/lib/sdk/client/__tests__/sdk.spacer.integration.test.d.ts +0 -1
- package/lib/sdk/client/__tests__/sdk.spacer.integration.test.js +0 -361
- package/lib/sdk/client/base.d.ts +0 -88
- package/lib/sdk/client/base.js +0 -112
- package/lib/sdk/client/index.d.ts +0 -192
- package/lib/sdk/client/index.js +0 -128
- package/lib/sdk/client/mixins/HealthMixin.d.ts +0 -100
- package/lib/sdk/client/mixins/HealthMixin.js +0 -133
- package/lib/sdk/client/mixins/IAMMixin.d.ts +0 -59
- package/lib/sdk/client/mixins/IAMMixin.js +0 -83
- package/lib/sdk/client/mixins/RuntimesMixin.d.ts +0 -134
- package/lib/sdk/client/mixins/RuntimesMixin.js +0 -221
- package/lib/sdk/client/mixins/SpacerMixin.d.ts +0 -184
- package/lib/sdk/client/mixins/SpacerMixin.js +0 -278
- package/lib/sdk/client/models/Lexical.d.ts +0 -156
- package/lib/sdk/client/models/Lexical.js +0 -275
- package/lib/sdk/client/models/Notebook.d.ts +0 -174
- package/lib/sdk/client/models/Notebook.js +0 -311
- package/lib/sdk/client/models/Runtime.d.ts +0 -221
- package/lib/sdk/client/models/Runtime.js +0 -341
- package/lib/sdk/client/models/Snapshot.d.ts +0 -156
- package/lib/sdk/client/models/Snapshot.js +0 -244
- package/lib/sdk/client/models/Space.d.ts +0 -182
- package/lib/sdk/client/models/Space.js +0 -276
- package/lib/sdk/client/models/__tests__/Lexical.test.d.ts +0 -1
- package/lib/sdk/client/models/__tests__/Lexical.test.js +0 -288
- package/lib/sdk/client/models/__tests__/Notebook.test.d.ts +0 -1
- package/lib/sdk/client/models/__tests__/Notebook.test.js +0 -206
- package/lib/sdk/client/models/__tests__/Runtime.test.d.ts +0 -1
- package/lib/sdk/client/models/__tests__/Runtime.test.js +0 -133
- package/lib/sdk/client/models/__tests__/Snapshot.test.d.ts +0 -1
- package/lib/sdk/client/models/__tests__/Snapshot.test.js +0 -244
- package/lib/sdk/client/models/__tests__/Space.test.d.ts +0 -1
- package/lib/sdk/client/models/__tests__/Space.test.js +0 -334
- package/lib/sdk/client/models/index.d.ts +0 -30
- package/lib/sdk/client/models/index.js +0 -30
- package/lib/sdk/client/utils/mixins.d.ts +0 -42
- /package/lib/{sdk/stateful/runtimes/apis.js → api/types/common.js} +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/exec/Python.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/exec/Python.js +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/exec/index.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/exec/index.js +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/index.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/index.js +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/kernelsHandler.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/jupyter/kernelsHandler.js +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/index.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/index.js +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/settings.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/settings.js +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/snapshots.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/snapshots.js +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/utils.d.ts +0 -0
- /package/lib/{sdk/stateful → stateful}/runtimes/utils.js +0 -0
|
@@ -1,179 +0,0 @@
|
|
|
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 { DatalayerSDK } from '..';
|
|
7
|
-
import { testConfig } from '../../../__tests__/shared/test-config';
|
|
8
|
-
import { DEFAULT_SERVICE_URLS } from '../../../api/constants';
|
|
9
|
-
/**
|
|
10
|
-
* SDK IAM Integration Tests
|
|
11
|
-
*
|
|
12
|
-
* Tests authentication and identity management functionality
|
|
13
|
-
* using the SDK client.
|
|
14
|
-
*/
|
|
15
|
-
describe('SDK IAM Integration Tests', () => {
|
|
16
|
-
let sdk;
|
|
17
|
-
beforeAll(() => {
|
|
18
|
-
if (!testConfig.hasToken()) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
sdk = new DatalayerSDK({
|
|
22
|
-
token: testConfig.getToken(),
|
|
23
|
-
iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
|
|
24
|
-
runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
|
|
25
|
-
spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
describe.skipIf(!testConfig.hasToken())('IAM authentication methods', () => {
|
|
29
|
-
describe('whoami', () => {
|
|
30
|
-
it('should get current user profile', async () => {
|
|
31
|
-
console.log('Testing whoami...');
|
|
32
|
-
const user = await sdk.whoami();
|
|
33
|
-
expect(user).toBeDefined();
|
|
34
|
-
expect(user.id).toBeDefined();
|
|
35
|
-
expect(user.uid).toBeDefined();
|
|
36
|
-
expect(user.handle).toBeDefined();
|
|
37
|
-
expect(user.roles).toBeDefined();
|
|
38
|
-
expect(Array.isArray(user.roles)).toBe(true);
|
|
39
|
-
console.log('Current user:');
|
|
40
|
-
console.log(` ID: ${user.id}`);
|
|
41
|
-
console.log(` UID: ${user.uid}`);
|
|
42
|
-
console.log(` Handle: ${user.handle}`);
|
|
43
|
-
console.log(` Email: ${user.email || 'Not provided'}`);
|
|
44
|
-
console.log(` Name: ${user.first_name} ${user.last_name}`);
|
|
45
|
-
console.log(` Roles: ${user.roles.join(', ')}`);
|
|
46
|
-
});
|
|
47
|
-
it('should include organization info if available', async () => {
|
|
48
|
-
console.log('Checking organization info...');
|
|
49
|
-
const user = await sdk.whoami();
|
|
50
|
-
if (user.organizationIds &&
|
|
51
|
-
user.organizationIds.length > 0) {
|
|
52
|
-
console.log(`User belongs to ${user.organizationIds.length} organization(s)`);
|
|
53
|
-
expect(Array.isArray(user.organizationIds)).toBe(true);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
console.log('User does not belong to any organizations');
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
it('should cache user profile for performance', async () => {
|
|
60
|
-
console.log('Testing user profile caching...');
|
|
61
|
-
const start1 = Date.now();
|
|
62
|
-
const user1 = await sdk.whoami();
|
|
63
|
-
const time1 = Date.now() - start1;
|
|
64
|
-
const start2 = Date.now();
|
|
65
|
-
const user2 = await sdk.whoami();
|
|
66
|
-
const time2 = Date.now() - start2;
|
|
67
|
-
// Second call should be same or faster (cached)
|
|
68
|
-
expect(user2.id).toBe(user1.id);
|
|
69
|
-
console.log(`First call: ${time1}ms, Second call: ${time2}ms`);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
describe('login', () => {
|
|
73
|
-
it('should handle invalid credentials properly', async () => {
|
|
74
|
-
console.log('Testing login with invalid credentials...');
|
|
75
|
-
try {
|
|
76
|
-
await sdk.login({
|
|
77
|
-
handle: 'invalid@example.com',
|
|
78
|
-
password: 'wrong-password',
|
|
79
|
-
});
|
|
80
|
-
// Should not reach here
|
|
81
|
-
expect(true).toBe(false);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
expect(error).toBeDefined();
|
|
85
|
-
console.log('Invalid login rejected correctly');
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
it('should validate login request structure', async () => {
|
|
89
|
-
console.log('Testing login validation...');
|
|
90
|
-
try {
|
|
91
|
-
// Missing required fields
|
|
92
|
-
await sdk.login({});
|
|
93
|
-
expect(true).toBe(false);
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
expect(error).toBeDefined();
|
|
97
|
-
console.log('Invalid login request rejected');
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
describe('token management', () => {
|
|
102
|
-
it('should include token in all API requests', async () => {
|
|
103
|
-
console.log('Verifying token is included in requests...');
|
|
104
|
-
// Make a request and verify it succeeds (which means token was included)
|
|
105
|
-
const user = await sdk.whoami();
|
|
106
|
-
expect(user).toBeDefined();
|
|
107
|
-
// Verify token is stored in SDK
|
|
108
|
-
const token = sdk.getToken();
|
|
109
|
-
expect(token).toBe(testConfig.getToken());
|
|
110
|
-
console.log('Token management verified');
|
|
111
|
-
});
|
|
112
|
-
it('should handle expired tokens gracefully', async () => {
|
|
113
|
-
console.log('Testing expired token handling...');
|
|
114
|
-
const expiredSdk = new DatalayerSDK({
|
|
115
|
-
token: 'expired.invalid.token',
|
|
116
|
-
iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
|
|
117
|
-
runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
|
|
118
|
-
spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
|
|
119
|
-
});
|
|
120
|
-
try {
|
|
121
|
-
await expiredSdk.whoami();
|
|
122
|
-
expect(true).toBe(false);
|
|
123
|
-
}
|
|
124
|
-
catch (error) {
|
|
125
|
-
expect(error).toBeDefined();
|
|
126
|
-
console.log('Expired token rejected correctly');
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
describe('logout', () => {
|
|
131
|
-
it('should handle logout operation', async () => {
|
|
132
|
-
console.log('Testing logout...');
|
|
133
|
-
// Create a separate SDK instance for logout test
|
|
134
|
-
const logoutSdk = new DatalayerSDK({
|
|
135
|
-
token: testConfig.getToken(),
|
|
136
|
-
iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
|
|
137
|
-
runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
|
|
138
|
-
spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
|
|
139
|
-
});
|
|
140
|
-
// Verify we can make authenticated requests
|
|
141
|
-
const userBefore = await logoutSdk.whoami();
|
|
142
|
-
expect(userBefore).toBeDefined();
|
|
143
|
-
// Note: Actual logout may not invalidate the token server-side
|
|
144
|
-
// This tests the logout method exists and can be called
|
|
145
|
-
await logoutSdk.logout();
|
|
146
|
-
console.log('Logout completed');
|
|
147
|
-
// In a real scenario, subsequent requests might fail
|
|
148
|
-
// But with API tokens, they typically remain valid until expiry
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
describe('error handling', () => {
|
|
152
|
-
it('should provide clear error messages for auth failures', async () => {
|
|
153
|
-
console.log('Testing auth error messages...');
|
|
154
|
-
const invalidSdk = new DatalayerSDK({
|
|
155
|
-
token: 'invalid-token',
|
|
156
|
-
iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
|
|
157
|
-
runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
|
|
158
|
-
spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
|
|
159
|
-
});
|
|
160
|
-
try {
|
|
161
|
-
await invalidSdk.whoami();
|
|
162
|
-
expect(true).toBe(false);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
expect(error.message).toBeDefined();
|
|
166
|
-
// Error should mention authentication, token, or invalid
|
|
167
|
-
const errorLower = error.message.toLowerCase();
|
|
168
|
-
expect(errorLower.includes('auth') ||
|
|
169
|
-
errorLower.includes('unauth') ||
|
|
170
|
-
errorLower.includes('401') ||
|
|
171
|
-
errorLower.includes('403') ||
|
|
172
|
-
errorLower.includes('invalid') ||
|
|
173
|
-
errorLower.includes('token')).toBe(true);
|
|
174
|
-
console.log('Auth error message is clear and helpful');
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,376 +0,0 @@
|
|
|
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, afterAll } from 'vitest';
|
|
6
|
-
import { DatalayerSDK } from '..';
|
|
7
|
-
import { Runtime } from '../models/Runtime';
|
|
8
|
-
import { Snapshot } from '../models/Snapshot';
|
|
9
|
-
import { Notebook } from '../models/Notebook';
|
|
10
|
-
import { Lexical } from '../models/Lexical';
|
|
11
|
-
import { testConfig } from '../../../__tests__/shared/test-config';
|
|
12
|
-
import { DEFAULT_SERVICE_URLS } from '../../../api/constants';
|
|
13
|
-
import { performCleanup } from '../../../__tests__/shared/cleanup-shared';
|
|
14
|
-
/**
|
|
15
|
-
* SDK Models Integration Tests
|
|
16
|
-
*
|
|
17
|
-
* Tests model state management, lazy loading, and relationships
|
|
18
|
-
* using the SDK client and model classes.
|
|
19
|
-
*/
|
|
20
|
-
describe('SDK Models Integration Tests', () => {
|
|
21
|
-
let sdk;
|
|
22
|
-
let testSpace = null;
|
|
23
|
-
let testNotebook = null;
|
|
24
|
-
let testLexical = null;
|
|
25
|
-
let testRuntime = null;
|
|
26
|
-
let testSnapshot = null;
|
|
27
|
-
beforeAll(async () => {
|
|
28
|
-
if (!testConfig.hasToken()) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
await performCleanup('setup');
|
|
32
|
-
sdk = new DatalayerSDK({
|
|
33
|
-
token: testConfig.getToken(),
|
|
34
|
-
iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
|
|
35
|
-
runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
|
|
36
|
-
spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
afterAll(async () => {
|
|
40
|
-
if (!testConfig.hasToken()) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
await performCleanup('teardown');
|
|
44
|
-
}, 30000);
|
|
45
|
-
describe.skipIf(!testConfig.hasToken())('Model state management', () => {
|
|
46
|
-
it('should mark models as deleted after deletion', async () => {
|
|
47
|
-
console.log('Testing model deletion state...');
|
|
48
|
-
// Get a space to work with
|
|
49
|
-
const spaces = await sdk.getMySpaces();
|
|
50
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
51
|
-
testSpace = spaces[0];
|
|
52
|
-
// Create a notebook
|
|
53
|
-
const notebook = await sdk.createNotebook({
|
|
54
|
-
spaceId: testSpace.uid,
|
|
55
|
-
notebookType: 'jupyter',
|
|
56
|
-
name: 'model-test-notebook-' + Date.now(),
|
|
57
|
-
description: 'Test notebook for model tests',
|
|
58
|
-
});
|
|
59
|
-
expect(notebook).toBeInstanceOf(Notebook);
|
|
60
|
-
// Delete it
|
|
61
|
-
await notebook.delete();
|
|
62
|
-
// Verify it's marked as deleted
|
|
63
|
-
expect(notebook.isDeleted).toBe(true);
|
|
64
|
-
// Verify methods throw errors
|
|
65
|
-
try {
|
|
66
|
-
await notebook.getName();
|
|
67
|
-
expect(true).toBe(false); // Should not reach here
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
expect(error.message).toContain('deleted');
|
|
71
|
-
console.log('Deleted model correctly throws error');
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
it('should handle lazy loading of model properties', async () => {
|
|
75
|
-
if (!testSpace) {
|
|
76
|
-
throw new Error('Test dependency failed: testSpace should be available from previous test');
|
|
77
|
-
}
|
|
78
|
-
console.log('Testing lazy loading...');
|
|
79
|
-
// Create a notebook with minimal data
|
|
80
|
-
testNotebook = await sdk.createNotebook({
|
|
81
|
-
spaceId: testSpace.uid,
|
|
82
|
-
notebookType: 'jupyter',
|
|
83
|
-
name: 'lazy-load-test-' + Date.now(),
|
|
84
|
-
description: 'Test description',
|
|
85
|
-
});
|
|
86
|
-
// First call should fetch from API
|
|
87
|
-
const name1 = await testNotebook.getName();
|
|
88
|
-
expect(name1).toBeDefined();
|
|
89
|
-
// Second call should use cached value (faster)
|
|
90
|
-
const start = Date.now();
|
|
91
|
-
const name2 = await testNotebook.getName();
|
|
92
|
-
const elapsed = Date.now() - start;
|
|
93
|
-
expect(name2).toBe(name1);
|
|
94
|
-
expect(elapsed).toBeLessThan(10); // Should be instant
|
|
95
|
-
console.log(`Lazy loading working - cached access in ${elapsed}ms`);
|
|
96
|
-
});
|
|
97
|
-
it('should refresh data when explicitly requested', async () => {
|
|
98
|
-
// Ensure we have a space to work with
|
|
99
|
-
if (!testSpace) {
|
|
100
|
-
const spaces = await sdk.getMySpaces();
|
|
101
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
102
|
-
testSpace = spaces[0];
|
|
103
|
-
}
|
|
104
|
-
// Create a notebook if we don't have one
|
|
105
|
-
if (!testNotebook) {
|
|
106
|
-
testNotebook = await sdk.createNotebook({
|
|
107
|
-
spaceId: testSpace.uid,
|
|
108
|
-
notebookType: 'jupyter',
|
|
109
|
-
name: 'refresh-test-' + Date.now(),
|
|
110
|
-
description: 'Test description',
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
console.log('Testing data refresh...');
|
|
114
|
-
// Get initial name
|
|
115
|
-
const originalName = await testNotebook.getName();
|
|
116
|
-
expect(originalName).toBeDefined();
|
|
117
|
-
// Test that we can fetch fresh data
|
|
118
|
-
const content = await testNotebook.getContent();
|
|
119
|
-
expect(content).toBeDefined();
|
|
120
|
-
// Verify the model is working properly
|
|
121
|
-
const uid = testNotebook.uid;
|
|
122
|
-
expect(uid).toBeDefined();
|
|
123
|
-
console.log(`Model data access verified - name: ${originalName}, uid: ${uid}`);
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
describe.skipIf(!testConfig.hasToken())('Model relationships', () => {
|
|
127
|
-
it('should handle Space → Notebook relationship', async () => {
|
|
128
|
-
// Ensure we have a space
|
|
129
|
-
if (!testSpace) {
|
|
130
|
-
const spaces = await sdk.getMySpaces();
|
|
131
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
132
|
-
testSpace = spaces[0];
|
|
133
|
-
}
|
|
134
|
-
// Ensure we have a notebook
|
|
135
|
-
if (!testNotebook) {
|
|
136
|
-
testNotebook = await sdk.createNotebook({
|
|
137
|
-
spaceId: testSpace.uid,
|
|
138
|
-
notebookType: 'jupyter',
|
|
139
|
-
name: 'relationship-test-' + Date.now(),
|
|
140
|
-
description: 'Test notebook for relationships',
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
console.log('Testing Space → Notebook relationship...');
|
|
144
|
-
// Get items from space
|
|
145
|
-
const items = await testSpace.getItems();
|
|
146
|
-
expect(Array.isArray(items)).toBe(true);
|
|
147
|
-
console.log(`Space has ${items.length} items`);
|
|
148
|
-
console.log('Looking for notebook with id:', testNotebook.id);
|
|
149
|
-
console.log('Items in space:', items.map(item => ({
|
|
150
|
-
id: item.id,
|
|
151
|
-
uid: item.uid,
|
|
152
|
-
type: item.type || item.type,
|
|
153
|
-
name: item.name,
|
|
154
|
-
})));
|
|
155
|
-
// Our test notebook should be in the items
|
|
156
|
-
// Note: Space items may not have a 'type' property
|
|
157
|
-
const foundNotebook = items.find(item => item.id === testNotebook.id ||
|
|
158
|
-
item.uid === testNotebook.uid);
|
|
159
|
-
expect(foundNotebook).toBeDefined();
|
|
160
|
-
console.log(`Found notebook ${testNotebook.id} in space items`);
|
|
161
|
-
console.log(`Space contains ${items.length} items`);
|
|
162
|
-
});
|
|
163
|
-
it('should handle Space → Lexical relationship', async () => {
|
|
164
|
-
// Ensure we have a space
|
|
165
|
-
if (!testSpace) {
|
|
166
|
-
const spaces = await sdk.getMySpaces();
|
|
167
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
168
|
-
testSpace = spaces[0];
|
|
169
|
-
}
|
|
170
|
-
console.log('Testing Space → Lexical relationship...');
|
|
171
|
-
// Create a lexical document
|
|
172
|
-
testLexical = await sdk.createLexical({
|
|
173
|
-
spaceId: testSpace.uid,
|
|
174
|
-
name: 'relationship-test-lexical-' + Date.now(),
|
|
175
|
-
documentType: 'document',
|
|
176
|
-
description: 'Test lexical document for relationships',
|
|
177
|
-
});
|
|
178
|
-
expect(testLexical).toBeInstanceOf(Lexical);
|
|
179
|
-
// Verify it appears in space items
|
|
180
|
-
const items = await testSpace.getItems();
|
|
181
|
-
const foundLexical = items.find(item => item.id === testLexical.id || item.uid === testLexical.uid);
|
|
182
|
-
expect(foundLexical).toBeDefined();
|
|
183
|
-
console.log(`Created lexical ${testLexical.id} in space`);
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
describe.skipIf(!testConfig.hasToken() || testConfig.shouldSkipExpensive())('Runtime → Snapshot relationship', () => {
|
|
187
|
-
it('should handle Runtime → Snapshot creation', async () => {
|
|
188
|
-
console.log('Testing Runtime → Snapshot relationship...');
|
|
189
|
-
// Create a runtime
|
|
190
|
-
testRuntime = await sdk.createRuntime({
|
|
191
|
-
environment_name: 'python-cpu-env',
|
|
192
|
-
type: 'notebook',
|
|
193
|
-
given_name: 'model-test-runtime',
|
|
194
|
-
credits_limit: 10,
|
|
195
|
-
});
|
|
196
|
-
expect(testRuntime).toBeInstanceOf(Runtime);
|
|
197
|
-
console.log(`Created runtime: ${testRuntime.podName}`);
|
|
198
|
-
// Create a snapshot from the runtime
|
|
199
|
-
testSnapshot = await testRuntime.createSnapshot('model-test-snapshot', 'Test snapshot from model test');
|
|
200
|
-
expect(testSnapshot).toBeInstanceOf(Snapshot);
|
|
201
|
-
// Snapshots don't have a podName property
|
|
202
|
-
// Instead, check that the snapshot was created successfully
|
|
203
|
-
expect(testSnapshot.uid).toBeDefined();
|
|
204
|
-
expect(testSnapshot.name).toBe('model-test-snapshot');
|
|
205
|
-
console.log(`Created snapshot ${testSnapshot.uid} from runtime`);
|
|
206
|
-
});
|
|
207
|
-
it('should list runtime snapshots', async () => {
|
|
208
|
-
if (!testRuntime || !testSnapshot) {
|
|
209
|
-
throw new Error('Test dependency failed: testRuntime and testSnapshot should be available from previous test');
|
|
210
|
-
}
|
|
211
|
-
console.log('Testing runtime snapshot listing...');
|
|
212
|
-
// List all snapshots
|
|
213
|
-
const snapshots = await sdk.listSnapshots();
|
|
214
|
-
// Find our test snapshot
|
|
215
|
-
const found = snapshots.find(s => s.uid === testSnapshot.uid);
|
|
216
|
-
expect(found).toBeDefined();
|
|
217
|
-
console.log(`Found ${snapshots.length} snapshots total`);
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
describe.skipIf(!testConfig.hasToken())('Model serialization', () => {
|
|
221
|
-
it('should serialize Space model to JSON', async () => {
|
|
222
|
-
if (!testSpace) {
|
|
223
|
-
throw new Error('Test dependency failed: testSpace should be available from previous test');
|
|
224
|
-
}
|
|
225
|
-
console.log('Testing Space serialization...');
|
|
226
|
-
const json = await testSpace.toJSON();
|
|
227
|
-
expect(json).toBeDefined();
|
|
228
|
-
expect(json.id || json.uid).toBeDefined();
|
|
229
|
-
// JSON should include fetched properties
|
|
230
|
-
if (testSpace.name) {
|
|
231
|
-
expect(json.name).toBe(testSpace.name);
|
|
232
|
-
}
|
|
233
|
-
console.log('Space serialized successfully');
|
|
234
|
-
});
|
|
235
|
-
it('should serialize Notebook model to JSON', async () => {
|
|
236
|
-
// Always create a fresh notebook for this test to avoid state issues
|
|
237
|
-
// Ensure we have a space first
|
|
238
|
-
if (!testSpace) {
|
|
239
|
-
const spaces = await sdk.getMySpaces();
|
|
240
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
241
|
-
testSpace = spaces[0];
|
|
242
|
-
}
|
|
243
|
-
const freshNotebook = await sdk.createNotebook({
|
|
244
|
-
spaceId: testSpace.uid,
|
|
245
|
-
notebookType: 'jupyter',
|
|
246
|
-
name: 'serialization-test-' + Date.now(),
|
|
247
|
-
description: 'Test notebook for serialization',
|
|
248
|
-
});
|
|
249
|
-
console.log('Testing Notebook serialization...');
|
|
250
|
-
console.log('Notebook created with id:', freshNotebook.id);
|
|
251
|
-
const json = await freshNotebook.toJSON();
|
|
252
|
-
expect(json).toBeDefined();
|
|
253
|
-
expect(json.id).toBe(freshNotebook.id);
|
|
254
|
-
// Log the JSON to see what fields are present
|
|
255
|
-
console.log('Notebook JSON:', JSON.stringify(json, null, 2));
|
|
256
|
-
// The notebook should have its basic properties
|
|
257
|
-
// The name might be in name, name_t, or notebook_name_s
|
|
258
|
-
const name = json.name || json.name_t || json.notebook_name_s;
|
|
259
|
-
expect(name).toBeDefined();
|
|
260
|
-
expect(json.id).toBeDefined();
|
|
261
|
-
expect(json.uid).toBeDefined();
|
|
262
|
-
console.log('Notebook serialized successfully');
|
|
263
|
-
});
|
|
264
|
-
it.skipIf(testConfig.shouldSkipExpensive())('should serialize Runtime model to JSON', async () => {
|
|
265
|
-
if (!testRuntime) {
|
|
266
|
-
throw new Error('Test dependency failed: testRuntime should be available from previous test');
|
|
267
|
-
}
|
|
268
|
-
console.log('Testing Runtime serialization...');
|
|
269
|
-
const json = await testRuntime.toJSON();
|
|
270
|
-
expect(json).toBeDefined();
|
|
271
|
-
expect(json.pod_name).toBe(testRuntime.podName);
|
|
272
|
-
expect(json.environment_name).toBe(testRuntime.environmentName);
|
|
273
|
-
console.log('Runtime serialized successfully');
|
|
274
|
-
});
|
|
275
|
-
it.skipIf(testConfig.shouldSkipExpensive())('should serialize Snapshot model to JSON', async () => {
|
|
276
|
-
if (!testSnapshot) {
|
|
277
|
-
throw new Error('Test dependency failed: testSnapshot should be available from previous test');
|
|
278
|
-
}
|
|
279
|
-
console.log('Testing Snapshot serialization...');
|
|
280
|
-
const json = await testSnapshot.toJSON();
|
|
281
|
-
expect(json).toBeDefined();
|
|
282
|
-
expect(json.uid).toBe(testSnapshot.uid);
|
|
283
|
-
console.log('Snapshot serialized successfully');
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
describe.skipIf(!testConfig.hasToken())('Model error handling', () => {
|
|
287
|
-
it('should handle API errors gracefully in models', async () => {
|
|
288
|
-
console.log('Testing model error handling...');
|
|
289
|
-
// Create a fake notebook with invalid ID
|
|
290
|
-
const fakeNotebook = new Notebook({ id: 'invalid-id', space_id: 'invalid-space' }, sdk);
|
|
291
|
-
try {
|
|
292
|
-
await fakeNotebook.getName();
|
|
293
|
-
expect(true).toBe(false); // Should not reach here
|
|
294
|
-
}
|
|
295
|
-
catch (error) {
|
|
296
|
-
expect(error).toBeDefined();
|
|
297
|
-
console.log('Model correctly propagates API errors');
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
it('should validate model operations', async () => {
|
|
301
|
-
if (!testNotebook) {
|
|
302
|
-
throw new Error('Test dependency failed: testNotebook should be available from previous test');
|
|
303
|
-
}
|
|
304
|
-
console.log('Testing model validation...');
|
|
305
|
-
try {
|
|
306
|
-
// Try to update with invalid data
|
|
307
|
-
await testNotebook.update({});
|
|
308
|
-
// This might succeed with empty update, which is okay
|
|
309
|
-
console.log('Empty update handled');
|
|
310
|
-
}
|
|
311
|
-
catch (error) {
|
|
312
|
-
console.log('Invalid update rejected');
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
it('should handle concurrent model operations', async () => {
|
|
316
|
-
if (!testNotebook) {
|
|
317
|
-
throw new Error('Test dependency failed: testNotebook should be available from previous test');
|
|
318
|
-
}
|
|
319
|
-
console.log('Testing concurrent model operations...');
|
|
320
|
-
// Make multiple concurrent requests
|
|
321
|
-
const promises = [
|
|
322
|
-
testNotebook.getName(),
|
|
323
|
-
testNotebook.getContent(),
|
|
324
|
-
testNotebook.getUpdatedAt(),
|
|
325
|
-
];
|
|
326
|
-
const results = await Promise.all(promises);
|
|
327
|
-
expect(results[0]).toBeDefined(); // name
|
|
328
|
-
expect(results[1]).toBeDefined(); // content
|
|
329
|
-
expect(results[2]).toBeInstanceOf(Date); // updatedAt
|
|
330
|
-
console.log('Concurrent operations completed successfully');
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
describe.skipIf(!testConfig.hasToken())('Model lifecycle', () => {
|
|
334
|
-
it('should support full model lifecycle', async () => {
|
|
335
|
-
// Ensure we have a space
|
|
336
|
-
if (!testSpace) {
|
|
337
|
-
const spaces = await sdk.getMySpaces();
|
|
338
|
-
expect(spaces.length).toBeGreaterThan(0);
|
|
339
|
-
testSpace = spaces[0];
|
|
340
|
-
}
|
|
341
|
-
console.log('Testing full model lifecycle...');
|
|
342
|
-
// 1. Create
|
|
343
|
-
const notebook = await sdk.createNotebook({
|
|
344
|
-
spaceId: testSpace.uid,
|
|
345
|
-
notebookType: 'jupyter',
|
|
346
|
-
name: 'lifecycle-test-' + Date.now(),
|
|
347
|
-
description: 'Lifecycle test notebook',
|
|
348
|
-
});
|
|
349
|
-
expect(notebook).toBeInstanceOf(Notebook);
|
|
350
|
-
console.log('1. Created notebook');
|
|
351
|
-
// 2. Read
|
|
352
|
-
const retrieved = await sdk.getNotebook(notebook.uid);
|
|
353
|
-
expect(retrieved.id).toBe(notebook.id);
|
|
354
|
-
console.log('2. Retrieved notebook');
|
|
355
|
-
// 3. Use methods to access properties
|
|
356
|
-
const name = await notebook.getName();
|
|
357
|
-
expect(name).toBeDefined();
|
|
358
|
-
const content = await notebook.getContent();
|
|
359
|
-
expect(content).toBeDefined();
|
|
360
|
-
console.log('3. Used notebook methods');
|
|
361
|
-
// 4. Delete
|
|
362
|
-
await notebook.delete();
|
|
363
|
-
expect(notebook.isDeleted).toBe(true);
|
|
364
|
-
console.log('4. Deleted notebook');
|
|
365
|
-
// 5. Verify deletion
|
|
366
|
-
try {
|
|
367
|
-
await notebook.getName();
|
|
368
|
-
expect(true).toBe(false);
|
|
369
|
-
}
|
|
370
|
-
catch (error) {
|
|
371
|
-
expect(error.message).toContain('deleted');
|
|
372
|
-
console.log('5. Verified deletion state');
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|