Skip to content

Commit

Permalink
Create a helper function for generating correctly typed Perseus test …
Browse files Browse the repository at this point in the history
…items (#980)

## Summary:
There are many places in webapp where custom types are created for Perseus items, frequently related to testing. This change adds a helper function that creates a generic Perseus test item that can have specific sections overridden with custom input. It will ensure tests are properly typed and help us know where updates need to be made if any changes happen to the types in Perseus.

Issue: LC-1658

## Test plan:
- Confirm all checks pass
- Test the new function in webapp with the npm snapshot
- In webapp, confirm related tests pass and related stories still work

Author: Myranae

Reviewers: Myranae, handeyeco, nixterrimus, SonicScrewdriver

Required Reviewers:

Approved By: handeyeco

Checks: ✅ codecov/project, ✅ codecov/patch, ✅ Upload Coverage, ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Extract i18n strings (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #980
  • Loading branch information
Myranae authored Feb 22, 2024
1 parent 7c030e6 commit 7d4d098
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-ways-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": minor
---

Create a helper function for generating correctly typed Perseus test items
4 changes: 4 additions & 0 deletions packages/perseus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ export {
injectWidgets,
} from "./util/extract-perseus-data";
export {parsePerseusItem} from "./util/parse-perseus-json";
export {
generateTestPerseusItem,
genericPerseusItemData,
} from "./util/test-utils";

/**
* Mixins
Expand Down
34 changes: 34 additions & 0 deletions packages/perseus/src/util/test-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {generateTestPerseusItem} from "./test-utils";
import {
basicObject,
customQuestionInfo,
expectedQuestionInfoAdded,
customAnswerAreaInfo,
expectedAnswerAreaInfoAdded,
customHintsInfo,
expectedHintsInfoAdded,
} from "./test-utils.testdata";

describe("generateTestPerseusItem", () => {
it("should provide a basic Perseus item object with no inputs", () => {
expect(generateTestPerseusItem()).toEqual(basicObject);
});

it("should replace question parts when given question custom info", () => {
expect(generateTestPerseusItem(customQuestionInfo)).toEqual(
expectedQuestionInfoAdded,
);
});

it("should replace answer area parts when given answer area custom info", () => {
expect(generateTestPerseusItem(customAnswerAreaInfo)).toEqual(
expectedAnswerAreaInfoAdded,
);
});

it("should add hints when given custom info containing hints", () => {
expect(generateTestPerseusItem(customHintsInfo)).toEqual(
expectedHintsInfoAdded,
);
});
});
219 changes: 219 additions & 0 deletions packages/perseus/src/util/test-utils.testdata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import type {PerseusItem} from "@khanacademy/perseus";

export const basicObject: PerseusItem = {
question: {
content: "",
images: {},
widgets: {},
},
answerArea: {
calculator: false,
chi2Table: false,
periodicTable: false,
tTable: false,
zTable: false,
financialCalculatorMonthlyPayment: false,
financialCalculatorTotalAmount: false,
financialCalculatorTimeToPayOff: false,
periodicTableWithKey: false,
},
itemDataVersion: {
major: 0,
minor: 1,
},
hints: [],
_multi: null,
answer: null,
};

export const customQuestionInfo: Partial<PerseusItem> = {
question: {
content: "Test content string",
images: {"Test image string": {width: 200, height: 200}},
widgets: {
"input-number 1": {
type: "input-number",
graded: true,
options: {
value: 123,
simplify: "required",
size: "small",
inexact: false,
maxError: 0.123,
answerType: "number",
},
},
},
},
};

export const expectedQuestionInfoAdded: PerseusItem = {
question: {
content: "Test content string",
images: {"Test image string": {width: 200, height: 200}},
widgets: {
"input-number 1": {
type: "input-number",
graded: true,
options: {
value: 123,
simplify: "required",
size: "small",
inexact: false,
maxError: 0.123,
answerType: "number",
},
},
},
},
answerArea: {
calculator: false,
chi2Table: false,
periodicTable: false,
tTable: false,
zTable: false,
financialCalculatorMonthlyPayment: false,
financialCalculatorTotalAmount: false,
financialCalculatorTimeToPayOff: false,
periodicTableWithKey: false,
},
itemDataVersion: {
major: 0,
minor: 1,
},
hints: [],
_multi: null,
answer: null,
};

export const customAnswerAreaInfo: Partial<PerseusItem> = {
answerArea: {
calculator: true,
chi2Table: true,
periodicTable: true,
tTable: true,
zTable: true,
financialCalculatorMonthlyPayment: true,
financialCalculatorTotalAmount: true,
financialCalculatorTimeToPayOff: true,
periodicTableWithKey: true,
},
};

export const expectedAnswerAreaInfoAdded: PerseusItem = {
question: {
content: "",
images: {},
widgets: {},
},
answerArea: {
calculator: true,
chi2Table: true,
periodicTable: true,
tTable: true,
zTable: true,
financialCalculatorMonthlyPayment: true,
financialCalculatorTotalAmount: true,
financialCalculatorTimeToPayOff: true,
periodicTableWithKey: true,
},
itemDataVersion: {
major: 0,
minor: 1,
},
hints: [],
_multi: null,
answer: null,
};

export const customHintsInfo: Partial<PerseusItem> = {
hints: [
{
content: "Test content string",
images: {
"Test images string": {height: 200, width: 200},
},
widgets: {
"radio 1": {
graded: true,
options: {
choices: [
{
content: "Test content string",
correct: true,
},
{
content: "Test content string 2",
correct: false,
},
],
deselectEnabled: false,
displayCount: null,
multipleSelect: false,
noneOfTheAbove: false,
onePerLine: true,
randomize: true,
},
type: "radio",
},
},
},
],
};

export const expectedHintsInfoAdded: PerseusItem = {
question: {
content: "",
images: {},
widgets: {},
},
answerArea: {
calculator: false,
chi2Table: false,
periodicTable: false,
tTable: false,
zTable: false,
financialCalculatorMonthlyPayment: false,
financialCalculatorTotalAmount: false,
financialCalculatorTimeToPayOff: false,
periodicTableWithKey: false,
},
itemDataVersion: {
major: 0,
minor: 1,
},
hints: [
{
content: "Test content string",
images: {
"Test images string": {height: 200, width: 200},
},
widgets: {
"radio 1": {
graded: true,
options: {
choices: [
{
content: "Test content string",
correct: true,
},
{
content: "Test content string 2",
correct: false,
},
],
deselectEnabled: false,
displayCount: null,
multipleSelect: false,
noneOfTheAbove: false,
onePerLine: true,
randomize: true,
},
type: "radio",
},
},
},
],
_multi: null,
answer: null,
};
42 changes: 42 additions & 0 deletions packages/perseus/src/util/test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type {PerseusItem} from "../perseus-types";

export const genericPerseusItemData: PerseusItem = {
question: {
content: "",
images: {},
widgets: {},
},
answerArea: {
calculator: false,
chi2Table: false,
periodicTable: false,
tTable: false,
zTable: false,
financialCalculatorMonthlyPayment: false,
financialCalculatorTotalAmount: false,
financialCalculatorTimeToPayOff: false,
periodicTableWithKey: false,
},
itemDataVersion: {
major: 0,
minor: 1,
},
hints: [],
_multi: null,
answer: null,
} as const;

/**
* Generate a Perseus item object for testing purposes.
*
* In order to better type Perseus objects used in testing, this function
* uses a basic Perseus object and updates it with custom values as needed.
*
* @param {Partial<PerseusItem>} customFields
* @returns PerseusItem
*/
export function generateTestPerseusItem(
customFields: Partial<PerseusItem> = {},
): PerseusItem {
return {...genericPerseusItemData, ...customFields};
}

0 comments on commit 7d4d098

Please sign in to comment.