Skip to content

Commit

Permalink
[LEMS-2850] Answerless Dropdown (#2231)
Browse files Browse the repository at this point in the history
## Summary:
Nothing interesting really. Dropdown didn't need the answers at all, so I just made sure it wouldn't have access and added tests to make sure it was interactive with/without answer data.

Issue: LEMS-2850

## Test plan:
Nothing should change. Dropdown should continue to be interactive and scorable.

Author: handeyeco

Reviewers: handeyeco, benchristel, Myranae, jeremywiebe

Required Reviewers:

Approved By: benchristel

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

Pull Request URL: #2231
  • Loading branch information
handeyeco authored Feb 20, 2025
1 parent 9daaed4 commit 08409c6
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changeset/silly-pianos-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": patch
"@khanacademy/perseus-core": patch
---

Add tests for answerless Dropdown support
1 change: 1 addition & 0 deletions packages/perseus-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export {
export {default as getLabelImagePublicWidgetOptions} from "./widgets/label-image/label-image-util";
export {default as getSorterPublicWidgetOptions} from "./widgets/sorter/sorter-util";
export {default as getDropdownPublicWidgetOptions} from "./widgets/dropdown/dropdown-util";
export type {DropdownPublicWidgetOptions} from "./widgets/dropdown/dropdown-util";
export {default as getNumericInputPublicWidgetOptions} from "./widgets/numeric-input/numeric-input-util";
export {default as getNumberLinePublicWidgetOptions} from "./widgets/number-line/number-line-util";
export {default as getRadioPublicWidgetOptions} from "./widgets/radio/radio-util";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {PerseusDropdownWidgetOptions} from "@khanacademy/perseus-core";
* For details on the individual options, see the
* PerseusDropdownWidgetOptions type
*/
type DropdownPublicWidgetOptions = {
export type DropdownPublicWidgetOptions = {
choices: ReadonlyArray<{content: string}>;
placeholder: PerseusDropdownWidgetOptions["placeholder"];
static: PerseusDropdownWidgetOptions["static"];
Expand Down
96 changes: 96 additions & 0 deletions packages/perseus/src/widgets/dropdown/dropdown.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import {
splitPerseusItem,
type PerseusRenderer,
} from "@khanacademy/perseus-core";
import {scorePerseusItem} from "@khanacademy/perseus-score";
import {screen} from "@testing-library/react";
import {userEvent as userEventLib} from "@testing-library/user-event";

import {testDependencies} from "../../../../../testing/test-dependencies";
import * as Dependencies from "../../dependencies";
import {registerAllWidgetsForTesting} from "../../util/register-all-widgets-for-testing";
import {scorePerseusItemTesting} from "../../util/test-utils";
import {renderQuestion} from "../__testutils__/renderQuestion";

Expand Down Expand Up @@ -127,4 +133,94 @@ describe("Dropdown widget", () => {
// Assert
expect(screen.getByLabelText("Select an answer")).toBeInTheDocument();
});

describe("interactive: full vs answerless", () => {
beforeAll(() => {
registerAllWidgetsForTesting();
});

let userEvent: UserEvent;
beforeEach(() => {
userEvent = userEventLib.setup({
advanceTimers: jest.advanceTimersByTime,
});

jest.spyOn(Dependencies, "getDependencies").mockReturnValue(
testDependencies,
);
});

function getAnswerfulItem(): PerseusRenderer {
return {
content: "[[☃ dropdown 1]]",
images: {},
widgets: {
"dropdown 1": {
type: "dropdown",
options: {
static: false,
placeholder: "Choose an answer",
choices: [
{
content: "Correct",
correct: true,
},
{
content: "Incorrect",
correct: false,
},
],
},
},
},
};
}

function getAnswerlessItem(): PerseusRenderer {
return splitPerseusItem(getAnswerfulItem());
}

test.each(["answerless", "answerful"])(
"is interactive with widget options: %p",
async (e) => {
// Arrange
const useAnswerless = e === "answerless";
const renderItem = useAnswerless
? getAnswerlessItem()
: getAnswerfulItem();

// assert that splitting worked as expected
if (useAnswerless) {
expect(
renderItem.widgets["dropdown 1"].options.choices[0]
.correct,
).toBeUndefined();
expect(
renderItem.widgets["dropdown 1"].options.choices[1]
.correct,
).toBeUndefined();
}

// Act
const {renderer} = renderQuestion(renderItem);

await userEvent.click(
screen.getByRole("combobox", {name: "Select an answer"}),
);
await userEvent.click(
screen.getByRole("option", {name: "Correct"}),
);

const userInput = renderer.getUserInputMap();
const score = scorePerseusItem(
getAnswerfulItem(),
userInput,
"en",
);

// Assert
expect(score).toHaveBeenAnsweredCorrectly();
},
);
});
});
18 changes: 8 additions & 10 deletions packages/perseus/src/widgets/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import {getPromptJSON as _getPromptJSON} from "../../widget-ai-utils/dropdown/dr

import type {Widget, WidgetExports, WidgetProps} from "../../types";
import type {DropdownPromptJSON} from "../../widget-ai-utils/dropdown/dropdown-ai-utils";
import type {PerseusDropdownWidgetOptions} from "@khanacademy/perseus-core";
import type {
PerseusDropdownRubric,
PerseusDropdownUserInput,
} from "@khanacademy/perseus-score";
DropdownPublicWidgetOptions,
PerseusDropdownWidgetOptions,
} from "@khanacademy/perseus-core";
import type {PerseusDropdownUserInput} from "@khanacademy/perseus-score";

type Props = WidgetProps<RenderProps, PerseusDropdownRubric> & {
type Props = WidgetProps<RenderProps> & {
selected: number;
};

Expand Down Expand Up @@ -151,21 +151,19 @@ type RenderProps = {
choices: ReadonlyArray<string>;
};

const optionsTransform: (arg1: PerseusDropdownWidgetOptions) => RenderProps = (
widgetOptions,
) => {
function transform(widgetOptions: DropdownPublicWidgetOptions): RenderProps {
return {
placeholder: widgetOptions.placeholder,
visibleLabel: widgetOptions.visibleLabel,
ariaLabel: widgetOptions.ariaLabel,
choices: widgetOptions.choices.map((choice) => choice.content),
};
};
}

export default {
name: "dropdown",
displayName: "Drop down",
accessible: true,
widget: Dropdown,
transform: optionsTransform,
transform,
} satisfies WidgetExports<typeof Dropdown>;

0 comments on commit 08409c6

Please sign in to comment.