Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 72 additions & 42 deletions extension/src/services/__tests__/Storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,44 @@ import {
Storage,
} from "../../services/Storage.ts";

const StorageLive = Layer.empty.pipe(
Layer.provideMerge(Storage.Default),
Layer.provide(TestVsCode.Default),
Layer.provideMerge(
Layer.succeed(ExtensionContext, {
globalState: new Memento(),
workspaceState: new Memento(),
}),
),
);

it.layer(StorageLive)("Storage", (it) => {
const key = createStorageKey("key", Schema.Struct({ value: Schema.Int }));
const withTestCtx = Effect.fnUntraced(function* (
ctx: { globalState?: Memento; workspaceState?: Memento } = {},
) {
const vscode = yield* TestVsCode.make();
const layer = Layer.empty.pipe(
Layer.provideMerge(Storage.Default),
Layer.provide(TestVsCode.Default),
Layer.provideMerge(
Layer.succeed(ExtensionContext, {
globalState: ctx.globalState ?? new Memento(),
workspaceState: ctx.workspaceState ?? new Memento(),
}),
),
);
return {
key: createStorageKey("key", Schema.Struct({ value: Schema.Int })),
layer,
vscode,
};
});

it.effect(
"should return Option.None when no entry",
Effect.fnUntraced(function* () {
it.effect(
"should return Option.None when no entry",
Effect.fnUntraced(function* () {
const { key, layer } = yield* withTestCtx();
yield* Effect.gen(function* () {
const storage = yield* Storage;
const value = yield* storage.workspace.get(key);
assert(Option.isOption(value));
}),
);
}).pipe(Effect.provide(layer));
}),
);

it.effect(
"should fallback to default without updating storage",
Effect.fnUntraced(function* () {
it.effect(
"should fallback to default without updating storage",
Effect.fnUntraced(function* () {
const { key, layer } = yield* withTestCtx();
yield* Effect.gen(function* () {
const storage = yield* Storage;
const defaultValue = { value: 1 };

Expand All @@ -47,12 +59,15 @@ it.layer(StorageLive)("Storage", (it) => {
"workspaceState": {},
}
`);
}),
);
}).pipe(Effect.provide(layer));
}),
);

it.effect(
"should encode value into the underlying store",
Effect.fnUntraced(function* () {
it.effect(
"should encode value into the underlying store",
Effect.fnUntraced(function* () {
const { key, layer } = yield* withTestCtx();
yield* Effect.gen(function* () {
const storage = yield* Storage;
yield* storage.workspace.set(key, { value: 2 });

Expand All @@ -67,12 +82,20 @@ it.layer(StorageLive)("Storage", (it) => {
},
}
`);
}),
);
}).pipe(Effect.provide(layer));
}),
);

it.effect(
"should replace existing value in the underlying store",
Effect.fnUntraced(function* () {
it.effect(
"should replace existing value in the underlying store",
Effect.fnUntraced(function* () {
// initial state
const workspaceState = new Memento();
workspaceState.update("key", { value: 2 });

const { key, layer } = yield* withTestCtx({ workspaceState });

yield* Effect.gen(function* () {
const storage = yield* Storage;
yield* storage.workspace.set(key, { value: 3 });

Expand All @@ -87,17 +110,24 @@ it.layer(StorageLive)("Storage", (it) => {
},
}
`);
}),
);
}).pipe(Effect.provide(layer));
}),
);

it.effect(
"should throw StorageDecodeError badly encoded value",
Effect.fnUntraced(function* () {
const workspaceState = new Memento();
workspaceState.update("key", "blah");

it.effect.fails(
"should throw StorageDecodeError badly encoded value",
Effect.fnUntraced(function* () {
const { key, layer } = yield* withTestCtx({ workspaceState });

yield* Effect.gen(function* () {
const storage = yield* Storage;
const context = yield* ExtensionContext;
const result = yield* Effect.either(storage.workspace.get(key));

yield* Effect.promise(() => context.workspaceState.update("key", "blah"));
yield* storage.workspace.get(key);
}),
);
});
assert(result._tag === "Left", "Expected to fail decoding");
assert(result.left._tag === "StorageDecodeError");
}).pipe(Effect.provide(layer));
}),
);