Skip to content

Commit 2b1caad

Browse files
committed
Re-work where validation is called in scoring
1 parent c9c67cd commit 2b1caad

File tree

2 files changed

+14
-32
lines changed

2 files changed

+14
-32
lines changed

packages/perseus/src/renderer-util.test.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,16 @@ describe("renderer utils", () => {
749749
// Act
750750
const validatorSpy = jest
751751
.spyOn(DropdownWidgetExport, "validator")
752-
// Empty
752+
// 1st call - Empty
753753
.mockReturnValueOnce({
754754
type: "invalid",
755755
message: null,
756756
})
757-
// Not empty
757+
// 2nd call - Not empty
758758
.mockReturnValueOnce(null);
759-
const scoringSpy = jest.spyOn(DropdownWidgetExport, "scorer");
759+
const scoringSpy = jest
760+
.spyOn(DropdownWidgetExport, "scorer")
761+
.mockReturnValueOnce({type: "points", total: 1, earned: 1});
760762

761763
// Act
762764
const score = scorePerseusItem(
@@ -777,7 +779,8 @@ describe("renderer utils", () => {
777779

778780
// Assert
779781
expect(validatorSpy).toHaveBeenCalledTimes(2);
780-
expect(scoringSpy).not.toHaveBeenCalled();
782+
// Scoring is only called if validation passes
783+
expect(scoringSpy).toHaveBeenCalledTimes(1);
781784
expect(score).toEqual({type: "invalid", message: null});
782785
});
783786

packages/perseus/src/renderer-util.ts

+7-28
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ import type {
1616
ValidationDataMap,
1717
} from "./validation.types";
1818

19-
function mapWidgetIdsToEmptyScore(widgetIds: ReadonlyArray<string>): {
20-
[widgetId: string]: PerseusScore;
21-
} {
22-
const emptyResult: {[widgetId: string]: PerseusScore} = {};
23-
widgetIds.forEach((widgetId) => {
24-
emptyResult[widgetId] = {type: "invalid", message: null};
25-
});
26-
return emptyResult;
27-
}
28-
2919
export function getUpgradedWidgetOptions(
3020
oldWidgetOptions: PerseusWidgetsMap,
3121
): PerseusWidgetsMap {
@@ -118,18 +108,6 @@ export function scoreWidgetsFunctional(
118108
): {[widgetId: string]: PerseusScore} {
119109
const upgradedWidgets = getUpgradedWidgetOptions(widgets);
120110

121-
// Do empty check first
122-
const emptyWidgets = emptyWidgetsFunctional(
123-
widgets,
124-
widgetIds,
125-
userInputMap,
126-
strings,
127-
locale,
128-
);
129-
if (emptyWidgets.length > 0) {
130-
return mapWidgetIdsToEmptyScore(emptyWidgets);
131-
}
132-
133111
const gradedWidgetIds = widgetIds.filter((id) => {
134112
const props = upgradedWidgets[id];
135113
const widgetIsGraded: boolean = props?.graded == null || props.graded;
@@ -146,13 +124,14 @@ export function scoreWidgetsFunctional(
146124
}
147125

148126
const userInput = userInputMap[id];
127+
const validator = getWidgetValidator(widget.type);
149128
const scorer = getWidgetScorer(widget.type);
150-
const score = scorer?.(
151-
userInput as UserInput,
152-
widget.options,
153-
strings,
154-
locale,
155-
);
129+
130+
// We do validation (empty checks) first and then scoring. If
131+
// validation fails, it's result is itself a PerseusScore.
132+
const score =
133+
validator?.(userInput, widget.options, strings, locale) ??
134+
scorer?.(userInput, widget.options, strings, locale);
156135
if (score != null) {
157136
widgetScores[id] = score;
158137
}

0 commit comments

Comments
 (0)