Extract helper and lint
This commit is contained in:
parent
5844e282e2
commit
e186a593ff
2 changed files with 61 additions and 37 deletions
|
|
@ -1,17 +1,26 @@
|
||||||
import { FileSystemOperations } from "sync-client";
|
import type { FileSystemOperations } from "sync-client";
|
||||||
import type { RelativePath } from "../persistence/database";
|
import type { Database, RelativePath } from "../persistence/database";
|
||||||
import { FileOperations } from "./file-operations";
|
import { FileOperations } from "./file-operations";
|
||||||
import { Logger } from "../tracing/logger";
|
import { Logger } from "../tracing/logger";
|
||||||
import assert from "assert";
|
import { assertSetContainsExactly } from "src/utils/assert-set-contains-exactly";
|
||||||
|
|
||||||
describe("File operations", () => {
|
describe("File operations", () => {
|
||||||
|
class MockDatabase {
|
||||||
|
public async updatePath(
|
||||||
|
_oldRelativePath: RelativePath,
|
||||||
|
_newRelativePath: RelativePath
|
||||||
|
): Promise<void> {
|
||||||
|
// this is called but irrelevant for this mock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FakeFileSystemOperations implements FileSystemOperations {
|
class FakeFileSystemOperations implements FileSystemOperations {
|
||||||
public readonly names = new Set<string>();
|
public readonly names = new Set<string>();
|
||||||
|
|
||||||
public listAllFiles(): Promise<RelativePath[]> {
|
public async listAllFiles(): Promise<RelativePath[]> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public read(path: RelativePath): Promise<Uint8Array> {
|
public async read(_path: RelativePath): Promise<Uint8Array> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public async write(
|
public async write(
|
||||||
|
|
@ -20,23 +29,25 @@ describe("File operations", () => {
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.names.add(path);
|
this.names.add(path);
|
||||||
}
|
}
|
||||||
public atomicUpdateText(
|
public async atomicUpdateText(
|
||||||
path: RelativePath,
|
_path: RelativePath,
|
||||||
updater: (currentContent: string) => string
|
_updater: (currentContent: string) => string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public getFileSize(path: RelativePath): Promise<number> {
|
public async getFileSize(_path: RelativePath): Promise<number> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public getModificationTime(path: RelativePath): Promise<Date> {
|
public async getModificationTime(_path: RelativePath): Promise<Date> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public async exists(path: RelativePath): Promise<boolean> {
|
public async exists(path: RelativePath): Promise<boolean> {
|
||||||
return this.names.has(path);
|
return this.names.has(path);
|
||||||
}
|
}
|
||||||
public async createDirectory(path: RelativePath): Promise<void> {}
|
public async createDirectory(_path: RelativePath): Promise<void> {
|
||||||
public delete(path: RelativePath): Promise<void> {
|
// this is called but irrelevant for this mock
|
||||||
|
}
|
||||||
|
public async delete(_path: RelativePath): Promise<void> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
public async rename(
|
public async rename(
|
||||||
|
|
@ -49,54 +60,54 @@ describe("File operations", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should deconflict renames", async () => {
|
test("should deconflict renames", async () => {
|
||||||
let fs = new FakeFileSystemOperations();
|
const fs = new FakeFileSystemOperations();
|
||||||
let fileOperations = new FileOperations(new Logger(), fs);
|
const fileOperations = new FileOperations(
|
||||||
|
new Logger(),
|
||||||
|
new MockDatabase() as Database, // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
fs
|
||||||
|
);
|
||||||
|
|
||||||
await fileOperations.create("a", new Uint8Array());
|
await fileOperations.create("a", new Uint8Array());
|
||||||
assertSetOnlyContains(fs.names, "a");
|
assertSetContainsExactly(fs.names, "a");
|
||||||
await fileOperations.move("a", "b");
|
await fileOperations.move("a", "b");
|
||||||
assertSetOnlyContains(fs.names, "b");
|
assertSetContainsExactly(fs.names, "b");
|
||||||
|
|
||||||
await fileOperations.create("c", new Uint8Array());
|
await fileOperations.create("c", new Uint8Array());
|
||||||
assertSetOnlyContains(fs.names, "b", "c");
|
assertSetContainsExactly(fs.names, "b", "c");
|
||||||
|
|
||||||
await fileOperations.move("c", "b");
|
await fileOperations.move("c", "b");
|
||||||
assertSetOnlyContains(fs.names, "b", "b (1)");
|
assertSetContainsExactly(fs.names, "b", "b (1)");
|
||||||
|
|
||||||
await fileOperations.create("c", new Uint8Array());
|
await fileOperations.create("c", new Uint8Array());
|
||||||
await fileOperations.move("c", "b");
|
await fileOperations.move("c", "b");
|
||||||
assertSetOnlyContains(fs.names, "b", "b (1)", "b (2)");
|
assertSetContainsExactly(fs.names, "b", "b (1)", "b (2)");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should deconflict renames with file extension", async () => {
|
test("should deconflict renames with file extension", async () => {
|
||||||
let fs = new FakeFileSystemOperations();
|
const fs = new FakeFileSystemOperations();
|
||||||
let fileOperations = new FileOperations(new Logger(), fs);
|
const fileOperations = new FileOperations(
|
||||||
|
new Logger(),
|
||||||
|
new MockDatabase() as Database, // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
fs
|
||||||
|
);
|
||||||
|
|
||||||
await fileOperations.create("b.md", new Uint8Array());
|
await fileOperations.create("b.md", new Uint8Array());
|
||||||
await fileOperations.create("c.md", new Uint8Array());
|
await fileOperations.create("c.md", new Uint8Array());
|
||||||
await fileOperations.move("c.md", "b.md");
|
await fileOperations.move("c.md", "b.md");
|
||||||
assertSetOnlyContains(fs.names, "b.md", "b (1).md");
|
assertSetContainsExactly(fs.names, "b.md", "b (1).md");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should deconflict renames with paths", async () => {
|
test("should deconflict renames with paths", async () => {
|
||||||
let fs = new FakeFileSystemOperations();
|
const fs = new FakeFileSystemOperations();
|
||||||
let fileOperations = new FileOperations(new Logger(), fs);
|
const fileOperations = new FileOperations(
|
||||||
|
new Logger(),
|
||||||
|
new MockDatabase() as Database, // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
fs
|
||||||
|
);
|
||||||
|
|
||||||
await fileOperations.create("a/b.c/d", new Uint8Array());
|
await fileOperations.create("a/b.c/d", new Uint8Array());
|
||||||
await fileOperations.create("a/b.c/e", new Uint8Array());
|
await fileOperations.create("a/b.c/e", new Uint8Array());
|
||||||
await fileOperations.move("a/b.c/d", "a/b.c/e");
|
await fileOperations.move("a/b.c/d", "a/b.c/e");
|
||||||
assertSetOnlyContains(fs.names, "a/b.c/e", "a/b.c/e (1)");
|
assertSetContainsExactly(fs.names, "a/b.c/e", "a/b.c/e (1)");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function assertSetOnlyContains<T>(set: Set<T>, ...values: T[]) {
|
|
||||||
assert(
|
|
||||||
set.size === values.length &&
|
|
||||||
Array.from(set).every((value) => values.includes(value)),
|
|
||||||
`Expected set to contain only ${values.map((v) => '"' + v + '"').join(", ")}, but it contained ${Array.from(
|
|
||||||
set
|
|
||||||
)
|
|
||||||
.map((v) => '"' + v + '"')
|
|
||||||
.join(", ")}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import assert from "assert";
|
||||||
|
|
||||||
|
export function assertSetContainsExactly<T>(set: Set<T>, ...values: T[]): void {
|
||||||
|
assert(
|
||||||
|
set.size === values.length &&
|
||||||
|
Array.from(set).every((value) => values.includes(value)),
|
||||||
|
`Expected set to contain only ${values.map((v) => '"' + v + '"').join(", ")}, but it contained ${Array.from(
|
||||||
|
set
|
||||||
|
)
|
||||||
|
.map((v) => '"' + v + '"')
|
||||||
|
.join(", ")}`
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue