@powerhousedao/reactor 5.0.0-staging.8 → 5.0.1-staging.1
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/dist/src/cache/buffer/ring-buffer.d.ts +37 -0
- package/dist/src/cache/buffer/ring-buffer.d.ts.map +1 -0
- package/dist/src/cache/buffer/ring-buffer.js +69 -0
- package/dist/src/cache/buffer/ring-buffer.js.map +1 -0
- package/dist/src/cache/kysely-write-cache.d.ts +133 -0
- package/dist/src/cache/kysely-write-cache.d.ts.map +1 -0
- package/dist/src/cache/kysely-write-cache.js +375 -0
- package/dist/src/cache/kysely-write-cache.js.map +1 -0
- package/dist/src/cache/lru/lru-tracker.d.ts +15 -0
- package/dist/src/cache/lru/lru-tracker.d.ts.map +1 -0
- package/dist/src/cache/lru/lru-tracker.js +96 -0
- package/dist/src/cache/lru/lru-tracker.js.map +1 -0
- package/dist/src/cache/types.d.ts +42 -0
- package/dist/src/cache/types.d.ts.map +1 -0
- package/dist/src/cache/types.js +2 -0
- package/dist/src/cache/types.js.map +1 -0
- package/dist/src/cache/write/interfaces.d.ts +83 -0
- package/dist/src/cache/write/interfaces.d.ts.map +1 -0
- package/dist/src/cache/write/interfaces.js +2 -0
- package/dist/src/cache/write/interfaces.js.map +1 -0
- package/dist/src/client/reactor-client.d.ts +103 -0
- package/dist/src/client/reactor-client.d.ts.map +1 -0
- package/dist/src/client/reactor-client.js +184 -0
- package/dist/src/client/reactor-client.js.map +1 -0
- package/dist/src/client/types.d.ts +213 -0
- package/dist/src/client/types.d.ts.map +1 -0
- package/dist/src/client/types.js +14 -0
- package/dist/src/client/types.js.map +1 -0
- package/dist/src/core/builder.d.ts +20 -0
- package/dist/src/core/builder.d.ts.map +1 -0
- package/dist/src/core/builder.js +47 -0
- package/dist/src/core/builder.js.map +1 -0
- package/dist/src/{reactor.d.ts → core/reactor.d.ts} +13 -30
- package/dist/src/core/reactor.d.ts.map +1 -0
- package/dist/src/{reactor.js → core/reactor.js} +147 -111
- package/dist/src/core/reactor.js.map +1 -0
- package/dist/src/{interfaces/reactor.d.ts → core/types.d.ts} +7 -7
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/{utils.d.ts → core/utils.d.ts} +2 -2
- package/dist/src/core/utils.d.ts.map +1 -0
- package/dist/src/core/utils.js.map +1 -0
- package/dist/src/events/event-bus.d.ts +2 -2
- package/dist/src/events/event-bus.d.ts.map +1 -1
- package/dist/src/events/event-bus.js +1 -1
- package/dist/src/events/event-bus.js.map +1 -1
- package/dist/src/events/interfaces.d.ts +1 -1
- package/dist/src/events/interfaces.d.ts.map +1 -1
- package/dist/src/events/types.d.ts +14 -0
- package/dist/src/events/types.d.ts.map +1 -1
- package/dist/src/events/types.js +6 -0
- package/dist/src/events/types.js.map +1 -1
- package/dist/src/executor/interfaces.d.ts +2 -2
- package/dist/src/executor/interfaces.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor-manager.d.ts +5 -1
- package/dist/src/executor/simple-job-executor-manager.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor-manager.js +98 -36
- package/dist/src/executor/simple-job-executor-manager.js.map +1 -1
- package/dist/src/executor/simple-job-executor.d.ts +32 -3
- package/dist/src/executor/simple-job-executor.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor.js +436 -17
- package/dist/src/executor/simple-job-executor.js.map +1 -1
- package/dist/src/executor/types.d.ts +10 -3
- package/dist/src/executor/types.d.ts.map +1 -1
- package/dist/src/executor/types.js.map +1 -1
- package/dist/src/executor/util.d.ts +47 -0
- package/dist/src/executor/util.d.ts.map +1 -0
- package/dist/src/executor/util.js +113 -0
- package/dist/src/executor/util.js.map +1 -0
- package/dist/src/index.d.ts +23 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +30 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/job-tracker/in-memory-job-tracker.d.ts +15 -0
- package/dist/src/job-tracker/in-memory-job-tracker.d.ts.map +1 -0
- package/dist/src/job-tracker/in-memory-job-tracker.js +78 -0
- package/dist/src/job-tracker/in-memory-job-tracker.js.map +1 -0
- package/dist/src/job-tracker/index.d.ts +3 -0
- package/dist/src/job-tracker/index.d.ts.map +1 -0
- package/dist/src/job-tracker/index.js +2 -0
- package/dist/src/job-tracker/index.js.map +1 -0
- package/dist/src/job-tracker/interfaces.d.ts +41 -0
- package/dist/src/job-tracker/interfaces.d.ts.map +1 -0
- package/dist/src/job-tracker/interfaces.js +2 -0
- package/dist/src/job-tracker/interfaces.js.map +1 -0
- package/dist/src/queue/interfaces.d.ts +1 -1
- package/dist/src/queue/interfaces.d.ts.map +1 -1
- package/dist/src/queue/job-execution-handle.d.ts +2 -1
- package/dist/src/queue/job-execution-handle.d.ts.map +1 -1
- package/dist/src/queue/job-execution-handle.js.map +1 -1
- package/dist/src/queue/queue.d.ts +3 -3
- package/dist/src/queue/queue.d.ts.map +1 -1
- package/dist/src/queue/queue.js +47 -25
- package/dist/src/queue/queue.js.map +1 -1
- package/dist/src/queue/types.d.ts +7 -5
- package/dist/src/queue/types.d.ts.map +1 -1
- package/dist/src/queue/types.js.map +1 -1
- package/dist/src/read-models/coordinator.d.ts +38 -0
- package/dist/src/read-models/coordinator.d.ts.map +1 -0
- package/dist/src/read-models/coordinator.js +62 -0
- package/dist/src/read-models/coordinator.js.map +1 -0
- package/dist/src/read-models/document-view.d.ts +20 -0
- package/dist/src/read-models/document-view.d.ts.map +1 -0
- package/dist/src/read-models/document-view.js +365 -0
- package/dist/src/read-models/document-view.js.map +1 -0
- package/dist/src/read-models/interfaces.d.ts +29 -0
- package/dist/src/read-models/interfaces.d.ts.map +1 -0
- package/dist/src/read-models/interfaces.js +2 -0
- package/dist/src/read-models/interfaces.js.map +1 -0
- package/dist/src/read-models/types.d.ts +46 -0
- package/dist/src/read-models/types.d.ts.map +1 -0
- package/dist/src/read-models/types.js +2 -0
- package/dist/src/read-models/types.js.map +1 -0
- package/dist/src/registry/implementation.js +1 -1
- package/dist/src/registry/implementation.js.map +1 -1
- package/dist/src/shared/awaiter.d.ts +32 -0
- package/dist/src/shared/awaiter.d.ts.map +1 -0
- package/dist/src/shared/awaiter.js +132 -0
- package/dist/src/shared/awaiter.js.map +1 -0
- package/dist/src/shared/errors.d.ts +17 -0
- package/dist/src/shared/errors.d.ts.map +1 -0
- package/dist/src/shared/errors.js +33 -0
- package/dist/src/shared/errors.js.map +1 -0
- package/dist/src/shared/factories.d.ts +1 -1
- package/dist/src/shared/factories.d.ts.map +1 -1
- package/dist/src/shared/types.d.ts +8 -0
- package/dist/src/shared/types.d.ts.map +1 -1
- package/dist/src/shared/types.js +5 -0
- package/dist/src/shared/types.js.map +1 -1
- package/dist/src/signer/passthrough-signer.d.ts +6 -0
- package/dist/src/signer/passthrough-signer.d.ts.map +1 -0
- package/dist/src/signer/passthrough-signer.js +6 -0
- package/dist/src/signer/passthrough-signer.js.map +1 -0
- package/dist/src/signer/types.d.ts +15 -0
- package/dist/src/signer/types.d.ts.map +1 -0
- package/dist/src/signer/types.js +2 -0
- package/dist/src/signer/types.js.map +1 -0
- package/dist/src/storage/interfaces.d.ts +121 -0
- package/dist/src/storage/interfaces.d.ts.map +1 -0
- package/dist/src/storage/interfaces.js +19 -0
- package/dist/src/storage/interfaces.js.map +1 -0
- package/dist/src/storage/kysely/keyframe-store.d.ts +15 -0
- package/dist/src/storage/kysely/keyframe-store.d.ts.map +1 -0
- package/dist/src/storage/kysely/keyframe-store.js +71 -0
- package/dist/src/storage/kysely/keyframe-store.js.map +1 -0
- package/dist/src/storage/kysely/store.d.ts +15 -0
- package/dist/src/storage/kysely/store.d.ts.map +1 -0
- package/dist/src/storage/kysely/store.js +196 -0
- package/dist/src/storage/kysely/store.js.map +1 -0
- package/dist/src/storage/kysely/types.d.ts +39 -0
- package/dist/src/storage/kysely/types.d.ts.map +1 -0
- package/dist/src/storage/kysely/types.js +2 -0
- package/dist/src/storage/kysely/types.js.map +1 -0
- package/dist/src/storage/txn.d.ts +15 -0
- package/dist/src/storage/txn.d.ts.map +1 -0
- package/dist/src/storage/txn.js +41 -0
- package/dist/src/storage/txn.js.map +1 -0
- package/dist/src/subs/default-error-handler.d.ts +13 -0
- package/dist/src/subs/default-error-handler.d.ts.map +1 -0
- package/dist/src/subs/default-error-handler.js +27 -0
- package/dist/src/subs/default-error-handler.js.map +1 -0
- package/dist/src/subs/react-subscription-manager.d.ts +45 -0
- package/dist/src/subs/react-subscription-manager.d.ts.map +1 -0
- package/dist/src/subs/react-subscription-manager.js +185 -0
- package/dist/src/subs/react-subscription-manager.js.map +1 -0
- package/dist/src/subs/types.d.ts +64 -0
- package/dist/src/subs/types.d.ts.map +1 -0
- package/dist/src/subs/types.js +2 -0
- package/dist/src/subs/types.js.map +1 -0
- package/dist/src/utils/reshuffle.d.ts +30 -0
- package/dist/src/utils/reshuffle.d.ts.map +1 -0
- package/dist/src/utils/reshuffle.js +47 -0
- package/dist/src/utils/reshuffle.js.map +1 -0
- package/package.json +15 -9
- package/dist/bench/event-bus.bench.d.ts +0 -2
- package/dist/bench/event-bus.bench.d.ts.map +0 -1
- package/dist/bench/event-bus.bench.js +0 -228
- package/dist/bench/event-bus.bench.js.map +0 -1
- package/dist/bench/queue-only.bench.d.ts +0 -2
- package/dist/bench/queue-only.bench.d.ts.map +0 -1
- package/dist/bench/queue-only.bench.js +0 -46
- package/dist/bench/queue-only.bench.js.map +0 -1
- package/dist/bench/reactor-throughput.bench.d.ts +0 -2
- package/dist/bench/reactor-throughput.bench.d.ts.map +0 -1
- package/dist/bench/reactor-throughput.bench.js +0 -144
- package/dist/bench/reactor-throughput.bench.js.map +0 -1
- package/dist/src/interfaces/reactor.d.ts.map +0 -1
- package/dist/src/interfaces/reactor.js +0 -2
- package/dist/src/interfaces/reactor.js.map +0 -1
- package/dist/src/reactor.d.ts.map +0 -1
- package/dist/src/reactor.js.map +0 -1
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/utils.js.map +0 -1
- package/dist/test/event-bus.test.d.ts +0 -2
- package/dist/test/event-bus.test.d.ts.map +0 -1
- package/dist/test/event-bus.test.js +0 -541
- package/dist/test/event-bus.test.js.map +0 -1
- package/dist/test/executor/executor-integration.test.d.ts +0 -2
- package/dist/test/executor/executor-integration.test.d.ts.map +0 -1
- package/dist/test/executor/executor-integration.test.js +0 -287
- package/dist/test/executor/executor-integration.test.js.map +0 -1
- package/dist/test/executor/job-execution-handle.test.d.ts +0 -2
- package/dist/test/executor/job-execution-handle.test.d.ts.map +0 -1
- package/dist/test/executor/job-execution-handle.test.js +0 -272
- package/dist/test/executor/job-execution-handle.test.js.map +0 -1
- package/dist/test/executor/simple-job-executor-manager.test.d.ts +0 -2
- package/dist/test/executor/simple-job-executor-manager.test.d.ts.map +0 -1
- package/dist/test/executor/simple-job-executor-manager.test.js +0 -132
- package/dist/test/executor/simple-job-executor-manager.test.js.map +0 -1
- package/dist/test/executor/simple-job-executor.test.d.ts +0 -2
- package/dist/test/executor/simple-job-executor.test.d.ts.map +0 -1
- package/dist/test/executor/simple-job-executor.test.js +0 -139
- package/dist/test/executor/simple-job-executor.test.js.map +0 -1
- package/dist/test/factories.d.ts +0 -122
- package/dist/test/factories.d.ts.map +0 -1
- package/dist/test/factories.js +0 -319
- package/dist/test/factories.js.map +0 -1
- package/dist/test/integration/document-drive-integration.test.d.ts +0 -2
- package/dist/test/integration/document-drive-integration.test.d.ts.map +0 -1
- package/dist/test/integration/document-drive-integration.test.js +0 -1102
- package/dist/test/integration/document-drive-integration.test.js.map +0 -1
- package/dist/test/integration/reactor-read.test.d.ts +0 -2
- package/dist/test/integration/reactor-read.test.d.ts.map +0 -1
- package/dist/test/integration/reactor-read.test.js +0 -300
- package/dist/test/integration/reactor-read.test.js.map +0 -1
- package/dist/test/queue/queue-integration.test.d.ts +0 -2
- package/dist/test/queue/queue-integration.test.d.ts.map +0 -1
- package/dist/test/queue/queue-integration.test.js +0 -322
- package/dist/test/queue/queue-integration.test.js.map +0 -1
- package/dist/test/queue/queue.test.d.ts +0 -2
- package/dist/test/queue/queue.test.d.ts.map +0 -1
- package/dist/test/queue/queue.test.js +0 -770
- package/dist/test/queue/queue.test.js.map +0 -1
- package/dist/test/registry/registry.test.d.ts +0 -2
- package/dist/test/registry/registry.test.d.ts.map +0 -1
- package/dist/test/registry/registry.test.js +0 -182
- package/dist/test/registry/registry.test.js.map +0 -1
- package/dist/test/utils.test.d.ts +0 -2
- package/dist/test/utils.test.d.ts.map +0 -1
- package/dist/test/utils.test.js +0 -66
- package/dist/test/utils.test.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/vitest.config.d.ts +0 -3
- package/dist/vitest.config.d.ts.map +0 -1
- package/dist/vitest.config.js +0 -11
- package/dist/vitest.config.js.map +0 -1
- /package/dist/src/{utils.js → core/utils.js} +0 -0
|
@@ -1,1102 +0,0 @@
|
|
|
1
|
-
import { MemoryStorage, ReactorBuilder, addFile, addFolder, copyNode, deleteNode, driveDocumentModelModule, moveNode, setAvailableOffline, setDriveIcon, setDriveName, setSharingType, updateFile, updateNode, } from "document-drive";
|
|
2
|
-
import { generateId } from "document-model";
|
|
3
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { EventBus } from "../../src/events/event-bus.js";
|
|
5
|
-
import { SimpleJobExecutorManager } from "../../src/executor/simple-job-executor-manager.js";
|
|
6
|
-
import { SimpleJobExecutor } from "../../src/executor/simple-job-executor.js";
|
|
7
|
-
import { InMemoryQueue } from "../../src/queue/queue.js";
|
|
8
|
-
import { Reactor } from "../../src/reactor.js";
|
|
9
|
-
import { DocumentModelRegistry } from "../../src/registry/implementation.js";
|
|
10
|
-
import { JobStatus } from "../../src/shared/types.js";
|
|
11
|
-
describe("Integration Test: Reactor <> Document Drive Document Model", () => {
|
|
12
|
-
let reactor;
|
|
13
|
-
let registry;
|
|
14
|
-
let storage;
|
|
15
|
-
let eventBus;
|
|
16
|
-
let queue;
|
|
17
|
-
let executor;
|
|
18
|
-
let executorManager;
|
|
19
|
-
let driveServer;
|
|
20
|
-
beforeEach(async () => {
|
|
21
|
-
// Setup real components
|
|
22
|
-
storage = new MemoryStorage();
|
|
23
|
-
registry = new DocumentModelRegistry();
|
|
24
|
-
registry.registerModules(driveDocumentModelModule);
|
|
25
|
-
// Create real drive server using ReactorBuilder
|
|
26
|
-
const builder = new ReactorBuilder([
|
|
27
|
-
driveDocumentModelModule,
|
|
28
|
-
]).withStorage(storage);
|
|
29
|
-
driveServer = builder.build();
|
|
30
|
-
await driveServer.initialize();
|
|
31
|
-
eventBus = new EventBus();
|
|
32
|
-
queue = new InMemoryQueue(eventBus);
|
|
33
|
-
executor = new SimpleJobExecutor(registry, storage, storage);
|
|
34
|
-
executorManager = new SimpleJobExecutorManager(() => executor, eventBus, queue);
|
|
35
|
-
// Start the executor manager to process jobs
|
|
36
|
-
await executorManager.start(1);
|
|
37
|
-
// Create reactor with all components
|
|
38
|
-
reactor = new Reactor(driveServer, storage, eventBus, queue, executor);
|
|
39
|
-
});
|
|
40
|
-
afterEach(async () => {
|
|
41
|
-
await executorManager.stop();
|
|
42
|
-
});
|
|
43
|
-
describe("ADD Operations", () => {
|
|
44
|
-
it("should add a folder via reactor.mutate", async () => {
|
|
45
|
-
// Create a document-drive document
|
|
46
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
47
|
-
await storage.create(document);
|
|
48
|
-
// Create an ADD_FOLDER action
|
|
49
|
-
const folderId = generateId();
|
|
50
|
-
const action = addFolder({
|
|
51
|
-
id: folderId,
|
|
52
|
-
name: "Test Folder",
|
|
53
|
-
parentFolder: null,
|
|
54
|
-
});
|
|
55
|
-
// Submit via reactor.mutate
|
|
56
|
-
const jobInfo = await reactor.mutate(document.header.id, [action]);
|
|
57
|
-
expect(jobInfo.status).toBe(JobStatus.PENDING);
|
|
58
|
-
// Wait for processing
|
|
59
|
-
await vi.waitFor(async () => {
|
|
60
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
61
|
-
expect(operations.global.results).toHaveLength(1);
|
|
62
|
-
});
|
|
63
|
-
// Verify the operation was processed
|
|
64
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
65
|
-
expect(operations.global.results[0].action.type).toBe("ADD_FOLDER");
|
|
66
|
-
// Verify state was updated
|
|
67
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
68
|
-
const globalState = updatedDocument.state.global;
|
|
69
|
-
expect(globalState.nodes).toHaveLength(1);
|
|
70
|
-
expect(globalState.nodes[0]).toMatchObject({
|
|
71
|
-
id: folderId,
|
|
72
|
-
name: "Test Folder",
|
|
73
|
-
parentFolder: null,
|
|
74
|
-
kind: "folder",
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
it("should add a file via reactor.mutate", async () => {
|
|
78
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
79
|
-
await storage.create(document);
|
|
80
|
-
// First add a folder
|
|
81
|
-
const folderId = generateId();
|
|
82
|
-
const folderAction = addFolder({
|
|
83
|
-
id: folderId,
|
|
84
|
-
name: "Documents",
|
|
85
|
-
parentFolder: null,
|
|
86
|
-
});
|
|
87
|
-
await reactor.mutate(document.header.id, [folderAction]);
|
|
88
|
-
// Wait for folder to be created
|
|
89
|
-
await vi.waitFor(async () => {
|
|
90
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
91
|
-
expect(operations.global.results).toHaveLength(1);
|
|
92
|
-
});
|
|
93
|
-
// Then add a file to the folder
|
|
94
|
-
const fileId = generateId();
|
|
95
|
-
const fileAction = addFile({
|
|
96
|
-
id: fileId,
|
|
97
|
-
name: "test.txt",
|
|
98
|
-
documentType: "text/plain",
|
|
99
|
-
parentFolder: folderId,
|
|
100
|
-
});
|
|
101
|
-
await reactor.mutate(document.header.id, [fileAction]);
|
|
102
|
-
// Wait for processing
|
|
103
|
-
await vi.waitFor(async () => {
|
|
104
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
105
|
-
expect(operations.global.results).toHaveLength(2);
|
|
106
|
-
});
|
|
107
|
-
// Verify both operations were processed
|
|
108
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
109
|
-
expect(operations.global.results).toHaveLength(2);
|
|
110
|
-
// Verify state contains both nodes
|
|
111
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
112
|
-
const globalState = updatedDocument.state.global;
|
|
113
|
-
expect(globalState.nodes).toHaveLength(2);
|
|
114
|
-
const file = globalState.nodes.find((n) => n.id === fileId);
|
|
115
|
-
expect(file).toMatchObject({
|
|
116
|
-
id: fileId,
|
|
117
|
-
name: "test.txt",
|
|
118
|
-
documentType: "text/plain",
|
|
119
|
-
parentFolder: folderId,
|
|
120
|
-
kind: "file",
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
it("should handle nested folder structure", async () => {
|
|
124
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
125
|
-
await storage.create(document);
|
|
126
|
-
// Create a hierarchy: root -> folder1 -> folder2 -> folder3
|
|
127
|
-
const folder1Id = generateId();
|
|
128
|
-
const folder2Id = generateId();
|
|
129
|
-
const folder3Id = generateId();
|
|
130
|
-
const actions = [
|
|
131
|
-
addFolder({
|
|
132
|
-
id: folder1Id,
|
|
133
|
-
name: "Folder 1",
|
|
134
|
-
parentFolder: null,
|
|
135
|
-
}),
|
|
136
|
-
addFolder({
|
|
137
|
-
id: folder2Id,
|
|
138
|
-
name: "Folder 2",
|
|
139
|
-
parentFolder: folder1Id,
|
|
140
|
-
}),
|
|
141
|
-
addFolder({
|
|
142
|
-
id: folder3Id,
|
|
143
|
-
name: "Folder 3",
|
|
144
|
-
parentFolder: folder2Id,
|
|
145
|
-
}),
|
|
146
|
-
];
|
|
147
|
-
// Submit all actions at once
|
|
148
|
-
await reactor.mutate(document.header.id, actions);
|
|
149
|
-
// Wait for processing
|
|
150
|
-
await vi.waitFor(async () => {
|
|
151
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
152
|
-
expect(operations.global.results).toHaveLength(3);
|
|
153
|
-
});
|
|
154
|
-
// Verify the hierarchy
|
|
155
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
156
|
-
const globalState = updatedDocument.state.global;
|
|
157
|
-
expect(globalState.nodes).toHaveLength(3);
|
|
158
|
-
const folder1 = globalState.nodes.find((n) => n.id === folder1Id);
|
|
159
|
-
const folder2 = globalState.nodes.find((n) => n.id === folder2Id);
|
|
160
|
-
const folder3 = globalState.nodes.find((n) => n.id === folder3Id);
|
|
161
|
-
expect(folder1).toBeDefined();
|
|
162
|
-
expect(folder2).toBeDefined();
|
|
163
|
-
expect(folder3).toBeDefined();
|
|
164
|
-
expect(folder1?.parentFolder).toBe(null);
|
|
165
|
-
expect(folder2?.parentFolder).toBe(folder1Id);
|
|
166
|
-
expect(folder3?.parentFolder).toBe(folder2Id);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
describe("UPDATE Operations", () => {
|
|
170
|
-
it("should update a file via reactor.mutate", async () => {
|
|
171
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
172
|
-
await storage.create(document);
|
|
173
|
-
// Add a file first
|
|
174
|
-
const fileId = generateId();
|
|
175
|
-
const addAction = addFile({
|
|
176
|
-
id: fileId,
|
|
177
|
-
name: "original.txt",
|
|
178
|
-
documentType: "text/plain",
|
|
179
|
-
parentFolder: null,
|
|
180
|
-
});
|
|
181
|
-
await reactor.mutate(document.header.id, [addAction]);
|
|
182
|
-
await vi.waitFor(async () => {
|
|
183
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
184
|
-
expect(operations.global.results).toHaveLength(1);
|
|
185
|
-
});
|
|
186
|
-
// Update the file
|
|
187
|
-
const updateAction = updateFile({
|
|
188
|
-
id: fileId,
|
|
189
|
-
name: "renamed.txt",
|
|
190
|
-
documentType: "text/markdown",
|
|
191
|
-
});
|
|
192
|
-
await reactor.mutate(document.header.id, [updateAction]);
|
|
193
|
-
await vi.waitFor(async () => {
|
|
194
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
195
|
-
expect(operations.global.results).toHaveLength(2);
|
|
196
|
-
});
|
|
197
|
-
// Verify the update
|
|
198
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
199
|
-
const globalState = updatedDocument.state.global;
|
|
200
|
-
const file = globalState.nodes.find((n) => n.id === fileId);
|
|
201
|
-
expect(file).toMatchObject({
|
|
202
|
-
id: fileId,
|
|
203
|
-
name: "renamed.txt",
|
|
204
|
-
documentType: "text/markdown",
|
|
205
|
-
kind: "file",
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
it("should update a node (folder) via reactor.mutate", async () => {
|
|
209
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
210
|
-
await storage.create(document);
|
|
211
|
-
// Add a folder first
|
|
212
|
-
const folderId = generateId();
|
|
213
|
-
const addAction = addFolder({
|
|
214
|
-
id: folderId,
|
|
215
|
-
name: "Original Folder",
|
|
216
|
-
parentFolder: null,
|
|
217
|
-
});
|
|
218
|
-
await reactor.mutate(document.header.id, [addAction]);
|
|
219
|
-
await vi.waitFor(async () => {
|
|
220
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
221
|
-
expect(operations.global.results).toHaveLength(1);
|
|
222
|
-
});
|
|
223
|
-
// Update the folder
|
|
224
|
-
const updateAction = updateNode({
|
|
225
|
-
id: folderId,
|
|
226
|
-
name: "Renamed Folder",
|
|
227
|
-
});
|
|
228
|
-
await reactor.mutate(document.header.id, [updateAction]);
|
|
229
|
-
await vi.waitFor(async () => {
|
|
230
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
231
|
-
expect(operations.global.results).toHaveLength(2);
|
|
232
|
-
});
|
|
233
|
-
// Verify the update
|
|
234
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
235
|
-
const globalState = updatedDocument.state.global;
|
|
236
|
-
const folder = globalState.nodes.find((n) => n.id === folderId);
|
|
237
|
-
expect(folder).toMatchObject({
|
|
238
|
-
id: folderId,
|
|
239
|
-
name: "Renamed Folder",
|
|
240
|
-
kind: "folder",
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
describe("DELETE Operations", () => {
|
|
245
|
-
it("should delete a node via reactor.mutate", async () => {
|
|
246
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
247
|
-
await storage.create(document);
|
|
248
|
-
// Add a folder first
|
|
249
|
-
const folderId = generateId();
|
|
250
|
-
const addAction = addFolder({
|
|
251
|
-
id: folderId,
|
|
252
|
-
name: "To Be Deleted",
|
|
253
|
-
parentFolder: null,
|
|
254
|
-
});
|
|
255
|
-
await reactor.mutate(document.header.id, [addAction]);
|
|
256
|
-
await vi.waitFor(async () => {
|
|
257
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
258
|
-
expect(operations.global.results).toHaveLength(1);
|
|
259
|
-
});
|
|
260
|
-
// Delete the folder
|
|
261
|
-
const deleteAction = deleteNode({
|
|
262
|
-
id: folderId,
|
|
263
|
-
});
|
|
264
|
-
await reactor.mutate(document.header.id, [deleteAction]);
|
|
265
|
-
await vi.waitFor(async () => {
|
|
266
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
267
|
-
expect(operations.global.results).toHaveLength(2);
|
|
268
|
-
});
|
|
269
|
-
// Verify the deletion
|
|
270
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
271
|
-
const globalState = updatedDocument.state.global;
|
|
272
|
-
const folder = globalState.nodes.find((n) => n.id === folderId);
|
|
273
|
-
expect(folder).toBeUndefined();
|
|
274
|
-
expect(globalState.nodes).toHaveLength(0);
|
|
275
|
-
});
|
|
276
|
-
it("should delete children when parent is deleted", async () => {
|
|
277
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
278
|
-
await storage.create(document);
|
|
279
|
-
// Create parent folder with children
|
|
280
|
-
const parentId = generateId();
|
|
281
|
-
const child1Id = generateId();
|
|
282
|
-
const child2Id = generateId();
|
|
283
|
-
const fileId = generateId();
|
|
284
|
-
const actions = [
|
|
285
|
-
addFolder({
|
|
286
|
-
id: parentId,
|
|
287
|
-
name: "Parent",
|
|
288
|
-
parentFolder: null,
|
|
289
|
-
}),
|
|
290
|
-
addFolder({
|
|
291
|
-
id: child1Id,
|
|
292
|
-
name: "Child 1",
|
|
293
|
-
parentFolder: parentId,
|
|
294
|
-
}),
|
|
295
|
-
addFolder({
|
|
296
|
-
id: child2Id,
|
|
297
|
-
name: "Child 2",
|
|
298
|
-
parentFolder: parentId,
|
|
299
|
-
}),
|
|
300
|
-
addFile({
|
|
301
|
-
id: fileId,
|
|
302
|
-
name: "file.txt",
|
|
303
|
-
documentType: "text/plain",
|
|
304
|
-
parentFolder: child1Id,
|
|
305
|
-
}),
|
|
306
|
-
];
|
|
307
|
-
await reactor.mutate(document.header.id, actions);
|
|
308
|
-
await vi.waitFor(async () => {
|
|
309
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
310
|
-
expect(operations.global.results).toHaveLength(4);
|
|
311
|
-
});
|
|
312
|
-
// Delete parent
|
|
313
|
-
const deleteAction = deleteNode({
|
|
314
|
-
id: parentId,
|
|
315
|
-
});
|
|
316
|
-
await reactor.mutate(document.header.id, [deleteAction]);
|
|
317
|
-
await vi.waitFor(async () => {
|
|
318
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
319
|
-
expect(operations.global.results).toHaveLength(5);
|
|
320
|
-
});
|
|
321
|
-
// Verify all nodes were deleted
|
|
322
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
323
|
-
const globalState = updatedDocument.state.global;
|
|
324
|
-
expect(globalState.nodes).toHaveLength(0);
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
describe("MOVE Operations", () => {
|
|
328
|
-
it("should move a node to a different parent", async () => {
|
|
329
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
330
|
-
await storage.create(document);
|
|
331
|
-
// Create folder structure
|
|
332
|
-
const folder1Id = generateId();
|
|
333
|
-
const folder2Id = generateId();
|
|
334
|
-
const childId = generateId();
|
|
335
|
-
const actions = [
|
|
336
|
-
addFolder({
|
|
337
|
-
id: folder1Id,
|
|
338
|
-
name: "Folder 1",
|
|
339
|
-
parentFolder: null,
|
|
340
|
-
}),
|
|
341
|
-
addFolder({
|
|
342
|
-
id: folder2Id,
|
|
343
|
-
name: "Folder 2",
|
|
344
|
-
parentFolder: null,
|
|
345
|
-
}),
|
|
346
|
-
addFolder({
|
|
347
|
-
id: childId,
|
|
348
|
-
name: "Child",
|
|
349
|
-
parentFolder: folder1Id,
|
|
350
|
-
}),
|
|
351
|
-
];
|
|
352
|
-
await reactor.mutate(document.header.id, actions);
|
|
353
|
-
await vi.waitFor(async () => {
|
|
354
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
355
|
-
expect(operations.global.results).toHaveLength(3);
|
|
356
|
-
});
|
|
357
|
-
// Move child from folder1 to folder2
|
|
358
|
-
const moveAction = moveNode({
|
|
359
|
-
srcFolder: childId,
|
|
360
|
-
targetParentFolder: folder2Id,
|
|
361
|
-
});
|
|
362
|
-
await reactor.mutate(document.header.id, [moveAction]);
|
|
363
|
-
await vi.waitFor(async () => {
|
|
364
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
365
|
-
expect(operations.global.results).toHaveLength(4);
|
|
366
|
-
});
|
|
367
|
-
// Verify the move
|
|
368
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
369
|
-
const globalState = updatedDocument.state.global;
|
|
370
|
-
const child = globalState.nodes.find((n) => n.id === childId);
|
|
371
|
-
expect(child).toBeDefined();
|
|
372
|
-
expect(child?.parentFolder).toBe(folder2Id);
|
|
373
|
-
});
|
|
374
|
-
it("should move a node to root when targetParentFolder is null", async () => {
|
|
375
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
376
|
-
await storage.create(document);
|
|
377
|
-
// Create nested folder
|
|
378
|
-
const parentId = generateId();
|
|
379
|
-
const childId = generateId();
|
|
380
|
-
const actions = [
|
|
381
|
-
addFolder({
|
|
382
|
-
id: parentId,
|
|
383
|
-
name: "Parent",
|
|
384
|
-
parentFolder: null,
|
|
385
|
-
}),
|
|
386
|
-
addFolder({
|
|
387
|
-
id: childId,
|
|
388
|
-
name: "Child",
|
|
389
|
-
parentFolder: parentId,
|
|
390
|
-
}),
|
|
391
|
-
];
|
|
392
|
-
await reactor.mutate(document.header.id, actions);
|
|
393
|
-
await vi.waitFor(async () => {
|
|
394
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
395
|
-
expect(operations.global.results).toHaveLength(2);
|
|
396
|
-
});
|
|
397
|
-
// Move child to root
|
|
398
|
-
const moveAction = moveNode({
|
|
399
|
-
srcFolder: childId,
|
|
400
|
-
targetParentFolder: null,
|
|
401
|
-
});
|
|
402
|
-
await reactor.mutate(document.header.id, [moveAction]);
|
|
403
|
-
await vi.waitFor(async () => {
|
|
404
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
405
|
-
expect(operations.global.results).toHaveLength(3);
|
|
406
|
-
});
|
|
407
|
-
// Verify the move
|
|
408
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
409
|
-
const globalState = updatedDocument.state.global;
|
|
410
|
-
const child = globalState.nodes.find((n) => n.id === childId);
|
|
411
|
-
expect(child).toBeDefined();
|
|
412
|
-
expect(child?.parentFolder).toBe(null);
|
|
413
|
-
});
|
|
414
|
-
it("should prevent moving folder to its descendant", async () => {
|
|
415
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
416
|
-
await storage.create(document);
|
|
417
|
-
// Create nested folders
|
|
418
|
-
const folder1Id = generateId();
|
|
419
|
-
const folder2Id = generateId();
|
|
420
|
-
const folder3Id = generateId();
|
|
421
|
-
const actions = [
|
|
422
|
-
addFolder({
|
|
423
|
-
id: folder1Id,
|
|
424
|
-
name: "Folder 1",
|
|
425
|
-
parentFolder: null,
|
|
426
|
-
}),
|
|
427
|
-
addFolder({
|
|
428
|
-
id: folder2Id,
|
|
429
|
-
name: "Folder 2",
|
|
430
|
-
parentFolder: folder1Id,
|
|
431
|
-
}),
|
|
432
|
-
addFolder({
|
|
433
|
-
id: folder3Id,
|
|
434
|
-
name: "Folder 3",
|
|
435
|
-
parentFolder: folder2Id,
|
|
436
|
-
}),
|
|
437
|
-
];
|
|
438
|
-
await reactor.mutate(document.header.id, actions);
|
|
439
|
-
await vi.waitFor(async () => {
|
|
440
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
441
|
-
expect(operations.global.results).toHaveLength(3);
|
|
442
|
-
});
|
|
443
|
-
// Try to move folder1 to folder3 (its descendant)
|
|
444
|
-
const moveAction = moveNode({
|
|
445
|
-
srcFolder: folder1Id,
|
|
446
|
-
targetParentFolder: folder3Id,
|
|
447
|
-
});
|
|
448
|
-
await reactor.mutate(document.header.id, [moveAction]);
|
|
449
|
-
// Wait a bit for potential processing
|
|
450
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
451
|
-
// The operation should have been rejected - verify folder1 is still at root
|
|
452
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
453
|
-
const globalState = updatedDocument.state.global;
|
|
454
|
-
const folder1 = globalState.nodes.find((n) => n.id === folder1Id);
|
|
455
|
-
expect(folder1).toBeDefined();
|
|
456
|
-
expect(folder1?.parentFolder).toBe(null);
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
describe("COPY Operations", () => {
|
|
460
|
-
it("should copy a node to a different parent", async () => {
|
|
461
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
462
|
-
await storage.create(document);
|
|
463
|
-
// Create folder structure
|
|
464
|
-
const folder1Id = generateId();
|
|
465
|
-
const folder2Id = generateId();
|
|
466
|
-
const sourceId = generateId();
|
|
467
|
-
const actions = [
|
|
468
|
-
addFolder({
|
|
469
|
-
id: folder1Id,
|
|
470
|
-
name: "Folder 1",
|
|
471
|
-
parentFolder: null,
|
|
472
|
-
}),
|
|
473
|
-
addFolder({
|
|
474
|
-
id: folder2Id,
|
|
475
|
-
name: "Folder 2",
|
|
476
|
-
parentFolder: null,
|
|
477
|
-
}),
|
|
478
|
-
addFolder({
|
|
479
|
-
id: sourceId,
|
|
480
|
-
name: "Source",
|
|
481
|
-
parentFolder: folder1Id,
|
|
482
|
-
}),
|
|
483
|
-
];
|
|
484
|
-
await reactor.mutate(document.header.id, actions);
|
|
485
|
-
await vi.waitFor(async () => {
|
|
486
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
487
|
-
expect(operations.global.results).toHaveLength(3);
|
|
488
|
-
});
|
|
489
|
-
// Copy source to folder2
|
|
490
|
-
const targetId = generateId();
|
|
491
|
-
const copyAction = copyNode({
|
|
492
|
-
srcId: sourceId,
|
|
493
|
-
targetId: targetId,
|
|
494
|
-
targetParentFolder: folder2Id,
|
|
495
|
-
});
|
|
496
|
-
await reactor.mutate(document.header.id, [copyAction]);
|
|
497
|
-
await vi.waitFor(async () => {
|
|
498
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
499
|
-
expect(operations.global.results).toHaveLength(4);
|
|
500
|
-
});
|
|
501
|
-
// Verify the copy
|
|
502
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
503
|
-
const globalState = updatedDocument.state.global;
|
|
504
|
-
// Original should still exist
|
|
505
|
-
const original = globalState.nodes.find((n) => n.id === sourceId);
|
|
506
|
-
expect(original).toBeDefined();
|
|
507
|
-
expect(original?.parentFolder).toBe(folder1Id);
|
|
508
|
-
// Copy should exist in new location
|
|
509
|
-
const copy = globalState.nodes.find((n) => n.id === targetId);
|
|
510
|
-
expect(copy).toBeDefined();
|
|
511
|
-
expect(copy?.parentFolder).toBe(folder2Id);
|
|
512
|
-
expect(copy?.name).toBe("Source");
|
|
513
|
-
});
|
|
514
|
-
it("should copy a node with a new name", async () => {
|
|
515
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
516
|
-
await storage.create(document);
|
|
517
|
-
// Create source folder
|
|
518
|
-
const sourceId = generateId();
|
|
519
|
-
const addAction = addFolder({
|
|
520
|
-
id: sourceId,
|
|
521
|
-
name: "Original Name",
|
|
522
|
-
parentFolder: null,
|
|
523
|
-
});
|
|
524
|
-
await reactor.mutate(document.header.id, [addAction]);
|
|
525
|
-
await vi.waitFor(async () => {
|
|
526
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
527
|
-
expect(operations.global.results).toHaveLength(1);
|
|
528
|
-
});
|
|
529
|
-
// Copy with new name
|
|
530
|
-
const targetId = generateId();
|
|
531
|
-
const copyAction = copyNode({
|
|
532
|
-
srcId: sourceId,
|
|
533
|
-
targetId: targetId,
|
|
534
|
-
targetName: "New Name",
|
|
535
|
-
targetParentFolder: null,
|
|
536
|
-
});
|
|
537
|
-
await reactor.mutate(document.header.id, [copyAction]);
|
|
538
|
-
await vi.waitFor(async () => {
|
|
539
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
540
|
-
expect(operations.global.results).toHaveLength(2);
|
|
541
|
-
});
|
|
542
|
-
// Verify the copy
|
|
543
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
544
|
-
const globalState = updatedDocument.state.global;
|
|
545
|
-
const copy = globalState.nodes.find((n) => n.id === targetId);
|
|
546
|
-
expect(copy).toBeDefined();
|
|
547
|
-
expect(copy?.name).toBe("New Name");
|
|
548
|
-
});
|
|
549
|
-
it("should copy a single node", async () => {
|
|
550
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
551
|
-
await storage.create(document);
|
|
552
|
-
// Create source structure
|
|
553
|
-
const parentId = generateId();
|
|
554
|
-
const child1Id = generateId();
|
|
555
|
-
const child2Id = generateId();
|
|
556
|
-
const fileId = generateId();
|
|
557
|
-
const actions = [
|
|
558
|
-
addFolder({
|
|
559
|
-
id: parentId,
|
|
560
|
-
name: "Parent",
|
|
561
|
-
parentFolder: null,
|
|
562
|
-
}),
|
|
563
|
-
addFolder({
|
|
564
|
-
id: child1Id,
|
|
565
|
-
name: "Child 1",
|
|
566
|
-
parentFolder: parentId,
|
|
567
|
-
}),
|
|
568
|
-
addFolder({
|
|
569
|
-
id: child2Id,
|
|
570
|
-
name: "Child 2",
|
|
571
|
-
parentFolder: parentId,
|
|
572
|
-
}),
|
|
573
|
-
addFile({
|
|
574
|
-
id: fileId,
|
|
575
|
-
name: "file.txt",
|
|
576
|
-
documentType: "text/plain",
|
|
577
|
-
parentFolder: child1Id,
|
|
578
|
-
}),
|
|
579
|
-
];
|
|
580
|
-
await reactor.mutate(document.header.id, actions);
|
|
581
|
-
await vi.waitFor(async () => {
|
|
582
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
583
|
-
expect(operations.global.results).toHaveLength(4);
|
|
584
|
-
});
|
|
585
|
-
// Copy the entire structure
|
|
586
|
-
const targetId = generateId();
|
|
587
|
-
const copyAction = copyNode({
|
|
588
|
-
srcId: parentId,
|
|
589
|
-
targetId: targetId,
|
|
590
|
-
targetParentFolder: null,
|
|
591
|
-
});
|
|
592
|
-
await reactor.mutate(document.header.id, [copyAction]);
|
|
593
|
-
await vi.waitFor(async () => {
|
|
594
|
-
const { document: doc } = await reactor.get(document.header.id);
|
|
595
|
-
const globalState = doc.state.global;
|
|
596
|
-
// Should have original 4 nodes + 1 copied node
|
|
597
|
-
expect(globalState.nodes.length).toBe(5);
|
|
598
|
-
});
|
|
599
|
-
// Verify the node was copied
|
|
600
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
601
|
-
const globalState = updatedDocument.state.global;
|
|
602
|
-
// Find the copied parent
|
|
603
|
-
const copiedParent = globalState.nodes.find((n) => n.id === targetId);
|
|
604
|
-
expect(copiedParent).toBeDefined();
|
|
605
|
-
// The name might have a suffix if there's a collision
|
|
606
|
-
expect(copiedParent?.name).toMatch(/^Parent( \(copy\)( \d+)?)?$/);
|
|
607
|
-
// Verify only the single node was copied (not children)
|
|
608
|
-
expect(globalState.nodes.length).toBe(5); // 4 original + 1 copied
|
|
609
|
-
// Verify original nodes still exist
|
|
610
|
-
const originalParent = globalState.nodes.find((n) => n.id === parentId);
|
|
611
|
-
const originalChild1 = globalState.nodes.find((n) => n.id === child1Id);
|
|
612
|
-
const originalChild2 = globalState.nodes.find((n) => n.id === child2Id);
|
|
613
|
-
const originalFile = globalState.nodes.find((n) => n.id === fileId);
|
|
614
|
-
expect(originalParent).toBeDefined();
|
|
615
|
-
expect(originalChild1).toBeDefined();
|
|
616
|
-
expect(originalChild2).toBeDefined();
|
|
617
|
-
expect(originalFile).toBeDefined();
|
|
618
|
-
// The copied node should not have children automatically copied
|
|
619
|
-
const copiedNodeChildren = globalState.nodes.filter((n) => n.parentFolder === targetId);
|
|
620
|
-
expect(copiedNodeChildren.length).toBe(0);
|
|
621
|
-
});
|
|
622
|
-
});
|
|
623
|
-
describe("Drive-level Operations", () => {
|
|
624
|
-
it("should set drive name via reactor.mutate", async () => {
|
|
625
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
626
|
-
await storage.create(document);
|
|
627
|
-
// Set drive name
|
|
628
|
-
const action = setDriveName({
|
|
629
|
-
name: "My Drive",
|
|
630
|
-
});
|
|
631
|
-
await reactor.mutate(document.header.id, [action]);
|
|
632
|
-
await vi.waitFor(async () => {
|
|
633
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
634
|
-
expect(operations.global.results).toHaveLength(1);
|
|
635
|
-
});
|
|
636
|
-
// Verify the drive name was set
|
|
637
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
638
|
-
const globalState = updatedDocument.state.global;
|
|
639
|
-
expect(globalState.name).toBe("My Drive");
|
|
640
|
-
});
|
|
641
|
-
it("should set drive icon via reactor.mutate", async () => {
|
|
642
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
643
|
-
await storage.create(document);
|
|
644
|
-
// Set drive icon
|
|
645
|
-
const action = setDriveIcon({
|
|
646
|
-
icon: "folder-open",
|
|
647
|
-
});
|
|
648
|
-
await reactor.mutate(document.header.id, [action]);
|
|
649
|
-
await vi.waitFor(async () => {
|
|
650
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
651
|
-
expect(operations.global.results).toHaveLength(1);
|
|
652
|
-
});
|
|
653
|
-
// Verify the drive icon was set
|
|
654
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
655
|
-
const globalState = updatedDocument.state.global;
|
|
656
|
-
expect(globalState.icon).toBe("folder-open");
|
|
657
|
-
});
|
|
658
|
-
it("should set sharing type via reactor.mutate", async () => {
|
|
659
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
660
|
-
await storage.create(document);
|
|
661
|
-
// Set sharing type (note: this is a local operation)
|
|
662
|
-
const action = setSharingType({
|
|
663
|
-
type: "PUBLIC",
|
|
664
|
-
});
|
|
665
|
-
await reactor.mutate(document.header.id, [action]);
|
|
666
|
-
await vi.waitFor(async () => {
|
|
667
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
668
|
-
expect(operations.local.results).toHaveLength(1);
|
|
669
|
-
});
|
|
670
|
-
// Verify the sharing type was set
|
|
671
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
672
|
-
const localState = updatedDocument.state.local;
|
|
673
|
-
expect(localState.sharingType).toBe("PUBLIC");
|
|
674
|
-
});
|
|
675
|
-
it("should set available offline via reactor.mutate", async () => {
|
|
676
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
677
|
-
await storage.create(document);
|
|
678
|
-
// Set available offline (note: this is a local operation)
|
|
679
|
-
const action = setAvailableOffline({
|
|
680
|
-
availableOffline: true,
|
|
681
|
-
});
|
|
682
|
-
await reactor.mutate(document.header.id, [action]);
|
|
683
|
-
await vi.waitFor(async () => {
|
|
684
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
685
|
-
expect(operations.local.results).toHaveLength(1);
|
|
686
|
-
});
|
|
687
|
-
// Verify available offline was set
|
|
688
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
689
|
-
const localState = updatedDocument.state.local;
|
|
690
|
-
expect(localState.availableOffline).toBe(true);
|
|
691
|
-
});
|
|
692
|
-
});
|
|
693
|
-
describe("Batch Operations", () => {
|
|
694
|
-
it("should process multiple operations in a single mutate call", async () => {
|
|
695
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
696
|
-
await storage.create(document);
|
|
697
|
-
// Create multiple operations
|
|
698
|
-
const folder1Id = generateId();
|
|
699
|
-
const folder2Id = generateId();
|
|
700
|
-
const file1Id = generateId();
|
|
701
|
-
const file2Id = generateId();
|
|
702
|
-
const actions = [
|
|
703
|
-
setDriveName({
|
|
704
|
-
name: "Multi-Op Drive",
|
|
705
|
-
}),
|
|
706
|
-
addFolder({
|
|
707
|
-
id: folder1Id,
|
|
708
|
-
name: "Folder 1",
|
|
709
|
-
parentFolder: null,
|
|
710
|
-
}),
|
|
711
|
-
addFolder({
|
|
712
|
-
id: folder2Id,
|
|
713
|
-
name: "Folder 2",
|
|
714
|
-
parentFolder: null,
|
|
715
|
-
}),
|
|
716
|
-
addFile({
|
|
717
|
-
id: file1Id,
|
|
718
|
-
name: "file1.txt",
|
|
719
|
-
documentType: "text/plain",
|
|
720
|
-
parentFolder: folder1Id,
|
|
721
|
-
}),
|
|
722
|
-
addFile({
|
|
723
|
-
id: file2Id,
|
|
724
|
-
name: "file2.txt",
|
|
725
|
-
documentType: "text/plain",
|
|
726
|
-
parentFolder: folder2Id,
|
|
727
|
-
}),
|
|
728
|
-
];
|
|
729
|
-
// Submit all at once
|
|
730
|
-
await reactor.mutate(document.header.id, actions);
|
|
731
|
-
await vi.waitFor(async () => {
|
|
732
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
733
|
-
expect(operations.global.results).toHaveLength(5);
|
|
734
|
-
});
|
|
735
|
-
// Verify all operations were applied
|
|
736
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
737
|
-
const globalState = updatedDocument.state.global;
|
|
738
|
-
expect(globalState.name).toBe("Multi-Op Drive");
|
|
739
|
-
expect(globalState.nodes).toHaveLength(4);
|
|
740
|
-
// Verify structure
|
|
741
|
-
const folder1 = globalState.nodes.find((n) => n.id === folder1Id);
|
|
742
|
-
const folder2 = globalState.nodes.find((n) => n.id === folder2Id);
|
|
743
|
-
const file1 = globalState.nodes.find((n) => n.id === file1Id);
|
|
744
|
-
const file2 = globalState.nodes.find((n) => n.id === file2Id);
|
|
745
|
-
expect(folder1).toBeDefined();
|
|
746
|
-
expect(folder2).toBeDefined();
|
|
747
|
-
expect(file1).toBeDefined();
|
|
748
|
-
expect(file1?.parentFolder).toBe(folder1Id);
|
|
749
|
-
expect(file2).toBeDefined();
|
|
750
|
-
expect(file2?.parentFolder).toBe(folder2Id);
|
|
751
|
-
});
|
|
752
|
-
it("should maintain operation order in batch processing", async () => {
|
|
753
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
754
|
-
await storage.create(document);
|
|
755
|
-
// Operations that depend on each other
|
|
756
|
-
const folderId = generateId();
|
|
757
|
-
const fileId = generateId();
|
|
758
|
-
const actions = [
|
|
759
|
-
// Create folder
|
|
760
|
-
addFolder({
|
|
761
|
-
id: folderId,
|
|
762
|
-
name: "Original Name",
|
|
763
|
-
parentFolder: null,
|
|
764
|
-
}),
|
|
765
|
-
// Add file to folder
|
|
766
|
-
addFile({
|
|
767
|
-
id: fileId,
|
|
768
|
-
name: "test.txt",
|
|
769
|
-
documentType: "text/plain",
|
|
770
|
-
parentFolder: folderId,
|
|
771
|
-
}),
|
|
772
|
-
// Rename folder
|
|
773
|
-
updateNode({
|
|
774
|
-
id: folderId,
|
|
775
|
-
name: "Updated Name",
|
|
776
|
-
}),
|
|
777
|
-
// Update file
|
|
778
|
-
updateFile({
|
|
779
|
-
id: fileId,
|
|
780
|
-
documentType: "text/markdown",
|
|
781
|
-
}),
|
|
782
|
-
];
|
|
783
|
-
await reactor.mutate(document.header.id, actions);
|
|
784
|
-
await vi.waitFor(async () => {
|
|
785
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
786
|
-
expect(operations.global.results).toHaveLength(4);
|
|
787
|
-
});
|
|
788
|
-
// Verify final state
|
|
789
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
790
|
-
const globalState = updatedDocument.state.global;
|
|
791
|
-
const folder = globalState.nodes.find((n) => n.id === folderId);
|
|
792
|
-
const file = globalState.nodes.find((n) => n.id === fileId);
|
|
793
|
-
expect(folder?.name).toBe("Updated Name");
|
|
794
|
-
expect(file.documentType).toBe("text/markdown");
|
|
795
|
-
});
|
|
796
|
-
});
|
|
797
|
-
describe("Error Handling", () => {
|
|
798
|
-
it("should handle invalid node references gracefully", async () => {
|
|
799
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
800
|
-
await storage.create(document);
|
|
801
|
-
// Try to add a file to a non-existent folder
|
|
802
|
-
const fileId = generateId();
|
|
803
|
-
const action = addFile({
|
|
804
|
-
id: fileId,
|
|
805
|
-
name: "orphan.txt",
|
|
806
|
-
documentType: "text/plain",
|
|
807
|
-
parentFolder: "non-existent-folder",
|
|
808
|
-
});
|
|
809
|
-
await reactor.mutate(document.header.id, [action]);
|
|
810
|
-
// Wait a bit for potential processing
|
|
811
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
812
|
-
// The operation should have been attempted but may have failed
|
|
813
|
-
// Check that the document state is still valid
|
|
814
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
815
|
-
const globalState = updatedDocument.state.global;
|
|
816
|
-
// File might exist even with invalid parent (depends on reducer logic)
|
|
817
|
-
// The important thing is that the system didn't crash
|
|
818
|
-
const file = globalState.nodes.find((n) => n.id === fileId);
|
|
819
|
-
// Either the file doesn't exist or exists with the invalid parent
|
|
820
|
-
if (file) {
|
|
821
|
-
expect(file.parentFolder).toBe("non-existent-folder");
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
it("should handle duplicate node IDs", async () => {
|
|
825
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
826
|
-
await storage.create(document);
|
|
827
|
-
const duplicateId = generateId();
|
|
828
|
-
// Try to create two folders with the same ID
|
|
829
|
-
const actions = [
|
|
830
|
-
addFolder({
|
|
831
|
-
id: duplicateId,
|
|
832
|
-
name: "First",
|
|
833
|
-
parentFolder: null,
|
|
834
|
-
}),
|
|
835
|
-
addFolder({
|
|
836
|
-
id: duplicateId,
|
|
837
|
-
name: "Second",
|
|
838
|
-
parentFolder: null,
|
|
839
|
-
}),
|
|
840
|
-
];
|
|
841
|
-
await reactor.mutate(document.header.id, actions);
|
|
842
|
-
await vi.waitFor(async () => {
|
|
843
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
844
|
-
// At least one operation should have been processed
|
|
845
|
-
expect(operations.global.results.length).toBeGreaterThanOrEqual(1);
|
|
846
|
-
});
|
|
847
|
-
// Only one node with the ID should exist
|
|
848
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
849
|
-
const globalState = updatedDocument.state.global;
|
|
850
|
-
const nodesWithId = globalState.nodes.filter((n) => n.id === duplicateId);
|
|
851
|
-
expect(nodesWithId).toHaveLength(1);
|
|
852
|
-
});
|
|
853
|
-
it("should handle name collisions", async () => {
|
|
854
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
855
|
-
await storage.create(document);
|
|
856
|
-
const folder1Id = generateId();
|
|
857
|
-
const folder2Id = generateId();
|
|
858
|
-
// Try to create two folders with the same name in the same location
|
|
859
|
-
const actions = [
|
|
860
|
-
addFolder({
|
|
861
|
-
id: folder1Id,
|
|
862
|
-
name: "Duplicate Name",
|
|
863
|
-
parentFolder: null,
|
|
864
|
-
}),
|
|
865
|
-
addFolder({
|
|
866
|
-
id: folder2Id,
|
|
867
|
-
name: "Duplicate Name",
|
|
868
|
-
parentFolder: null,
|
|
869
|
-
}),
|
|
870
|
-
];
|
|
871
|
-
await reactor.mutate(document.header.id, actions);
|
|
872
|
-
await vi.waitFor(async () => {
|
|
873
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
874
|
-
// At least one operation should have been processed
|
|
875
|
-
expect(operations.global.results.length).toBeGreaterThanOrEqual(1);
|
|
876
|
-
});
|
|
877
|
-
// Check how the system handled the collision
|
|
878
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
879
|
-
const globalState = updatedDocument.state.global;
|
|
880
|
-
const foldersWithName = globalState.nodes.filter((n) => n.name === "Duplicate Name" || n.name.startsWith("Duplicate Name"));
|
|
881
|
-
// System should have handled the collision somehow
|
|
882
|
-
expect(foldersWithName.length).toBeGreaterThanOrEqual(1);
|
|
883
|
-
});
|
|
884
|
-
it("should continue processing after encountering an error", async () => {
|
|
885
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
886
|
-
await storage.create(document);
|
|
887
|
-
const folder1Id = generateId();
|
|
888
|
-
const folder2Id = generateId();
|
|
889
|
-
const actions = [
|
|
890
|
-
// Valid operation
|
|
891
|
-
addFolder({
|
|
892
|
-
id: folder1Id,
|
|
893
|
-
name: "Valid Folder 1",
|
|
894
|
-
parentFolder: null,
|
|
895
|
-
}),
|
|
896
|
-
// Invalid operation - moving non-existent node
|
|
897
|
-
moveNode({
|
|
898
|
-
srcFolder: "non-existent",
|
|
899
|
-
targetParentFolder: folder1Id,
|
|
900
|
-
}),
|
|
901
|
-
// Valid operation
|
|
902
|
-
addFolder({
|
|
903
|
-
id: folder2Id,
|
|
904
|
-
name: "Valid Folder 2",
|
|
905
|
-
parentFolder: null,
|
|
906
|
-
}),
|
|
907
|
-
];
|
|
908
|
-
await reactor.mutate(document.header.id, actions);
|
|
909
|
-
await vi.waitFor(async () => {
|
|
910
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
911
|
-
// At least some operations should have been processed
|
|
912
|
-
expect(operations.global.results.length).toBeGreaterThanOrEqual(1);
|
|
913
|
-
});
|
|
914
|
-
// Check that valid operations were processed
|
|
915
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
916
|
-
const globalState = updatedDocument.state.global;
|
|
917
|
-
const folder1 = globalState.nodes.find((n) => n.id === folder1Id);
|
|
918
|
-
const folder2 = globalState.nodes.find((n) => n.id === folder2Id);
|
|
919
|
-
// At least one of the valid operations should have succeeded
|
|
920
|
-
expect(folder1 || folder2).toBeDefined();
|
|
921
|
-
});
|
|
922
|
-
});
|
|
923
|
-
describe("Complex Scenarios", () => {
|
|
924
|
-
it("should handle complex file reorganization", async () => {
|
|
925
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
926
|
-
await storage.create(document);
|
|
927
|
-
// Create initial structure
|
|
928
|
-
const docsId = generateId();
|
|
929
|
-
const imagesId = generateId();
|
|
930
|
-
const tempId = generateId();
|
|
931
|
-
const doc1Id = generateId();
|
|
932
|
-
const doc2Id = generateId();
|
|
933
|
-
const img1Id = generateId();
|
|
934
|
-
const setupActions = [
|
|
935
|
-
addFolder({
|
|
936
|
-
id: docsId,
|
|
937
|
-
name: "Documents",
|
|
938
|
-
parentFolder: null,
|
|
939
|
-
}),
|
|
940
|
-
addFolder({
|
|
941
|
-
id: imagesId,
|
|
942
|
-
name: "Images",
|
|
943
|
-
parentFolder: null,
|
|
944
|
-
}),
|
|
945
|
-
addFolder({
|
|
946
|
-
id: tempId,
|
|
947
|
-
name: "Temp",
|
|
948
|
-
parentFolder: null,
|
|
949
|
-
}),
|
|
950
|
-
addFile({
|
|
951
|
-
id: doc1Id,
|
|
952
|
-
name: "report.docx",
|
|
953
|
-
documentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
954
|
-
parentFolder: tempId,
|
|
955
|
-
}),
|
|
956
|
-
addFile({
|
|
957
|
-
id: doc2Id,
|
|
958
|
-
name: "presentation.pptx",
|
|
959
|
-
documentType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
960
|
-
parentFolder: tempId,
|
|
961
|
-
}),
|
|
962
|
-
addFile({
|
|
963
|
-
id: img1Id,
|
|
964
|
-
name: "logo.png",
|
|
965
|
-
documentType: "image/png",
|
|
966
|
-
parentFolder: tempId,
|
|
967
|
-
}),
|
|
968
|
-
];
|
|
969
|
-
await reactor.mutate(document.header.id, setupActions);
|
|
970
|
-
await vi.waitFor(async () => {
|
|
971
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
972
|
-
expect(operations.global.results).toHaveLength(6);
|
|
973
|
-
});
|
|
974
|
-
// Reorganize files
|
|
975
|
-
const reorganizeActions = [
|
|
976
|
-
// Move documents to Documents folder
|
|
977
|
-
moveNode({
|
|
978
|
-
srcFolder: doc1Id,
|
|
979
|
-
targetParentFolder: docsId,
|
|
980
|
-
}),
|
|
981
|
-
moveNode({
|
|
982
|
-
srcFolder: doc2Id,
|
|
983
|
-
targetParentFolder: docsId,
|
|
984
|
-
}),
|
|
985
|
-
// Move image to Images folder
|
|
986
|
-
moveNode({
|
|
987
|
-
srcFolder: img1Id,
|
|
988
|
-
targetParentFolder: imagesId,
|
|
989
|
-
}),
|
|
990
|
-
// Delete temp folder
|
|
991
|
-
deleteNode({
|
|
992
|
-
id: tempId,
|
|
993
|
-
}),
|
|
994
|
-
];
|
|
995
|
-
await reactor.mutate(document.header.id, reorganizeActions);
|
|
996
|
-
await vi.waitFor(async () => {
|
|
997
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
998
|
-
expect(operations.global.results).toHaveLength(10);
|
|
999
|
-
});
|
|
1000
|
-
// Verify final structure
|
|
1001
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
1002
|
-
const globalState = updatedDocument.state.global;
|
|
1003
|
-
// Temp folder should be gone
|
|
1004
|
-
const temp = globalState.nodes.find((n) => n.id === tempId);
|
|
1005
|
-
expect(temp).toBeUndefined();
|
|
1006
|
-
// Files should be in correct folders
|
|
1007
|
-
const doc1 = globalState.nodes.find((n) => n.id === doc1Id);
|
|
1008
|
-
const doc2 = globalState.nodes.find((n) => n.id === doc2Id);
|
|
1009
|
-
const img1 = globalState.nodes.find((n) => n.id === img1Id);
|
|
1010
|
-
expect(doc1?.parentFolder).toBe(docsId);
|
|
1011
|
-
expect(doc2?.parentFolder).toBe(docsId);
|
|
1012
|
-
expect(img1?.parentFolder).toBe(imagesId);
|
|
1013
|
-
});
|
|
1014
|
-
it("should handle project template creation", async () => {
|
|
1015
|
-
const document = driveDocumentModelModule.utils.createDocument();
|
|
1016
|
-
await storage.create(document);
|
|
1017
|
-
// Create a project template structure
|
|
1018
|
-
const projectId = generateId();
|
|
1019
|
-
const srcId = generateId();
|
|
1020
|
-
const testsId = generateId();
|
|
1021
|
-
const docsId = generateId();
|
|
1022
|
-
const configId = generateId();
|
|
1023
|
-
const mainFileId = generateId();
|
|
1024
|
-
const testFileId = generateId();
|
|
1025
|
-
const readmeId = generateId();
|
|
1026
|
-
const configFileId = generateId();
|
|
1027
|
-
const templateActions = [
|
|
1028
|
-
setDriveName({
|
|
1029
|
-
name: "My Project",
|
|
1030
|
-
}),
|
|
1031
|
-
addFolder({
|
|
1032
|
-
id: projectId,
|
|
1033
|
-
name: "my-project",
|
|
1034
|
-
parentFolder: null,
|
|
1035
|
-
}),
|
|
1036
|
-
addFolder({
|
|
1037
|
-
id: srcId,
|
|
1038
|
-
name: "src",
|
|
1039
|
-
parentFolder: projectId,
|
|
1040
|
-
}),
|
|
1041
|
-
addFolder({
|
|
1042
|
-
id: testsId,
|
|
1043
|
-
name: "tests",
|
|
1044
|
-
parentFolder: projectId,
|
|
1045
|
-
}),
|
|
1046
|
-
addFolder({
|
|
1047
|
-
id: docsId,
|
|
1048
|
-
name: "docs",
|
|
1049
|
-
parentFolder: projectId,
|
|
1050
|
-
}),
|
|
1051
|
-
addFolder({
|
|
1052
|
-
id: configId,
|
|
1053
|
-
name: "config",
|
|
1054
|
-
parentFolder: projectId,
|
|
1055
|
-
}),
|
|
1056
|
-
addFile({
|
|
1057
|
-
id: mainFileId,
|
|
1058
|
-
name: "index.ts",
|
|
1059
|
-
documentType: "text/typescript",
|
|
1060
|
-
parentFolder: srcId,
|
|
1061
|
-
}),
|
|
1062
|
-
addFile({
|
|
1063
|
-
id: testFileId,
|
|
1064
|
-
name: "index.test.ts",
|
|
1065
|
-
documentType: "text/typescript",
|
|
1066
|
-
parentFolder: testsId,
|
|
1067
|
-
}),
|
|
1068
|
-
addFile({
|
|
1069
|
-
id: readmeId,
|
|
1070
|
-
name: "README.md",
|
|
1071
|
-
documentType: "text/markdown",
|
|
1072
|
-
parentFolder: projectId,
|
|
1073
|
-
}),
|
|
1074
|
-
addFile({
|
|
1075
|
-
id: configFileId,
|
|
1076
|
-
name: "tsconfig.json",
|
|
1077
|
-
documentType: "application/json",
|
|
1078
|
-
parentFolder: configId,
|
|
1079
|
-
}),
|
|
1080
|
-
];
|
|
1081
|
-
await reactor.mutate(document.header.id, templateActions);
|
|
1082
|
-
await vi.waitFor(async () => {
|
|
1083
|
-
const operations = await reactor.getOperations(document.header.id);
|
|
1084
|
-
expect(operations.global.results).toHaveLength(10);
|
|
1085
|
-
});
|
|
1086
|
-
// Verify the complete structure
|
|
1087
|
-
const { document: updatedDocument } = await reactor.get(document.header.id);
|
|
1088
|
-
const globalState = updatedDocument.state.global;
|
|
1089
|
-
expect(globalState.name).toBe("My Project");
|
|
1090
|
-
expect(globalState.nodes).toHaveLength(9); // 5 folders + 4 files
|
|
1091
|
-
// Verify hierarchy
|
|
1092
|
-
const project = globalState.nodes.find((n) => n.id === projectId);
|
|
1093
|
-
expect(project?.parentFolder).toBe(null);
|
|
1094
|
-
const src = globalState.nodes.find((n) => n.id === srcId);
|
|
1095
|
-
expect(src?.parentFolder).toBe(projectId);
|
|
1096
|
-
const mainFile = globalState.nodes.find((n) => n.id === mainFileId);
|
|
1097
|
-
expect(mainFile?.parentFolder).toBe(srcId);
|
|
1098
|
-
expect(mainFile.documentType).toBe("text/typescript");
|
|
1099
|
-
});
|
|
1100
|
-
});
|
|
1101
|
-
});
|
|
1102
|
-
//# sourceMappingURL=document-drive-integration.test.js.map
|