From 633e93904ad932d2a32e2b5f56fdf0ffbc791f76 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 17 Apr 2021 21:00:10 +1000 Subject: [PATCH] add some unit tests to deckconfig --- ts/deckconfig/BUILD.bazel | 1 + ts/deckconfig/lib.test.ts | 151 ++++++++++++++++++++++++++++++++++++-- ts/deckconfig/lib.ts | 16 ++-- 3 files changed, 157 insertions(+), 11 deletions(-) diff --git a/ts/deckconfig/BUILD.bazel b/ts/deckconfig/BUILD.bazel index f606822a4..39b9a649a 100644 --- a/ts/deckconfig/BUILD.bazel +++ b/ts/deckconfig/BUILD.bazel @@ -131,5 +131,6 @@ jest_test( ":lib", "//ts/lib:backend_proto", "@npm//protobufjs", + "@npm//svelte", ], ) diff --git a/ts/deckconfig/lib.test.ts b/ts/deckconfig/lib.test.ts index 5ee341770..e47673229 100644 --- a/ts/deckconfig/lib.test.ts +++ b/ts/deckconfig/lib.test.ts @@ -3,6 +3,7 @@ import * as pb from "anki/backend_proto"; import { DeckConfigState } from "./lib"; +import { get } from "svelte/store"; const exampleData = { allConfig: [ @@ -15,7 +16,7 @@ const exampleData = { config: { learnSteps: [1, 10], relearnSteps: [10], - newPerDay: 20, + newPerDay: 10, reviewsPerDay: 200, initialEase: 2.5, easyMultiplier: 1.2999999523162842, @@ -85,9 +86,149 @@ const exampleData = { }, }; -test("create", () => { - const empty = pb.BackendProto.DeckConfigForUpdate.fromObject(exampleData); - console.log(empty); - const state = new DeckConfigState(empty); +function startingState(): DeckConfigState { + return new DeckConfigState( + pb.BackendProto.DeckConfigForUpdate.fromObject(exampleData) + ); +} + +test("start", () => { + const state = startingState(); expect(state.currentDeck.name).toBe("Default::child"); }); + +test("deck list", () => { + const state = startingState(); + expect(get(state.configList)).toStrictEqual([ + { + current: true, + idx: 1, + name: "another one", + useCount: 1, + }, + { + current: false, + idx: 0, + name: "Default", + useCount: 1, + }, + ]); + expect(get(state.currentConfig).newPerDay).toBe(40); + + // rename + state.setCurrentName("zzz"); + expect(get(state.configList)).toStrictEqual([ + { + current: false, + idx: 0, + name: "Default", + useCount: 1, + }, + { + current: true, + idx: 1, + name: "zzz", + useCount: 1, + }, + ]); + + // add + state.addConfig("hello"); + expect(get(state.configList)).toStrictEqual([ + { + current: false, + idx: 0, + name: "Default", + useCount: 1, + }, + { + current: true, + idx: 2, + name: "hello", + useCount: 1, + }, + { + current: false, + idx: 1, + name: "zzz", + useCount: 0, + }, + ]); + expect(get(state.currentConfig).newPerDay).toBe(20); + + // change current + state.setCurrentIndex(0); + expect(get(state.configList)).toStrictEqual([ + { + current: true, + idx: 0, + name: "Default", + useCount: 2, + }, + { + current: false, + idx: 2, + name: "hello", + useCount: 0, + }, + { + current: false, + idx: 1, + name: "zzz", + useCount: 0, + }, + ]); + expect(get(state.currentConfig).newPerDay).toBe(10); + + // can't delete default + expect(() => state.removeCurrentConfig()).toThrow(); + + // deleting old deck should work + state.setCurrentIndex(1); + state.removeCurrentConfig(); + expect(get(state.currentConfig).newPerDay).toBe(10); + + // as should newly added one + state.setCurrentIndex(1); + state.removeCurrentConfig(); + expect(get(state.currentConfig).newPerDay).toBe(10); + + // only the pre-existing deck should be listed for removal + expect((state as any).removedConfigs).toStrictEqual([1618570764780]); +}); + +test("duplicate name", () => { + const state = startingState(); + + // duplicate will get renamed + state.addConfig("another one"); + expect(get(state.configList).find((e) => e.current)?.name).toMatch(/another.*\d+$/); + + // should handle renames too + state.setCurrentName("Default"); + expect(get(state.configList).find((e) => e.current)?.name).toMatch(/Default\d+$/); +}); + +test("parent counts", () => { + const state = startingState(); + + expect(get(state.parentLimits)).toStrictEqual({ newCards: 10, reviews: 200 }); + + // adjusting the current deck config won't alter parent + state.currentConfig.update((c) => { + c.newPerDay = 123; + return c; + }); + expect(get(state.parentLimits)).toStrictEqual({ newCards: 10, reviews: 200 }); + + // but adjusting the default config will, since the parent deck uses it + state.setCurrentIndex(0); + state.currentConfig.update((c) => { + c.newPerDay = 123; + return c; + }); + // fixme: we should do this automatically when currentConfig is updated, or the + // parent count will become stale + state.saveCurrentConfig(); + expect(get(state.parentLimits)).toStrictEqual({ newCards: 123, reviews: 200 }); +}); diff --git a/ts/deckconfig/lib.ts b/ts/deckconfig/lib.ts index b58b4e739..d6717e20a 100644 --- a/ts/deckconfig/lib.ts +++ b/ts/deckconfig/lib.ts @@ -49,8 +49,8 @@ export class DeckConfigState { private configs: ConfigWithCount[]; private selectedIdx: number; - private configListSetter?: (val: ConfigListEntry[]) => void; - private parentLimitsSetter?: (val: ParentLimits) => void; + private configListSetter!: (val: ConfigListEntry[]) => void; + private parentLimitsSetter!: (val: ParentLimits) => void; private removedConfigs: DeckConfigId[] = []; constructor(data: pb.BackendProto.DeckConfigForUpdate) { @@ -79,6 +79,11 @@ export class DeckConfigState { this.parentLimitsSetter = set; return; }); + + // create a temporary subscription to force our setters to be set, so unit + // tests don't get stale results + get(this.configList); + get(this.parentLimits); } setCurrentIndex(index: number): void { @@ -93,12 +98,10 @@ export class DeckConfigState { saveCurrentConfig(): void { const config = get(this.currentConfig); if (!isEqual(config, this.configs[this.selectedIdx].config.config)) { - console.log("save"); this.configs[this.selectedIdx].config.config = config; this.configs[this.selectedIdx].config.mtimeSecs = 0; - } else { - console.log("no changes"); } + this.parentLimitsSetter?.(this.getParentLimits()); } getCurrentName(): string { @@ -148,7 +151,8 @@ export class DeckConfigState { } private ensureNewNameUnique(name: string): string { - if (this.configs.find((e) => e.config.name === name) !== undefined) { + const idx = this.configs.findIndex((e) => e.config.name === name); + if (idx !== -1) { return name + (new Date().getTime() / 1000).toFixed(0); } else { return name;