From 6d6b977bfbf39f27a11f7e12056d7bccf03ad481 Mon Sep 17 00:00:00 2001 From: Ben Christel Date: Fri, 6 Feb 2026 14:35:22 -0800 Subject: [PATCH 1/3] [benc/fix-toHaveBeenAnsweredIncorrectly] Fix bug in toHaveBeenAnsweredIncorrectly and clarify tests --- config/test/custom-matchers.ts | 5 +---- packages/perseus/src/widgets/image/image.test.ts | 7 +++++-- .../src/widgets/interaction/interaction.test.ts | 10 ++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/config/test/custom-matchers.ts b/config/test/custom-matchers.ts index 383384384ff..74ebb6eaa34 100644 --- a/config/test/custom-matchers.ts +++ b/config/test/custom-matchers.ts @@ -112,10 +112,7 @@ expect.extend({ }; } - // TODO: Are we sure this is right? I wonder if it should be - // score.earned === score.total - // (in multi-widget questions, you can get some right and some wrong) - if (score.earned !== 0) { + if (score.earned >= score.total) { return { pass: false, message: () => `Problem was answered correctly.`, diff --git a/packages/perseus/src/widgets/image/image.test.ts b/packages/perseus/src/widgets/image/image.test.ts index 1f16bd040f1..bafb6c6ffba 100644 --- a/packages/perseus/src/widgets/image/image.test.ts +++ b/packages/perseus/src/widgets/image/image.test.ts @@ -5,6 +5,7 @@ import { } from "@khanacademy/perseus-core"; import {act, screen, within} from "@testing-library/react"; import {userEvent as userEventLib} from "@testing-library/user-event"; +import invariant from "tiny-invariant"; import * as Dependencies from "../../dependencies"; import {getFeatureFlags} from "../../testing/feature-flags-util"; @@ -56,7 +57,7 @@ describe.each([[true], [false]])("image widget - isMobile(%j)", (isMobile) => { expect(container).toMatchSnapshot("first render"); }); - it("should be unanswerable", () => { + it("should score zero points", () => { // Arrange // Act @@ -66,8 +67,10 @@ describe.each([[true], [false]])("image widget - isMobile(%j)", (isMobile) => { renderer.getUserInputMap(), ); + invariant(score.type === "points", `score.type is ${score.type}`); + // Assert - expect(score).toHaveBeenAnsweredIncorrectly(); + expect(score.earned).toBe(0); }); it("should not render empty image", () => { diff --git a/packages/perseus/src/widgets/interaction/interaction.test.ts b/packages/perseus/src/widgets/interaction/interaction.test.ts index 142d6cb01bb..3e814b9ab5a 100644 --- a/packages/perseus/src/widgets/interaction/interaction.test.ts +++ b/packages/perseus/src/widgets/interaction/interaction.test.ts @@ -1,3 +1,5 @@ +import invariant from "tiny-invariant"; + import * as Dependencies from "../../dependencies"; import {testDependencies} from "../../testing/test-dependencies"; import {waitForInitialGraphieRender} from "../../testing/wait"; @@ -25,7 +27,7 @@ describe("interaction widget", () => { expect(container).toMatchSnapshot(); }); - it("should be unanswerable", async () => { + it("should score zero points", async () => { // Arrange const {renderer} = renderQuestion(question1); await waitForInitialGraphieRender(); @@ -36,10 +38,10 @@ describe("interaction widget", () => { renderer.getUserInputMap(), ); + invariant(score.type === "points", `score.type is ${score.type}`); + // Assert - // Note that this widget can never be answered correctly, no matter - // what state its in. - expect(score).toHaveBeenAnsweredIncorrectly(); + expect(score.earned).toBe(0); }); it("renders movable point elements with blank constraintXMin, constraintXMax, etc.", async () => { From d19b8ab25bb44de206034cfcf28caf6696b049ba Mon Sep 17 00:00:00 2001 From: Ben Christel Date: Tue, 10 Feb 2026 14:24:10 -0800 Subject: [PATCH 2/3] [benc/fix-toHaveBeenAnsweredIncorrectly] Improve invariant failure message --- packages/perseus/src/widgets/image/image.test.ts | 5 ++++- packages/perseus/src/widgets/interaction/interaction.test.ts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/perseus/src/widgets/image/image.test.ts b/packages/perseus/src/widgets/image/image.test.ts index bafb6c6ffba..dfd369056ac 100644 --- a/packages/perseus/src/widgets/image/image.test.ts +++ b/packages/perseus/src/widgets/image/image.test.ts @@ -67,7 +67,10 @@ describe.each([[true], [false]])("image widget - isMobile(%j)", (isMobile) => { renderer.getUserInputMap(), ); - invariant(score.type === "points", `score.type is ${score.type}`); + invariant( + score.type === "points", + `score.type should be "points", but was ${score.type}`, + ); // Assert expect(score.earned).toBe(0); diff --git a/packages/perseus/src/widgets/interaction/interaction.test.ts b/packages/perseus/src/widgets/interaction/interaction.test.ts index 3e814b9ab5a..f9e2481b9e3 100644 --- a/packages/perseus/src/widgets/interaction/interaction.test.ts +++ b/packages/perseus/src/widgets/interaction/interaction.test.ts @@ -38,7 +38,10 @@ describe("interaction widget", () => { renderer.getUserInputMap(), ); - invariant(score.type === "points", `score.type is ${score.type}`); + invariant( + score.type === "points", + `score.type should be "points", but was ${score.type}`, + ); // Assert expect(score.earned).toBe(0); From 4f10e84543d641f54275f4b105b0ab0b070287cf Mon Sep 17 00:00:00 2001 From: Ben Christel Date: Tue, 10 Feb 2026 14:24:25 -0800 Subject: [PATCH 3/3] [benc/fix-toHaveBeenAnsweredIncorrectly] docs(changeset): --- .changeset/purple-items-turn.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/purple-items-turn.md diff --git a/.changeset/purple-items-turn.md b/.changeset/purple-items-turn.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/purple-items-turn.md @@ -0,0 +1,2 @@ +--- +---