Skip to content

Commit 962f89a

Browse files
authored
Categorizer UserInput parsing issue (null / undefined values) (#2758)
## Summary: Categorizer user input was typed as `number[]`. _Correct_ answers can only be `number[]` but incomplete user input could be `Array<number | undefined>`. To complicate things, `JSON.stringify` converts `[undefined, 2]` to `[null,2]` so the backend also needs to support `null`. So fix the parser to handle number, undefined, or null. Issue: LEMS-3344 Author: handeyeco Reviewers: benchristel, catandthemachines, Myranae Required Reviewers: Approved By: benchristel, catandthemachines Checks: ✅ 10 checks were successful Pull Request URL: #2758
1 parent e269c7a commit 962f89a

File tree

6 files changed

+47
-5
lines changed

6 files changed

+47
-5
lines changed

.changeset/weak-dots-wave.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@khanacademy/perseus": patch
3+
"@khanacademy/perseus-core": patch
4+
---
5+
6+
Bugfix: Categorizer user input parser needs to handle undefined and null, not just numbers
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {parse} from "../parse";
2+
import {success} from "../result";
3+
4+
import {parseCategorizerUserInput} from "./categorizer-user-input";
5+
6+
describe("parseCategorizerUserInput", () => {
7+
it("handles undefined", () => {
8+
const userInput = {
9+
values: [undefined, 2],
10+
};
11+
12+
expect(parse(userInput, parseCategorizerUserInput)).toEqual(
13+
success({
14+
values: [undefined, 2],
15+
}),
16+
);
17+
});
18+
19+
it("handles null", () => {
20+
const userInput = {
21+
values: [null, 2],
22+
};
23+
24+
expect(parse(userInput, parseCategorizerUserInput)).toEqual(
25+
success({
26+
values: [null, 2],
27+
}),
28+
);
29+
});
30+
});
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
import {object, array, number} from "../general-purpose-parsers";
1+
import {
2+
object,
3+
array,
4+
number,
5+
optional,
6+
nullable,
7+
} from "../general-purpose-parsers";
28

39
export const parseCategorizerUserInput = object({
4-
values: array(number),
10+
values: array(optional(nullable(number))),
511
});

packages/perseus-core/src/validation.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export type PerseusCategorizerRubric = {
8787
} & PerseusCategorizerValidationData;
8888

8989
export type PerseusCategorizerUserInput = {
90-
values: PerseusCategorizerRubric["values"];
90+
values: Array<number | null | undefined>;
9191
};
9292

9393
export type PerseusCategorizerValidationData = {

packages/perseus/src/widget-ai-utils/categorizer/categorizer-ai-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type CategorizerPromptJSON = {
88
categories: ReadonlyArray<string>;
99
};
1010
userInput: {
11-
itemToCategoryMapping: ReadonlyArray<number>;
11+
itemToCategoryMapping: ReadonlyArray<number | null | undefined>;
1212
};
1313
};
1414

packages/perseus/src/widgets/categorizer/categorizer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export class Categorizer
6969
return _getPromptJSON(this.props);
7070
}
7171

72-
_handleUserInput(itemNum, catNum) {
72+
_handleUserInput(itemNum: number, catNum: number) {
7373
const values = [...this.props.userInput.values];
7474
values[itemNum] = catNum;
7575
this.props.handleUserInput({values});

0 commit comments

Comments
 (0)