Skip to content

Commit

Permalink
Test/coverage (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
ishiko732 authored Nov 28, 2023
1 parent b7365c0 commit b4162cc
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 19 deletions.
61 changes: 60 additions & 1 deletion __tests__/FSRSV4.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
createEmptyCard,
State,
Grade,
Grades,
Grades, default_request_retention, default_maximum_interval, default_enable_fuzz, default_w,
} from "../src/fsrs";
import { FSRSAlgorithm } from "../src/fsrs/algorithm";

describe("initial FSRS V4", () => {
const params = generatorParameters();
Expand Down Expand Up @@ -38,6 +39,45 @@ describe("initial FSRS V4", () => {
it("retrievability t=s ", () => {
expect(Number(f.current_retrievability(5, 5).toFixed(2))).toEqual(0.9);
});

it("default params",()=>{
const expected_w = [
0.4, 0.6, 2.4, 5.8, 4.93, 0.94, 0.86, 0.01, 1.49, 0.14, 0.94, 2.18, 0.05,
0.34, 1.26, 0.29, 2.61,
];
expect(default_request_retention).toEqual(0.9);
expect(default_maximum_interval).toEqual(36500);
expect(default_enable_fuzz).toEqual(false)
expect(default_w).toEqual(expected_w);
expect(default_w.length).toBe(expected_w.length);
})
});

describe("FSRS apply_fuzz", () => {
test("return original interval when fuzzing is disabled", () => {
const ivl = 3.0;
const enable_fuzz = false;
const algorithm = new FSRS({ enable_fuzz: enable_fuzz });
expect(algorithm.apply_fuzz(ivl)).toBe(3);
});

test("return original interval when ivl is less than 2.5", () => {
const ivl = 2.0;
const enable_fuzz = true;
const algorithm = new FSRS({ enable_fuzz: enable_fuzz });
expect(algorithm.apply_fuzz(ivl)).toBe(2);
});

test("return original interval when ivl is less than 2.5", () => {
const ivl = 2.5;
const enable_fuzz = true;
const algorithm = new FSRSAlgorithm({ enable_fuzz: enable_fuzz });
const min_ivl = Math.max(2, Math.round(ivl * 0.95 - 1));
const max_ivl = Math.round(ivl * 1.05 + 1);
const fuzzedInterval = algorithm.apply_fuzz(ivl);
expect(fuzzedInterval).toBeGreaterThanOrEqual(min_ivl);
expect(fuzzedInterval).toBeLessThanOrEqual(max_ivl);
});
});

// Ref: https://github.com/open-spaced-repetition/py-fsrs/blob/ecd68e453611eb808c7367c7a5312d7cadeedf5c/tests/test_fsrs.py#L1
Expand Down Expand Up @@ -135,3 +175,22 @@ describe("FSRS V4 AC by py-fsrs", () => {
]);
});
});

describe("get retrievability", () => {
const fsrs = new FSRS({});
test("return undefined for non-review cards", () => {
const card = createEmptyCard();
const now = new Date();
const expected = undefined;
expect(fsrs.get_retrievability(card, now)).toBe(expected);
});

test("return retrievability percentage for review cards", () => {
const card = createEmptyCard();
const sc = fsrs.repeat(card, new Date());
const r = [undefined, undefined, undefined, "100.00%"];
Grades.forEach((grade,index) => {
expect(fsrs.get_retrievability(sc[grade].card, new Date())).toBe(r[index]);
});
});
});
27 changes: 22 additions & 5 deletions __tests__/forget.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ describe("FSRS forget", () => {
);
}
for (const grade of grades) {
const forgetCard = f.forget(
scheduling_cards[grade].card,
forget_now,
false,
);
const forgetCard = f.forget(scheduling_cards[grade].card, forget_now);
expect(forgetCard.card).toEqual({
...card,
due: forget_now,
Expand All @@ -57,4 +53,25 @@ describe("FSRS forget", () => {
);
}
});

it("new card forget[reset true]", () => {
const card = createEmptyCard();
const forget_now = new Date(2023, 11, 30, 12, 30, 0, 0);
const forgetCard = f.forget(card, forget_now, true);
expect(forgetCard.card).toEqual({
...card,
due: forget_now,
lapses: 0,
reps: 0,
});
});
it("new card forget[reset true]", () => {
const card = createEmptyCard();
const forget_now = new Date(2023, 11, 30, 12, 30, 0, 0);
const forgetCard = f.forget(card, forget_now);
expect(forgetCard.card).toEqual({
...card,
due: forget_now,
});
});
});
180 changes: 180 additions & 0 deletions __tests__/help.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import {
date_diff, date_scheduler,
fixDate,
fixRating,
fixState,
formatDate,
Grades,
Rating,
State,
} from "../src/fsrs";

test("FSRS-Grades", () => {
expect(Grades).toStrictEqual([
Rating.Again,
Rating.Hard,
Rating.Good,
Rating.Easy,
]);
});

test("Date.prototype.format", () => {
const now = new Date(2022, 11, 30, 12, 30, 0, 0);
const last_review = new Date(2022, 11, 29, 12, 30, 0, 0);
expect(now.format()).toEqual("2022-12-30 12:30:00");
expect(formatDate(now)).toEqual("2022-12-30 12:30:00");
const TIMEUNITFORMAT_TEST = ["秒", "分", "时", "天", "月", "年"];
expect(now.dueFormat(last_review)).toEqual("1");
expect(now.dueFormat(last_review, true)).toEqual("1day");
expect(now.dueFormat(last_review, true, TIMEUNITFORMAT_TEST)).toEqual("1天");
});

describe("date_scheduler", () => {
test("offset by minutes", () => {
const now = new Date("2023-01-01T12:00:00Z");
const t = 30;
const expected = new Date("2023-01-01T12:30:00Z");

expect(date_scheduler(now, t)).toEqual(expected);
});

test("offset by days", () => {
const now = new Date("2023-01-01T12:00:00Z");
const t = 3;
const expected = new Date("2023-01-04T12:00:00Z");

expect(date_scheduler(now, t, true)).toEqual(expected);
});

test("negative offset", () => {
const now = new Date("2023-01-01T12:00:00Z");
const t = -15;
const expected = new Date("2023-01-01T11:45:00Z");

expect(date_scheduler(now, t)).toEqual(expected);
});

test("offset with isDay parameter", () => {
const now = new Date("2023-01-01T12:00:00Z");
const t = 2;
const expected = new Date("2023-01-03T12:00:00Z");

expect(date_scheduler(now, t, true)).toEqual(expected);
});
});

describe("date_diff", () => {
test("wrong fix", () => {
const now = new Date(2022, 11, 30, 12, 30, 0, 0);
const last_review = new Date(2022, 11, 29, 12, 30, 0, 0);

expect(() => date_diff(now, null as unknown as Date, "days")).toThrowError(
"Invalid date",
);
expect(() =>
date_diff(now, null as unknown as Date, "minutes"),
).toThrowError("Invalid date");
expect(() =>
date_diff(null as unknown as Date, last_review, "days"),
).toThrowError("Invalid date");
expect(() =>
date_diff(null as unknown as Date, last_review, "minutes"),
).toThrowError("Invalid date");
});

test("calculate difference in minutes", () => {
const now = new Date("2023-11-25T12:30:00Z");
const pre = new Date("2023-11-25T12:00:00Z");
const unit = "minutes";
const expected = 30;
expect(date_diff(now, pre, unit)).toBe(expected);
});

test("calculate difference in minutes for negative time difference", () => {
const now = new Date("2023-11-25T12:00:00Z");
const pre = new Date("2023-11-25T12:30:00Z");
const unit = "minutes";
const expected = -30;
expect(date_diff(now, pre, unit)).toBe(expected);
});
});

describe("fixDate", () => {
test("throw error for invalid date value", () => {
const input = "invalid-date";
expect(() => fixDate(input)).toThrowError("Invalid date:[invalid-date]");
});

test("throw error for unsupported value type", () => {
const input = true;
expect(() => fixDate(input)).toThrowError("Invalid date:[true]");
});

test("throw error for undefined value", () => {
const input = undefined;
expect(() => fixDate(input)).toThrowError("Invalid date:[undefined]");
});

test("throw error for null value", () => {
const input = null;
expect(() => fixDate(input)).toThrowError("Invalid date:[null]");
});
});

describe("fixState", () => {
test("fix state value", () => {
const newState = "New";
expect(fixState("new")).toEqual(State.New);
expect(fixState(newState)).toEqual(State.New);

const learning = "Learning";
expect(fixState("learning")).toEqual(State.Learning);
expect(fixState(learning)).toEqual(State.Learning);

const relearning = "Relearning";
expect(fixState("relearning")).toEqual(State.Relearning);
expect(fixState(relearning)).toEqual(State.Relearning);

const review = "Review";
expect(fixState("review")).toEqual(State.Review);
expect(fixState(review)).toEqual(State.Review);
});

test("throw error for invalid state value", () => {
const input = "invalid-state";
expect(() => fixState(input)).toThrowError("Invalid state:[invalid-state]");
expect(() => fixState(null)).toThrowError("Invalid state:[null]");
expect(() => fixState(undefined)).toThrowError("Invalid state:[undefined]");
});
});

describe("fixRating", () => {
test("fix Rating value", () => {
const again = "Again";
expect(fixRating("again")).toEqual(Rating.Again);
expect(fixRating(again)).toEqual(Rating.Again);

const hard = "Hard";
expect(fixRating("hard")).toEqual(Rating.Hard);
expect(fixRating(hard)).toEqual(Rating.Hard);

const good = "Good";
expect(fixRating("good")).toEqual(Rating.Good);
expect(fixRating(good)).toEqual(Rating.Good);

const easy = "Easy";
expect(fixRating("easy")).toEqual(Rating.Easy);
expect(fixRating(easy)).toEqual(Rating.Easy);
});

test("throw error for invalid rating value", () => {
const input = "invalid-rating";
expect(() => fixRating(input)).toThrowError(
"Invalid rating:[invalid-rating]",
);
expect(() => fixRating(null)).toThrowError("Invalid rating:[null]");
expect(() => fixRating(undefined)).toThrowError(
"Invalid rating:[undefined]",
);
});
});
5 changes: 0 additions & 5 deletions __tests__/help.tsts.ts

This file was deleted.

Loading

0 comments on commit b4162cc

Please sign in to comment.