diff --git a/.changeset/many-keys-smash.md b/.changeset/many-keys-smash.md
new file mode 100644
index 0000000000..3435bb94bd
--- /dev/null
+++ b/.changeset/many-keys-smash.md
@@ -0,0 +1,5 @@
+---
+"@khanacademy/perseus": patch
+---
+
+[Numeric Input] - Show format options as a list
diff --git a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap
index 08232c08ee..8e79ffdd65 100644
--- a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap
+++ b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap
@@ -81,13 +81,21 @@ exports[`server item renderer should snapshot: initial render 1`] = `
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
{
render(): React.ReactNode {
const input = this._renderInput();
- const examplesContent = _.map(this.props.examples, (example) => {
- return "- " + example;
- }).join("\n");
+ const examplesContent =
+ this.props.examples.length <= 2
+ ? this.props.examples.join(" ") // A single item (with or without leading text) is not a "list"
+ : this.props.examples // 2 or more items should display as a list
+ .map((example, index) => {
+ // If the first example is bold, then it is most likely a heading/leading text.
+ // So, it shouldn't be part of the list.
+ return index === 0 && example.startsWith("**")
+ ? `${example}\n`
+ : `- ${example}`;
+ })
+ .join("\n");
const showExamples =
this.props.shouldShowExamples && this.state.showExamples;
diff --git a/packages/perseus/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap b/packages/perseus/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap
index 078e779ff6..d2cda3f5fa 100644
--- a/packages/perseus/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap
+++ b/packages/perseus/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap
@@ -1015,13 +1015,21 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
ul {
- padding: 0;
- margin: -20px 0 -16px 0;
- > li {
- list-style-type: none;
- }
+/*
+ Extra specificity needed to override other styles that are too broad.
+ Once we get a better framework in place (like CSS Modules), we can fix this selector.
+*/
+.framework-perseus .perseus-formats-tooltip .paragraph,
+.framework-perseus .tooltipContainer .perseus-formats-tooltip .paragraph ul {
+ margin: 0;
}
.box-shadow(@shadow: 0 1px 3px rgba(0,0,0,0.25)) {
diff --git a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap
index 3926e342d6..0b1f5c6cb2 100644
--- a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap
+++ b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap
@@ -103,13 +103,21 @@ exports[`graded-group-set should render all graded groups 1`] = `
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
+
+
+ Your answer should be
+
+
+
+
+
- -
-
- Your answer should be
-
-
-
an integer, like
`;
+
+exports[`numeric-input widget Should render tooltip as list when multiple format options are given: render with format list tooltip 1`] = `
+
+
+
+
+
+
+
+ 5008 \\div 4 =
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`numeric-input widget Should render tooltip when format option is given: render with format tooltip 1`] = `
+
+
+
+
+
+
+
+ 5008 \\div 4 =
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts b/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts
index 2740d841d3..7a36eaa481 100644
--- a/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts
+++ b/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts
@@ -47,6 +47,20 @@ describe("numeric-input widget", () => {
expect(renderer).toHaveBeenAnsweredCorrectly();
});
+ it("should reject an incorrect answer", async () => {
+ // Arrange
+ const {renderer} = renderQuestion(question);
+
+ // Act
+ await userEvent.type(
+ screen.getByRole("textbox", {hidden: true}),
+ incorrect,
+ );
+
+ // Assert
+ expect(renderer).toHaveBeenAnsweredIncorrectly();
+ });
+
it("Should render predictably", async () => {
// Arrange
const {container} = renderQuestion(question);
@@ -62,18 +76,32 @@ describe("numeric-input widget", () => {
expect(container).toMatchSnapshot("after interaction");
});
- it("should reject an incorrect answer", async () => {
+ it("Should render tooltip when format option is given", async () => {
// Arrange
- const {renderer} = renderQuestion(question);
+ const questionWithFormatOptions = JSON.parse(JSON.stringify(question1));
+ questionWithFormatOptions.widgets[
+ "numeric-input 1"
+ ].options.answers[0].answerForms = ["proper"];
// Act
- await userEvent.type(
- screen.getByRole("textbox", {hidden: true}),
- incorrect,
- );
+ const {container} = renderQuestion(questionWithFormatOptions);
// Assert
- expect(renderer).toHaveBeenAnsweredIncorrectly();
+ expect(container).toMatchSnapshot("render with format tooltip");
+ });
+
+ it("Should render tooltip as list when multiple format options are given", async () => {
+ // Arrange
+ const questionWithFormatOptions = JSON.parse(JSON.stringify(question1));
+ questionWithFormatOptions.widgets[
+ "numeric-input 1"
+ ].options.answers[0].answerForms = ["proper", "improper", "mixed"];
+
+ // Act
+ const {container} = renderQuestion(questionWithFormatOptions);
+
+ // Assert
+ expect(container).toMatchSnapshot("render with format list tooltip");
});
});