Skip to content

docs(changeset): Fixed bugs related to numCorrect not updating properly for the Radio widget #2630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: um-correct
Choose a base branch
from

Conversation

SonicScrewdriver
Copy link
Contributor

@SonicScrewdriver SonicScrewdriver commented Jun 20, 2025

Summary:

We had 2 bugs reported related to the numCorrect value not correctly updating for the Radio Widget.

This PR fixes two of these bugs by ensuring that we're recalculating the numCorrect value when we delete choices, or switch in and out of multiple selection mode.

Unfortunately, I have not been able to recreate the third bug in the ticket.

Issue: LEMS-3230

Test plan:

  • New tests pass

Copy link
Contributor

github-actions bot commented Jun 20, 2025

Size Change: -55 B (-0.01%)

Total Size: 472 kB

Filename Size Change
packages/perseus-core/dist/es/index.js 20.3 kB -11 B (-0.05%)
packages/perseus-editor/dist/es/index.js 91.1 kB -44 B (-0.05%)
ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 20.7 kB
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 5.98 kB
packages/math-input/dist/es/index.js 98.6 kB
packages/math-input/dist/es/strings.js 1.61 kB
packages/perseus-linter/dist/es/index.js 7.14 kB
packages/perseus-score/dist/es/index.js 9.23 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/index.js 200 kB
packages/perseus/dist/es/strings.js 7.56 kB
packages/pure-markdown/dist/es/index.js 1.22 kB
packages/simple-markdown/dist/es/index.js 6.72 kB

compressed-size-action

@SonicScrewdriver SonicScrewdriver marked this pull request as ready for review June 20, 2025 22:27
Copy link
Contributor

github-actions bot commented Jun 20, 2025

npm Snapshot: Published

Good news!! We've packaged up the latest commit from this PR (2cccb7c) and published it to npm. You
can install it using the tag PR2630.

Example:

pnpm add @khanacademy/perseus@PR2630

If you are working in Khan Academy's frontend, you can run the below command.

./tools/bump_perseus_version.js -t PR2630

If you are working in Khan Academy's webapp, you can run the below command.

./dev/tools/bump_perseus_version.js -s n -t PR2630

let choices = this.props.choices;
if (!multipleSelect) {
const numCorrect = _.reduce(
this.props.choices,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the local choices object defined on line 123?

// we need to deselect all options
let choices = this.props.choices;
if (!multipleSelect) {
const numCorrect = _.reduce(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a good time to remove underscore, or would that be a big distraction from the purpose of this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do it! I'm down for any excuse to remove it

this.props.onChange({
multipleSelect: allowMultiple,
});
const multipleSelect = allowMultiple.multipleSelect;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a naming convention for boolean values like this? For instance, isMultipleSelect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh I don't know! It just bugged me that we were extracting multipleSelect out of allowMultiple and then calling it allowMultiple. 😅 I'm happy to make it isMultipleSelect though!

// Check that multipleSelect is updated and numCorrect is calculated
expect(onChangeMock).toHaveBeenCalledWith(
expect.objectContaining({
numCorrect: expect.any(Number),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this show that numCorrect has been calculated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't! Apparently my tired Friday brain didn't quite finish up this PR. I've fixed this up quite a bit!

it("updates numCorrect when deleting an option", async () => {
const onChangeMock = jest.fn();

function getCorrectChoice(): PerseusRadioChoice {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this function and its "incorrect" counterpart be hoisted to the describe parent instead of rebuilt for each test?

@@ -116,39 +116,44 @@ class RadioEditor extends React.Component<RadioEditorProps> {
};

onMultipleSelectChange: (arg1: any) => any = (allowMultiple) => {
allowMultiple = allowMultiple.multipleSelect;

const numCorrect = _.reduce(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea why were were doing this manually every time. We already have a nifty little method to handle this (deriveNumCorrect)!

const countChoices = count.countChoices;
this.props.onChange({
countChoices,
});
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was silly naming, imo.


return numCorrect ?? choices.filter((c) => c.correct).length;
return choices.filter((c) => c.correct).length;
}
Copy link
Contributor Author

@SonicScrewdriver SonicScrewdriver Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a spicy move, but I really don't understand why we were ever returning numCorrect in the first place, as everything I saw indicates that we always want to recalculate this value.

This is only used in the radio editor.tsx file with undefined for numCorrect, and in our parser for converting a Radio widget from v1 to a v2 as v1 did not have this option.


return numCorrect ?? choices.filter((c) => c.correct).length;
export function deriveNumCorrect(
choices: PerseusRadioWidgetOptions["choices"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be destructured?

Suggested change
choices: PerseusRadioWidgetOptions["choices"],
{choices} : PerseusRadioWidgetOptions,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooo it could, but I think we've generally used the first format 🤔.

Copy link
Contributor

@anakaren-rojas anakaren-rojas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌶️ move checks out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants