Skip to content

Commit

Permalink
Create helper to build public widget options for categorizer (#2092)
Browse files Browse the repository at this point in the history
## Summary:
This adds a function that takes categorizer's full widget options and filters out answer data. It also adds this function to the widget's widget export and adds a test confirming the function does what we expect.

Issue: LEMS-2756

## Test plan:
- Confirm all checks pass
- Confirm categorizer still works as expected

Author: Myranae

Reviewers: Myranae, handeyeco, jeremywiebe

Required Reviewers:

Approved By: jeremywiebe

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

Pull Request URL: #2092
  • Loading branch information
Myranae authored Jan 14, 2025
1 parent 01caf5f commit 600bf6a
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-numbers-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": minor
---

Introduce a widget export function to filter out scoring data from widget options. Implement this function for the categorizer widget.
13 changes: 13 additions & 0 deletions packages/perseus/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
UserInputMap,
} from "./validation.types";
import type {WidgetPromptJSON} from "./widget-ai-utils/prompt-types";
import type getCategorizerPublicWidgetOptions from "./widgets/categorizer/categorizer.util";
import type {KeypadAPI} from "@khanacademy/math-input";
import type {
Hint,
Expand Down Expand Up @@ -542,6 +543,12 @@ export type WidgetScorerFunction = (
locale?: string,
) => PerseusScore;

/**
* A union type of all the functions that provide public widget options.
*/
export type PublicWidgetOptionsFunction =
typeof getCategorizerPublicWidgetOptions;

export type WidgetExports<
T extends React.ComponentType<any> & Widget = React.ComponentType<any>,
> = Readonly<{
Expand Down Expand Up @@ -589,6 +596,12 @@ export type WidgetExports<
*/
scorer?: WidgetScorerFunction;

/**
* A function that provides a public version of the widget options that can
* be shared with the client.
*/
getPublicWidgetOptions?: PublicWidgetOptionsFunction;

getOneCorrectAnswerFromRubric?: (
rubric: Rubric,
) => string | null | undefined;
Expand Down
7 changes: 7 additions & 0 deletions packages/perseus/src/widgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
WidgetExports,
WidgetTransform,
WidgetScorerFunction,
PublicWidgetOptionsFunction,
} from "./types";
import type {PerseusWidget} from "@khanacademy/perseus-core";
import type * as React from "react";
Expand Down Expand Up @@ -141,6 +142,12 @@ export const getWidgetScorer = (name: string): WidgetScorerFunction | null => {
return widgets[name]?.scorer ?? null;
};

export const getPublicWidgetOptionsFunction = (
name: string,
): PublicWidgetOptionsFunction => {
return widgets[name]?.getPublicWidgetOptions ?? ((i) => i);
};

export const getEditor = (name: string): Editor | null | undefined => {
return _.has(editors, name) ? editors[name] : null;
};
Expand Down
2 changes: 2 additions & 0 deletions packages/perseus/src/widgets/categorizer/categorizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import sharedStyles from "../../styles/shared";
import Util from "../../util";
import {getPromptJSON as _getPromptJSON} from "../../widget-ai-utils/categorizer/categorizer-ai-utils";

import getCategorizerPublicWidgetOptions from "./categorizer.util";
import scoreCategorizer from "./score-categorizer";

import type {Widget, WidgetExports, WidgetProps} from "../../types";
Expand Down Expand Up @@ -328,4 +329,5 @@ export default {
// TODO(LEMS-2656): remove TS suppression
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusCSProgramUserInput'.
scorer: scoreCategorizer,
getPublicWidgetOptions: getCategorizerPublicWidgetOptions,
} satisfies WidgetExports<typeof Categorizer>;
32 changes: 32 additions & 0 deletions packages/perseus/src/widgets/categorizer/categorizer.util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import getCategorizerPublicWidgetOptions from "./categorizer.util";

import type {PerseusCategorizerWidgetOptions} from "@khanacademy/perseus-core";

describe("getCategorizerPublicWidgetOptions", () => {
it("returns an object without the answer data", () => {
const categorizerTestWidgetOptions: PerseusCategorizerWidgetOptions = {
values: [0, 1],
items: ["apples", "oranges"],
categories: ["citrus", "non-citrus"],
randomizeItems: true,
static: false,
highlightLint: false,
linterContext: {
contentType: "type",
paths: ["paths"],
stack: ["stack"],
},
};

const publicWidgetOptions = getCategorizerPublicWidgetOptions(
categorizerTestWidgetOptions,
);

expect(publicWidgetOptions).toEqual({
items: ["apples", "oranges"],
categories: ["citrus", "non-citrus"],
randomizeItems: true,
static: false,
});
});
});
29 changes: 29 additions & 0 deletions packages/perseus/src/widgets/categorizer/categorizer.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type {PerseusCategorizerWidgetOptions} from "@khanacademy/perseus-core";

/**
* For details on the individual options, see the
* PerseusCategorizerWidgetOptions type
*/
type CategorizerPublicWidgetOptions = {
items: PerseusCategorizerWidgetOptions["items"];
categories: PerseusCategorizerWidgetOptions["categories"];
randomizeItems: PerseusCategorizerWidgetOptions["randomizeItems"];
static: PerseusCategorizerWidgetOptions["static"];
};

/**
* Given a PerseusCategorizerWidgetOptions object, return a new object with only
* the public options that should be exposed to the client.
*/
function getCategorizerPublicWidgetOptions(
options: PerseusCategorizerWidgetOptions,
): CategorizerPublicWidgetOptions {
return {
items: options.items,
categories: options.categories,
randomizeItems: options.randomizeItems,
static: options.static,
};
}

export default getCategorizerPublicWidgetOptions;

0 comments on commit 600bf6a

Please sign in to comment.