Skip to content

Commit

Permalink
Convert backgroundImage dimensions to numbers during parsing (#1923)
Browse files Browse the repository at this point in the history
Issue: LEMS-2582

## Test plan:

`yarn test`

Author: benchristel

Reviewers: jeremywiebe, benchristel

Required Reviewers:

Approved By: jeremywiebe

Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1923
  • Loading branch information
benchristel authored Dec 3, 2024
1 parent 1d2b4e7 commit be8c06c
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/smooth-taxis-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Internal: convert backgroundImage dimensions to numbers during parsing.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {success} from "../result";

import {stringToNumber} from "./string-to-number";
import {ctx, parseFailureWith} from "./test-helpers";

describe("stringToNumber", () => {
it("accepts a number", () => {
expect(stringToNumber(42, ctx())).toEqual(success(42));
});

it("accepts a numeric string", () => {
expect(stringToNumber("7", ctx())).toEqual(success(7));
});

it("parses a decimal", () => {
expect(stringToNumber("5.5", ctx())).toEqual(success(5.5));
});

it("parses a negative number", () => {
expect(stringToNumber("-2", ctx())).toEqual(success(-2));
});

it("rejects the empty string", () => {
expect(stringToNumber("", ctx())).toEqual(
parseFailureWith({
badValue: "",
expected: ["a number or numeric string"],
}),
);
});

it("rejects a non-numeric string", () => {
expect(stringToNumber("3a", ctx())).toEqual(
parseFailureWith({
badValue: "3a",
expected: ["a number or numeric string"],
}),
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type {PartialParser} from "../parser-types";

export const stringToNumber: PartialParser<string | number, number> = (
rawValue,
ctx,
) => {
if (typeof rawValue === "number") {
return ctx.success(rawValue);
}

const parsedNumber = +rawValue;
if (rawValue === "" || isNaN(parsedNumber)) {
return ctx.failure("a number or numeric string", rawValue);
}

return ctx.success(parsedNumber);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ import {
number,
object,
optional,
pipeParsers,
string,
union,
} from "../general-purpose-parsers";
import {stringToNumber} from "../general-purpose-parsers/string-to-number";

import type {Parser} from "../parser-types";
import type {PerseusImageBackground} from "@khanacademy/perseus";

const numericToNumber = pipeParsers(union(number).or(string).parser).then(
stringToNumber,
).parser;

export const parsePerseusImageBackground: Parser<PerseusImageBackground> =
object({
url: optional(nullable(string)),
width: optional(number),
height: optional(number),
top: optional(number),
left: optional(number),
bottom: optional(number),
// TODO(benchristel): convert scale to a number
scale: optional(union(number).or(string).parser),
width: optional(numericToNumber),
height: optional(numericToNumber),
top: optional(numericToNumber),
left: optional(numericToNumber),
bottom: optional(numericToNumber),
scale: optional(numericToNumber),
});
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,166 @@ exports[`parseAndTypecheckPerseusItem correctly parses data/iframe-missing-stati
}
`;

exports[`parseAndTypecheckPerseusItem correctly parses data/interactive-graph-with-string-backgroundImage-left.json 1`] = `
{
"answer": undefined,
"answerArea": {
"calculator": false,
"chi2Table": false,
"periodicTable": false,
"tTable": false,
"zTable": false,
},
"hints": [],
"itemDataVersion": {
"major": 0,
"minor": 1,
},
"question": {
"content": "Ally is excited to compete in a $6$-mile race. The race organizers plotted the course on a coordinate map. The starting point is at $(4,3)$, and the ending point is at $(4,9)$. Ally's family decides to stand at $(4,6)$ on the map.
**Plot the starting point, ending point, and place where Ally's family stands on the map.**
[[☃ interactive-graph 1]]
**How far along will Ally be in the race when she reaches her family?**
[[☃ radio 1]]",
"images": {},
"metadata": undefined,
"widgets": {
"interactive-graph 1": {
"alignment": "default",
"graded": true,
"key": undefined,
"options": {
"backgroundImage": {
"bottom": 4,
"height": 0,
"left": 0,
"scale": 1,
"top": undefined,
"url": "",
"width": 0,
},
"correct": {
"coord": undefined,
"coords": [
[
4,
3,
],
[
4,
6,
],
[
4,
9,
],
],
"numPoints": 3,
"startCoords": undefined,
"type": "point",
},
"fullGraphAriaDescription": undefined,
"fullGraphLabel": undefined,
"graph": {
"coord": undefined,
"coords": undefined,
"numPoints": 3,
"startCoords": undefined,
"type": "point",
},
"gridStep": [
1,
1,
],
"labels": [
"x",
"y",
],
"lockedFigures": undefined,
"markings": "graph",
"range": [
[
-1,
10,
],
[
-1,
10,
],
],
"rulerLabel": "",
"rulerTicks": 10,
"showProtractor": false,
"showRuler": false,
"showTooltips": false,
"snapStep": [
0.5,
0.5,
],
"step": [
1,
1,
],
},
"static": false,
"type": "interactive-graph",
"version": {
"major": 0,
"minor": 0,
},
},
"radio 1": {
"alignment": "default",
"graded": true,
"key": undefined,
"options": {
"choices": [
{
"clue": undefined,
"content": "Less than halfway through the race",
"correct": false,
"isNoneOfTheAbove": undefined,
"widgets": undefined,
},
{
"clue": undefined,
"content": "Halfway through the race",
"correct": true,
"isNoneOfTheAbove": undefined,
"widgets": undefined,
},
{
"clue": undefined,
"content": "More than halfway through the race",
"correct": undefined,
"isNoneOfTheAbove": undefined,
"widgets": undefined,
},
],
"countChoices": false,
"deselectEnabled": false,
"displayCount": null,
"hasNoneOfTheAbove": false,
"multipleSelect": false,
"noneOfTheAbove": undefined,
"onePerLine": undefined,
"randomize": false,
},
"static": false,
"type": "radio",
"version": {
"major": 1,
"minor": 0,
},
},
},
},
}
`;

exports[`parseAndTypecheckPerseusItem correctly parses data/item-missing-answerArea.json 1`] = `
{
"_multi": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
{
"question": {
"content": "Ally is excited to compete in a $6$-mile race. The race organizers plotted the course on a coordinate map. The starting point is at $(4,3)$, and the ending point is at $(4,9)$. Ally's family decides to stand at $(4,6)$ on the map.\n\n**Plot the starting point, ending point, and place where Ally's family stands on the map.**\n\n[[☃ interactive-graph 1]]\n\n**How far along will Ally be in the race when she reaches her family?** \n[[☃ radio 1]]",
"images": {},
"widgets": {
"interactive-graph 1": {
"type": "interactive-graph",
"alignment": "default",
"static": false,
"graded": true,
"options": {
"step": [
1,
1
],
"backgroundImage": {
"url": "",
"scale": "1",
"bottom": "4",
"left": "0",
"width": 0,
"height": 0
},
"markings": "graph",
"labels": [
"x",
"y"
],
"showProtractor": false,
"showRuler": false,
"showTooltips": false,
"rulerLabel": "",
"rulerTicks": 10,
"range": [
[
-1,
10
],
[
-1,
10
]
],
"gridStep": [
1,
1
],
"snapStep": [
0.5,
0.5
],
"graph": {
"type": "point",
"numPoints": 3
},
"correct": {
"type": "point",
"coords": [
[
4,
3
],
[
4,
6
],
[
4,
9
]
],
"numPoints": 3
}
},
"version": {
"major": 0,
"minor": 0
}
},
"radio 1": {
"type": "radio",
"alignment": "default",
"static": false,
"graded": true,
"options": {
"choices": [
{
"correct": false,
"content": "Less than halfway through the race"
},
{
"correct": true,
"content": "Halfway through the race"
},
{
"content": "More than halfway through the race"
}
],
"randomize": false,
"multipleSelect": false,
"countChoices": false,
"displayCount": null,
"hasNoneOfTheAbove": false,
"deselectEnabled": false
},
"version": {
"major": 1,
"minor": 0
}
}
}
},
"answerArea": {
"calculator": false,
"chi2Table": false,
"periodicTable": false,
"tTable": false,
"zTable": false
},
"itemDataVersion": {
"major": 0,
"minor": 1
},
"hints": []
}

0 comments on commit be8c06c

Please sign in to comment.