@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,244 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module sdk/client/models/__tests__/Snapshot.test
|
|
7
|
+
* @description Tests for the Snapshot domain model.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
10
|
+
import { Snapshot } from '../Snapshot';
|
|
11
|
+
import { snapshots } from '../../../../api/runtimes';
|
|
12
|
+
// Mock the snapshots API
|
|
13
|
+
vi.mock('../../../../api/runtimes', () => ({
|
|
14
|
+
snapshots: {
|
|
15
|
+
getSnapshot: vi.fn(),
|
|
16
|
+
deleteSnapshot: vi.fn(),
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
describe('Snapshot Model', () => {
|
|
20
|
+
const mockSnapshotData = {
|
|
21
|
+
uid: 'snapshot-123',
|
|
22
|
+
name: 'Test Snapshot',
|
|
23
|
+
description: 'Test snapshot description',
|
|
24
|
+
environment: 'python-cpu',
|
|
25
|
+
metadata: {
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
language_info: {
|
|
28
|
+
name: 'python',
|
|
29
|
+
version: '3.9',
|
|
30
|
+
},
|
|
31
|
+
custom_field: 'custom_value',
|
|
32
|
+
},
|
|
33
|
+
size: 1024000,
|
|
34
|
+
format: 'tar.gz',
|
|
35
|
+
format_version: '2.0',
|
|
36
|
+
status: 'ready',
|
|
37
|
+
updated_at: '2023-01-01T12:00:00Z',
|
|
38
|
+
};
|
|
39
|
+
let mockSDK;
|
|
40
|
+
let snapshot;
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
mockSDK = {
|
|
43
|
+
getToken: vi.fn().mockReturnValue('mock-token'),
|
|
44
|
+
getRuntimesRunUrl: vi
|
|
45
|
+
.fn()
|
|
46
|
+
.mockReturnValue('https://runtimes.example.com'),
|
|
47
|
+
createRuntime: vi.fn(),
|
|
48
|
+
};
|
|
49
|
+
snapshot = new Snapshot(mockSnapshotData, mockSDK);
|
|
50
|
+
vi.clearAllMocks();
|
|
51
|
+
});
|
|
52
|
+
describe('Static Properties', () => {
|
|
53
|
+
it('should return correct uid', () => {
|
|
54
|
+
expect(snapshot.uid).toBe('snapshot-123');
|
|
55
|
+
});
|
|
56
|
+
it('should return correct name', () => {
|
|
57
|
+
expect(snapshot.name).toBe('Test Snapshot');
|
|
58
|
+
});
|
|
59
|
+
it('should return correct description', () => {
|
|
60
|
+
expect(snapshot.description).toBe('Test snapshot description');
|
|
61
|
+
});
|
|
62
|
+
it('should return correct environment', () => {
|
|
63
|
+
expect(snapshot.environment).toBe('python-cpu');
|
|
64
|
+
});
|
|
65
|
+
it('should return correct format', () => {
|
|
66
|
+
expect(snapshot.format).toBe('tar.gz');
|
|
67
|
+
});
|
|
68
|
+
it('should return correct format version', () => {
|
|
69
|
+
expect(snapshot.formatVersion).toBe('2.0');
|
|
70
|
+
});
|
|
71
|
+
it('should return correct metadata', () => {
|
|
72
|
+
expect(snapshot.metadata).toEqual({
|
|
73
|
+
version: '1.0.0',
|
|
74
|
+
language_info: {
|
|
75
|
+
name: 'python',
|
|
76
|
+
version: '3.9',
|
|
77
|
+
},
|
|
78
|
+
custom_field: 'custom_value',
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
it('should return correct updated date', () => {
|
|
82
|
+
expect(snapshot.updatedAt).toEqual(new Date('2023-01-01T12:00:00Z'));
|
|
83
|
+
});
|
|
84
|
+
it('should handle missing optional fields gracefully', () => {
|
|
85
|
+
const minimalData = {
|
|
86
|
+
uid: 'snapshot-456',
|
|
87
|
+
name: 'Minimal Snapshot',
|
|
88
|
+
environment: 'python-gpu',
|
|
89
|
+
updated_at: '2023-01-01T10:00:00Z',
|
|
90
|
+
};
|
|
91
|
+
const minimalSnapshot = new Snapshot(minimalData, mockSDK);
|
|
92
|
+
expect(minimalSnapshot.description).toBe('');
|
|
93
|
+
expect(minimalSnapshot.format).toBe('');
|
|
94
|
+
expect(minimalSnapshot.formatVersion).toBe('');
|
|
95
|
+
expect(minimalSnapshot.metadata).toEqual({});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('Dynamic Methods', () => {
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
101
|
+
snapshot: { ...mockSnapshotData, status: 'processing' },
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
it('should fetch fresh status from API and update internal data', async () => {
|
|
105
|
+
const status = await snapshot.getStatus();
|
|
106
|
+
expect(status).toBe('processing');
|
|
107
|
+
expect(snapshots.getSnapshot).toHaveBeenCalledWith('mock-token', 'snapshot-123', 'https://runtimes.example.com');
|
|
108
|
+
});
|
|
109
|
+
it('should fetch fresh size from API', async () => {
|
|
110
|
+
const updatedSize = 2048000;
|
|
111
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
112
|
+
snapshot: { ...mockSnapshotData, size: updatedSize },
|
|
113
|
+
});
|
|
114
|
+
const size = await snapshot.getSize();
|
|
115
|
+
expect(size).toBe(updatedSize);
|
|
116
|
+
expect(snapshots.getSnapshot).toHaveBeenCalledWith('mock-token', 'snapshot-123', 'https://runtimes.example.com');
|
|
117
|
+
});
|
|
118
|
+
it('should fetch fresh metadata from API', async () => {
|
|
119
|
+
const updatedMetadata = { version: '2.0.0', new_field: 'new_value' };
|
|
120
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
121
|
+
snapshot: { ...mockSnapshotData, metadata: updatedMetadata },
|
|
122
|
+
});
|
|
123
|
+
const metadata = await snapshot.getLatestMetadata();
|
|
124
|
+
expect(metadata).toEqual(updatedMetadata);
|
|
125
|
+
});
|
|
126
|
+
it('should handle missing size gracefully', async () => {
|
|
127
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
128
|
+
snapshot: { ...mockSnapshotData, size: undefined },
|
|
129
|
+
});
|
|
130
|
+
const size = await snapshot.getSize();
|
|
131
|
+
expect(size).toBe(0);
|
|
132
|
+
});
|
|
133
|
+
it('should handle missing status gracefully', async () => {
|
|
134
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
135
|
+
snapshot: { ...mockSnapshotData, status: undefined },
|
|
136
|
+
});
|
|
137
|
+
const status = await snapshot.getStatus();
|
|
138
|
+
expect(status).toBe('unknown');
|
|
139
|
+
});
|
|
140
|
+
it('should update internal data when fetching dynamic properties', async () => {
|
|
141
|
+
const updatedData = {
|
|
142
|
+
...mockSnapshotData,
|
|
143
|
+
status: 'completed',
|
|
144
|
+
size: 3072000,
|
|
145
|
+
};
|
|
146
|
+
snapshots.getSnapshot.mockResolvedValue({
|
|
147
|
+
snapshot: updatedData,
|
|
148
|
+
});
|
|
149
|
+
await snapshot.getStatus();
|
|
150
|
+
const json = await snapshot.toJSON();
|
|
151
|
+
expect(json.status).toBe('completed');
|
|
152
|
+
expect(json.size).toBe(3072000);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe('Action Methods', () => {
|
|
156
|
+
it('should delete snapshot and mark as deleted', async () => {
|
|
157
|
+
snapshots.deleteSnapshot.mockResolvedValue(undefined);
|
|
158
|
+
await snapshot.delete();
|
|
159
|
+
expect(snapshots.deleteSnapshot).toHaveBeenCalledWith('mock-token', 'snapshot-123', 'https://runtimes.example.com');
|
|
160
|
+
// After deletion, accessing properties should throw error
|
|
161
|
+
expect(() => snapshot.uid).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
162
|
+
});
|
|
163
|
+
it('should restore runtime from snapshot', async () => {
|
|
164
|
+
const mockRuntime = {
|
|
165
|
+
podName: 'runtime-from-snapshot',
|
|
166
|
+
state: 'starting',
|
|
167
|
+
};
|
|
168
|
+
mockSDK.createRuntime.mockResolvedValue(mockRuntime);
|
|
169
|
+
const runtime = await snapshot.restore({
|
|
170
|
+
credits_limit: 150,
|
|
171
|
+
custom_config: 'value',
|
|
172
|
+
});
|
|
173
|
+
expect(mockSDK.createRuntime).toHaveBeenCalledWith({
|
|
174
|
+
environment_name: 'python-cpu',
|
|
175
|
+
from_snapshot: 'snapshot-123',
|
|
176
|
+
credits_limit: 150,
|
|
177
|
+
custom_config: 'value',
|
|
178
|
+
});
|
|
179
|
+
expect(runtime).toBe(mockRuntime);
|
|
180
|
+
});
|
|
181
|
+
it('should restore runtime with minimal config', async () => {
|
|
182
|
+
const mockRuntime = { podName: 'runtime-minimal', state: 'starting' };
|
|
183
|
+
mockSDK.createRuntime.mockResolvedValue(mockRuntime);
|
|
184
|
+
const runtime = await snapshot.restore();
|
|
185
|
+
expect(mockSDK.createRuntime).toHaveBeenCalledWith({
|
|
186
|
+
environment_name: 'python-cpu',
|
|
187
|
+
from_snapshot: 'snapshot-123',
|
|
188
|
+
});
|
|
189
|
+
expect(runtime).toBe(mockRuntime);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
describe('Utility Methods', () => {
|
|
193
|
+
it('should return JSON with fresh data', async () => {
|
|
194
|
+
const freshData = { ...mockSnapshotData, status: 'completed' };
|
|
195
|
+
snapshots.getSnapshot.mockResolvedValue({ snapshot: freshData });
|
|
196
|
+
const json = await snapshot.toJSON();
|
|
197
|
+
expect(json.status).toBe('completed');
|
|
198
|
+
expect(json.uid).toBe('snapshot-123');
|
|
199
|
+
});
|
|
200
|
+
it('should return string representation', () => {
|
|
201
|
+
expect(snapshot.toString()).toBe('Snapshot(snapshot-123, Test Snapshot)');
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
describe('Deletion State Management', () => {
|
|
205
|
+
beforeEach(async () => {
|
|
206
|
+
snapshots.deleteSnapshot.mockResolvedValue(undefined);
|
|
207
|
+
await snapshot.delete();
|
|
208
|
+
});
|
|
209
|
+
it('should throw error when accessing static properties after deletion', () => {
|
|
210
|
+
expect(() => snapshot.uid).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
211
|
+
expect(() => snapshot.name).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
212
|
+
expect(() => snapshot.description).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
213
|
+
expect(() => snapshot.environment).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
214
|
+
expect(() => snapshot.format).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
215
|
+
expect(() => snapshot.formatVersion).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
216
|
+
expect(() => snapshot.metadata).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
217
|
+
expect(() => snapshot.updatedAt).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
218
|
+
});
|
|
219
|
+
it('should throw error when calling dynamic methods after deletion', async () => {
|
|
220
|
+
await expect(snapshot.getStatus()).rejects.toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
221
|
+
await expect(snapshot.getSize()).rejects.toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
222
|
+
await expect(snapshot.getLatestMetadata()).rejects.toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
223
|
+
});
|
|
224
|
+
it('should throw error when calling action methods after deletion', async () => {
|
|
225
|
+
await expect(snapshot.restore()).rejects.toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
226
|
+
});
|
|
227
|
+
it('should throw error when calling utility methods after deletion', async () => {
|
|
228
|
+
await expect(snapshot.toJSON()).rejects.toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
229
|
+
expect(() => snapshot.toString()).toThrow('Snapshot snapshot-123 has been deleted and no longer exists');
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('Error Handling', () => {
|
|
233
|
+
it('should handle API errors gracefully in dynamic methods', async () => {
|
|
234
|
+
snapshots.getSnapshot.mockRejectedValue(new Error('API Error'));
|
|
235
|
+
await expect(snapshot.getStatus()).rejects.toThrow('API Error');
|
|
236
|
+
});
|
|
237
|
+
it('should handle missing snapshot in API response', async () => {
|
|
238
|
+
snapshots.getSnapshot.mockResolvedValue({ snapshot: null });
|
|
239
|
+
const status = await snapshot.getStatus();
|
|
240
|
+
// Should return the current status from internal data when API returns null
|
|
241
|
+
expect(status).toBe('ready');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module sdk/client/models/__tests__/Space.test
|
|
7
|
+
* @description Tests for the Space domain model.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
10
|
+
import { Space } from '../Space';
|
|
11
|
+
import { users, items } from '../../../../api/spacer';
|
|
12
|
+
import { Notebook } from '../Notebook';
|
|
13
|
+
import { Lexical } from '../Lexical';
|
|
14
|
+
// Mock the spacer API
|
|
15
|
+
vi.mock('../../../../api/spacer', () => ({
|
|
16
|
+
users: {
|
|
17
|
+
getMySpaces: vi.fn(),
|
|
18
|
+
},
|
|
19
|
+
items: {
|
|
20
|
+
getSpaceItems: vi.fn(),
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
describe('Space Model', () => {
|
|
24
|
+
const mockSpaceData = {
|
|
25
|
+
uid: 'space-uid-123',
|
|
26
|
+
id: 'space-123',
|
|
27
|
+
name: 'Research Workspace',
|
|
28
|
+
name_t: 'Research Workspace',
|
|
29
|
+
handle_s: 'research-workspace',
|
|
30
|
+
variant_s: 'default',
|
|
31
|
+
description: 'Data analysis workspace',
|
|
32
|
+
description_t: 'Data analysis workspace',
|
|
33
|
+
visibility: 'private',
|
|
34
|
+
owner_id: 'user-abc',
|
|
35
|
+
organization_id: 'org-def',
|
|
36
|
+
created_at: '2023-01-01T10:00:00Z',
|
|
37
|
+
updated_at: '2023-01-02T15:30:00Z',
|
|
38
|
+
notebooks_count: 5,
|
|
39
|
+
members_count: 3,
|
|
40
|
+
tags: ['research', 'analysis'],
|
|
41
|
+
tags_ss: ['research', 'analysis'],
|
|
42
|
+
};
|
|
43
|
+
let mockSDK;
|
|
44
|
+
let space;
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
mockSDK = {
|
|
47
|
+
getToken: vi.fn().mockReturnValue('mock-token'),
|
|
48
|
+
getSpacerRunUrl: vi.fn().mockReturnValue('https://spacer.example.com'),
|
|
49
|
+
createNotebook: vi.fn(),
|
|
50
|
+
createLexical: vi.fn(),
|
|
51
|
+
};
|
|
52
|
+
space = new Space(mockSpaceData, mockSDK);
|
|
53
|
+
vi.clearAllMocks();
|
|
54
|
+
});
|
|
55
|
+
describe('Static Properties', () => {
|
|
56
|
+
it('should return correct uid', () => {
|
|
57
|
+
expect(space.uid).toBe('space-uid-123');
|
|
58
|
+
});
|
|
59
|
+
it('should return correct id', () => {
|
|
60
|
+
expect(space.id).toBe('space-123');
|
|
61
|
+
});
|
|
62
|
+
it('should return uid as id when id is not present', () => {
|
|
63
|
+
const dataWithoutId = { ...mockSpaceData, id: undefined };
|
|
64
|
+
const spaceWithoutId = new Space(dataWithoutId, mockSDK);
|
|
65
|
+
expect(spaceWithoutId.id).toBe('space-uid-123');
|
|
66
|
+
});
|
|
67
|
+
it('should return correct owner ID', () => {
|
|
68
|
+
expect(space.ownerId).toBe('user-abc');
|
|
69
|
+
});
|
|
70
|
+
it('should return correct organization ID', () => {
|
|
71
|
+
expect(space.organizationId).toBe('org-def');
|
|
72
|
+
});
|
|
73
|
+
it('should return correct created date', () => {
|
|
74
|
+
const createdAt = space.createdAt;
|
|
75
|
+
expect(createdAt).toEqual(new Date('2023-01-01T10:00:00Z'));
|
|
76
|
+
});
|
|
77
|
+
it('should return correct visibility', () => {
|
|
78
|
+
expect(space.visibility).toBe('private');
|
|
79
|
+
});
|
|
80
|
+
it('should return correct handle', () => {
|
|
81
|
+
expect(space.handle).toBe('research-workspace');
|
|
82
|
+
});
|
|
83
|
+
it('should return correct variant', () => {
|
|
84
|
+
expect(space.variant).toBe('default');
|
|
85
|
+
});
|
|
86
|
+
it('should handle missing optional fields gracefully', () => {
|
|
87
|
+
const minimalData = {
|
|
88
|
+
uid: 'space-minimal',
|
|
89
|
+
visibility: 'public',
|
|
90
|
+
};
|
|
91
|
+
const minimalSpace = new Space(minimalData, mockSDK);
|
|
92
|
+
expect(minimalSpace.ownerId).toBe('');
|
|
93
|
+
expect(minimalSpace.organizationId).toBe('');
|
|
94
|
+
expect(minimalSpace.handle).toBe('');
|
|
95
|
+
expect(minimalSpace.variant).toBe('');
|
|
96
|
+
expect(minimalSpace.createdAt).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe('Dynamic Methods', () => {
|
|
100
|
+
beforeEach(() => {
|
|
101
|
+
users.getMySpaces.mockResolvedValue({
|
|
102
|
+
success: true,
|
|
103
|
+
spaces: [{ ...mockSpaceData, name: 'Updated Workspace Name' }],
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('should fetch fresh name from API and update internal data', async () => {
|
|
107
|
+
const name = await space.getName();
|
|
108
|
+
expect(name).toBe('Updated Workspace Name');
|
|
109
|
+
expect(users.getMySpaces).toHaveBeenCalledWith('mock-token', 'https://spacer.example.com');
|
|
110
|
+
});
|
|
111
|
+
it('should fetch fresh description from API', async () => {
|
|
112
|
+
const updatedDescription = 'Updated workspace description';
|
|
113
|
+
users.getMySpaces.mockResolvedValue({
|
|
114
|
+
success: true,
|
|
115
|
+
spaces: [{ ...mockSpaceData, description: updatedDescription }],
|
|
116
|
+
});
|
|
117
|
+
const description = await space.getDescription();
|
|
118
|
+
expect(description).toBe(updatedDescription);
|
|
119
|
+
});
|
|
120
|
+
it('should fetch fresh updated date from API', async () => {
|
|
121
|
+
const newUpdateTime = '2023-01-03T12:00:00Z';
|
|
122
|
+
users.getMySpaces.mockResolvedValue({
|
|
123
|
+
success: true,
|
|
124
|
+
spaces: [{ ...mockSpaceData, updated_at: newUpdateTime }],
|
|
125
|
+
});
|
|
126
|
+
const updatedAt = await space.getUpdatedAt();
|
|
127
|
+
expect(updatedAt).toEqual(new Date(newUpdateTime));
|
|
128
|
+
});
|
|
129
|
+
it('should handle missing updated_at by falling back to created_at', async () => {
|
|
130
|
+
users.getMySpaces.mockResolvedValue({
|
|
131
|
+
success: true,
|
|
132
|
+
spaces: [{ ...mockSpaceData, updated_at: undefined }],
|
|
133
|
+
});
|
|
134
|
+
const updatedAt = await space.getUpdatedAt();
|
|
135
|
+
expect(updatedAt).toEqual(new Date(mockSpaceData.created_at));
|
|
136
|
+
});
|
|
137
|
+
it('should handle space not found in refresh', async () => {
|
|
138
|
+
users.getMySpaces.mockResolvedValue({
|
|
139
|
+
success: true,
|
|
140
|
+
spaces: [], // Empty array - space not found
|
|
141
|
+
});
|
|
142
|
+
const name = await space.getName();
|
|
143
|
+
// Should return the current name from internal data when space not found
|
|
144
|
+
expect(name).toBe('Research Workspace');
|
|
145
|
+
});
|
|
146
|
+
it('should prefer name over name_t field', async () => {
|
|
147
|
+
users.getMySpaces.mockResolvedValue({
|
|
148
|
+
success: true,
|
|
149
|
+
spaces: [
|
|
150
|
+
{ ...mockSpaceData, name: 'Primary Name', name_t: 'Secondary Name' },
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
const name = await space.getName();
|
|
154
|
+
expect(name).toBe('Primary Name');
|
|
155
|
+
});
|
|
156
|
+
it('should use name_t when name is not present', async () => {
|
|
157
|
+
users.getMySpaces.mockResolvedValue({
|
|
158
|
+
success: true,
|
|
159
|
+
spaces: [
|
|
160
|
+
{ ...mockSpaceData, name: undefined, name_t: 'Fallback Name' },
|
|
161
|
+
],
|
|
162
|
+
});
|
|
163
|
+
const name = await space.getName();
|
|
164
|
+
expect(name).toBe('Fallback Name');
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('Space-specific Methods', () => {
|
|
168
|
+
it('should get space items', async () => {
|
|
169
|
+
const mockItems = [
|
|
170
|
+
{ id: 'item-1', name: 'Notebook 1', type: 'notebook' },
|
|
171
|
+
{ id: 'item-2', name: 'Document 1', type: 'lexical' },
|
|
172
|
+
];
|
|
173
|
+
items.getSpaceItems.mockResolvedValue({
|
|
174
|
+
success: true,
|
|
175
|
+
items: mockItems,
|
|
176
|
+
});
|
|
177
|
+
const spaceItems = await space.getItems();
|
|
178
|
+
expect(items.getSpaceItems).toHaveBeenCalledWith('mock-token', 'space-uid-123', 'https://spacer.example.com');
|
|
179
|
+
expect(spaceItems).toEqual(mockItems);
|
|
180
|
+
});
|
|
181
|
+
it('should create notebook in space', async () => {
|
|
182
|
+
const mockNotebook = new Notebook({
|
|
183
|
+
id: 'notebook-new',
|
|
184
|
+
uid: 'notebook-uid-new',
|
|
185
|
+
name: 'New Notebook',
|
|
186
|
+
}, mockSDK);
|
|
187
|
+
mockSDK.createNotebook.mockResolvedValue(mockNotebook);
|
|
188
|
+
const formData = new FormData();
|
|
189
|
+
formData.append('name', 'New Notebook');
|
|
190
|
+
formData.append('notebookType', 'jupyter');
|
|
191
|
+
const notebook = await space.createNotebook(formData);
|
|
192
|
+
// Should automatically set spaceId
|
|
193
|
+
expect(formData.get('spaceId')).toBe('space-uid-123');
|
|
194
|
+
expect(mockSDK.createNotebook).toHaveBeenCalledWith(formData);
|
|
195
|
+
expect(notebook).toBe(mockNotebook);
|
|
196
|
+
});
|
|
197
|
+
it('should create lexical document in space', async () => {
|
|
198
|
+
const mockLexical = new Lexical({
|
|
199
|
+
id: 'lexical-new',
|
|
200
|
+
uid: 'lexical-uid-new',
|
|
201
|
+
name: 'New Document',
|
|
202
|
+
}, mockSDK);
|
|
203
|
+
mockSDK.createLexical.mockResolvedValue(mockLexical);
|
|
204
|
+
const formData = new FormData();
|
|
205
|
+
formData.append('name', 'New Document');
|
|
206
|
+
formData.append('documentType', 'lexical');
|
|
207
|
+
const lexical = await space.createLexical(formData);
|
|
208
|
+
// Should automatically set spaceId
|
|
209
|
+
expect(formData.get('spaceId')).toBe('space-uid-123');
|
|
210
|
+
expect(mockSDK.createLexical).toHaveBeenCalledWith(formData);
|
|
211
|
+
expect(lexical).toBe(mockLexical);
|
|
212
|
+
});
|
|
213
|
+
it('should override existing spaceId in formData', async () => {
|
|
214
|
+
const mockNotebook = new Notebook({
|
|
215
|
+
id: 'notebook-new',
|
|
216
|
+
uid: 'notebook-uid-new',
|
|
217
|
+
name: 'New Notebook',
|
|
218
|
+
}, mockSDK);
|
|
219
|
+
mockSDK.createNotebook.mockResolvedValue(mockNotebook);
|
|
220
|
+
const formData = new FormData();
|
|
221
|
+
formData.append('spaceId', 'wrong-space-id'); // Wrong space ID
|
|
222
|
+
formData.append('name', 'New Notebook');
|
|
223
|
+
await space.createNotebook(formData);
|
|
224
|
+
// Should override with correct spaceId
|
|
225
|
+
expect(formData.get('spaceId')).toBe('space-uid-123');
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
describe('Utility Methods', () => {
|
|
229
|
+
it('should return JSON with fresh data', async () => {
|
|
230
|
+
const freshData = { ...mockSpaceData, name: 'Fresh Workspace Name' };
|
|
231
|
+
users.getMySpaces.mockResolvedValue({
|
|
232
|
+
success: true,
|
|
233
|
+
spaces: [freshData],
|
|
234
|
+
});
|
|
235
|
+
const json = await space.toJSON();
|
|
236
|
+
expect(json.name).toBe('Fresh Workspace Name');
|
|
237
|
+
expect(json.uid).toBe('space-uid-123');
|
|
238
|
+
});
|
|
239
|
+
it('should return string representation with name', () => {
|
|
240
|
+
expect(space.toString()).toBe('Space(space-uid-123, Research Workspace)');
|
|
241
|
+
});
|
|
242
|
+
it('should use name_t in toString when name is not present', () => {
|
|
243
|
+
const dataWithoutName = { ...mockSpaceData, name: undefined };
|
|
244
|
+
const spaceWithoutName = new Space(dataWithoutName, mockSDK);
|
|
245
|
+
expect(spaceWithoutName.toString()).toBe('Space(space-uid-123, Research Workspace)');
|
|
246
|
+
});
|
|
247
|
+
it('should use "Unnamed" in toString when no name fields present', () => {
|
|
248
|
+
const dataWithoutNames = {
|
|
249
|
+
...mockSpaceData,
|
|
250
|
+
name: undefined,
|
|
251
|
+
name_t: undefined,
|
|
252
|
+
};
|
|
253
|
+
const spaceWithoutNames = new Space(dataWithoutNames, mockSDK);
|
|
254
|
+
expect(spaceWithoutNames.toString()).toBe('Space(space-uid-123, Unnamed)');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('Deletion State Management', () => {
|
|
258
|
+
beforeEach(() => {
|
|
259
|
+
// Mark space as deleted by setting the private flag
|
|
260
|
+
space._deleted = true;
|
|
261
|
+
});
|
|
262
|
+
it('should throw error when accessing static properties after deletion', () => {
|
|
263
|
+
expect(() => space.uid).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
264
|
+
expect(() => space.id).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
265
|
+
expect(() => space.ownerId).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
266
|
+
expect(() => space.organizationId).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
267
|
+
expect(() => space.createdAt).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
268
|
+
expect(() => space.visibility).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
269
|
+
expect(() => space.handle).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
270
|
+
expect(() => space.variant).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
271
|
+
});
|
|
272
|
+
it('should throw error when calling dynamic methods after deletion', async () => {
|
|
273
|
+
await expect(space.getName()).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
274
|
+
await expect(space.getDescription()).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
275
|
+
await expect(space.getUpdatedAt()).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
276
|
+
});
|
|
277
|
+
it('should throw error when calling space-specific methods after deletion', async () => {
|
|
278
|
+
await expect(space.getItems()).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
279
|
+
await expect(space.createNotebook(new FormData())).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
280
|
+
await expect(space.createLexical(new FormData())).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
281
|
+
});
|
|
282
|
+
it('should throw error when calling utility methods after deletion', async () => {
|
|
283
|
+
await expect(space.toJSON()).rejects.toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
284
|
+
expect(() => space.toString()).toThrow('Space space-uid-123 has been deleted and no longer exists');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
describe('Error Handling', () => {
|
|
288
|
+
it('should handle API errors gracefully in dynamic methods', async () => {
|
|
289
|
+
users.getMySpaces.mockRejectedValue(new Error('API Error'));
|
|
290
|
+
await expect(space.getName()).rejects.toThrow('API Error');
|
|
291
|
+
});
|
|
292
|
+
it('should handle API errors in getItems method', async () => {
|
|
293
|
+
items.getSpaceItems.mockRejectedValue(new Error('Items fetch failed'));
|
|
294
|
+
await expect(space.getItems()).rejects.toThrow('Items fetch failed');
|
|
295
|
+
});
|
|
296
|
+
it('should handle errors in createNotebook', async () => {
|
|
297
|
+
mockSDK.createNotebook.mockRejectedValue(new Error('Creation failed'));
|
|
298
|
+
await expect(space.createNotebook(new FormData())).rejects.toThrow('Creation failed');
|
|
299
|
+
});
|
|
300
|
+
it('should handle errors in createLexical', async () => {
|
|
301
|
+
mockSDK.createLexical.mockRejectedValue(new Error('Creation failed'));
|
|
302
|
+
await expect(space.createLexical(new FormData())).rejects.toThrow('Creation failed');
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
describe('Edge Cases', () => {
|
|
306
|
+
it('should handle empty description gracefully', async () => {
|
|
307
|
+
users.getMySpaces.mockResolvedValue({
|
|
308
|
+
success: true,
|
|
309
|
+
spaces: [{ ...mockSpaceData, description: '', description_t: '' }],
|
|
310
|
+
});
|
|
311
|
+
const description = await space.getDescription();
|
|
312
|
+
expect(description).toBe('');
|
|
313
|
+
});
|
|
314
|
+
it('should handle missing timestamps gracefully', async () => {
|
|
315
|
+
users.getMySpaces.mockResolvedValue({
|
|
316
|
+
success: true,
|
|
317
|
+
spaces: [
|
|
318
|
+
{ ...mockSpaceData, updated_at: undefined, created_at: undefined },
|
|
319
|
+
],
|
|
320
|
+
});
|
|
321
|
+
// Should return null when no timestamps are available
|
|
322
|
+
const updatedAt = await space.getUpdatedAt();
|
|
323
|
+
expect(updatedAt).toBeNull();
|
|
324
|
+
});
|
|
325
|
+
it('should handle empty items response', async () => {
|
|
326
|
+
items.getSpaceItems.mockResolvedValue({
|
|
327
|
+
success: true,
|
|
328
|
+
items: [],
|
|
329
|
+
});
|
|
330
|
+
const spaceItems = await space.getItems();
|
|
331
|
+
expect(spaceItems).toEqual([]);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/client/models
|
|
3
|
+
* @description Domain model classes for the Datalayer SDK.
|
|
4
|
+
*
|
|
5
|
+
* These models provide rich, object-oriented interfaces for working with
|
|
6
|
+
* Datalayer platform resources, wrapping API responses with convenient
|
|
7
|
+
* methods and automatic state management.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Runtime, Snapshot, Notebook, Lexical, Space } from '@datalayer/core/sdk/client/models';
|
|
12
|
+
*
|
|
13
|
+
* // Models are typically created by SDK methods
|
|
14
|
+
* const runtime = await sdk.createRuntime(config);
|
|
15
|
+
* const snapshot = await runtime.createSnapshot('checkpoint');
|
|
16
|
+
* const notebook = await sdk.createNotebook(formData);
|
|
17
|
+
* const lexical = await sdk.createLexical(formData);
|
|
18
|
+
* const space = await sdk.createSpace(config);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export { Runtime } from './Runtime';
|
|
22
|
+
export { Snapshot } from './Snapshot';
|
|
23
|
+
export { Notebook } from './Notebook';
|
|
24
|
+
export { Lexical } from './Lexical';
|
|
25
|
+
export { Space } from './Space';
|
|
26
|
+
export type { RuntimeData } from './Runtime';
|
|
27
|
+
export type { RuntimeSnapshot } from './Snapshot';
|
|
28
|
+
export type { NotebookData } from './Notebook';
|
|
29
|
+
export type { LexicalData } from './Lexical';
|
|
30
|
+
export type { SpaceData } from './Space';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module sdk/client/models
|
|
7
|
+
* @description Domain model classes for the Datalayer SDK.
|
|
8
|
+
*
|
|
9
|
+
* These models provide rich, object-oriented interfaces for working with
|
|
10
|
+
* Datalayer platform resources, wrapping API responses with convenient
|
|
11
|
+
* methods and automatic state management.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { Runtime, Snapshot, Notebook, Lexical, Space } from '@datalayer/core/sdk/client/models';
|
|
16
|
+
*
|
|
17
|
+
* // Models are typically created by SDK methods
|
|
18
|
+
* const runtime = await sdk.createRuntime(config);
|
|
19
|
+
* const snapshot = await runtime.createSnapshot('checkpoint');
|
|
20
|
+
* const notebook = await sdk.createNotebook(formData);
|
|
21
|
+
* const lexical = await sdk.createLexical(formData);
|
|
22
|
+
* const space = await sdk.createSpace(config);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
// Export domain model classes
|
|
26
|
+
export { Runtime } from './Runtime';
|
|
27
|
+
export { Snapshot } from './Snapshot';
|
|
28
|
+
export { Notebook } from './Notebook';
|
|
29
|
+
export { Lexical } from './Lexical';
|
|
30
|
+
export { Space } from './Space';
|