From 341d316aa8727ebb9e7fde28fc4e2d8779aa3e82 Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Wed, 11 Dec 2024 16:39:09 -0800 Subject: [PATCH 01/15] Upgrade ESLint and @typescript-eslint to remove lint warning (#1971) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: This PR bumps @typescript-eslint/* to v8.18.0 and ESLint to v8.57.1 to suppress a new lint warning after [bumping @khanacademy/eslint-plugi](https://github.com/Khan/perseus/pull/1949)n from v3.0.0 to v3.0.1. The warning looked like this: ``` $ yarn lint ============= WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree. You may find that it works just fine, or you may not. SUPPORTED TYPESCRIPT VERSIONS: >=4.7.4 <5.6.0 YOUR TYPESCRIPT VERSION: 5.7.2 Please only submit bug reports when using the officially supported version. ============= ``` Issue: FEI-6012 ## Test plan: `$ yarn --check-files; yarn lint` no warnings about TypeScript versions Author: jeremywiebe Reviewers: kevinb-khan, jeremywiebe, nishasy, #perseus Required Reviewers: Approved By: kevinb-khan Checks: ✅ Publish npm snapshot (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), ✅ Cypress (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x) Pull Request URL: https://github.com/Khan/perseus/pull/1971 --- .changeset/many-squids-relate.md | 14 ++ .eslintrc.js | 16 +- babel.config.js | 1 + jest.config.js | 1 + package.json | 8 +- packages/kas/.eslintrc.js | 2 +- packages/kas/src/nodes.ts | 2 +- packages/kas/src/parser-generator.ts | 2 +- packages/keypad-context/.eslintrc.js | 2 +- packages/kmath/.eslintrc.js | 2 +- packages/math-input/.eslintrc.js | 2 +- .../src/components/input/math-input.tsx | 12 +- .../components/input/mathquill-instance.ts | 1 + packages/math-input/src/enums.ts | 1 + packages/perseus-core/.eslintrc.js | 2 +- packages/perseus-editor/.eslintrc.js | 2 +- .../components/form-wrapped-text-field.tsx | 4 +- .../src/components/json-editor.tsx | 4 +- .../locked-figures/util.ts | 7 +- packages/perseus-linter/.eslintrc.js | 2 +- packages/perseus/.eslintrc.js | 2 +- packages/perseus/src/components/graph.tsx | 6 +- .../perseus/src/components/image-loader.tsx | 2 +- .../src/components/simple-keypad-input.tsx | 4 +- packages/perseus/src/components/sortable.tsx | 7 +- packages/perseus/src/components/svg-image.tsx | 6 +- .../visibility-observer.tsx | 2 +- packages/perseus/src/util.ts | 2 +- packages/perseus/src/util/scroll-utils.ts | 2 +- .../src/widgets/cs-program/cs-program.tsx | 2 +- .../graded-group-set/graded-group-set.tsx | 1 - .../perseus/src/widgets/iframe/iframe.tsx | 2 +- .../interactive-graphs/graphs/polygon.tsx | 2 +- .../src/widgets/interactive-graphs/utils.ts | 1 + .../perseus/src/widgets/orderer/orderer.tsx | 6 +- packages/perseus/src/zoom.ts | 4 +- packages/pure-markdown/.eslintrc.js | 2 +- packages/simple-markdown/.eslintrc.js | 2 +- packages/simple-markdown/src/index.ts | 2 +- utils/pre-publish-check-ci.ts | 1 + yarn.lock | 231 ++++++++---------- 41 files changed, 189 insertions(+), 187 deletions(-) create mode 100644 .changeset/many-squids-relate.md diff --git a/.changeset/many-squids-relate.md b/.changeset/many-squids-relate.md new file mode 100644 index 0000000000..a2f19b5be9 --- /dev/null +++ b/.changeset/many-squids-relate.md @@ -0,0 +1,14 @@ +--- +"@khanacademy/kas": patch +"@khanacademy/keypad-context": patch +"@khanacademy/kmath": patch +"@khanacademy/math-input": patch +"@khanacademy/perseus": patch +"@khanacademy/perseus-core": patch +"@khanacademy/perseus-editor": patch +"@khanacademy/perseus-linter": patch +"@khanacademy/pure-markdown": patch +"@khanacademy/simple-markdown": patch +--- + +Move to using optional chaining in a few places to resolve new lint rule violations. diff --git a/.eslintrc.js b/.eslintrc.js index f8ebfe48d2..64c2e1a093 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const fs = require("fs"); const path = require("path"); @@ -139,7 +139,7 @@ module.exports = { { files: ["config/**", "utils/**", "testing/*"], rules: { - "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-require-imports": "off", "import/no-commonjs": "off", "import/no-extraneous-dependencies": "off", "import/no-relative-packages": "off", @@ -166,6 +166,18 @@ module.exports = { ], }, }, + { + /** + * .typetest.ts files are used to do "type testing" :mindblown: + * It is common practice in these files to declare variables and + * expressions that are never used. + */ + files: ["*.typetest.ts"], + rules: { + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-expressions": "off", + }, + }, ], rules: { "max-lines": "off", diff --git a/babel.config.js b/babel.config.js index d848874b57..8dfb135f20 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,2 +1,3 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ // eslint-disable-next-line import/no-commonjs module.exports = require("./config/build/babel.config"); diff --git a/jest.config.js b/jest.config.js index b3486f1ea4..a4b55eba52 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,2 +1,3 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ module.exports = require("./config/test/test.config"); diff --git a/package.json b/package.json index d873e8d270..780c15e0ac 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,8 @@ "@types/react": "~18.2.64", "@types/react-dom": "~18.2.19", "@types/underscore": "^1.11.4", - "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.3.1", + "@typescript-eslint/eslint-plugin": "^8.18.0", + "@typescript-eslint/parser": "^8.18.0", "ancesdir": "^3.1.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", @@ -73,7 +73,7 @@ "cypress-jest-adapter": "^0.1.1", "cypress-real-events": "^1.12.0", "cypress-wait-until": "^3.0.1", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.5.5", @@ -81,7 +81,7 @@ "eslint-plugin-disable": "^2.0.3", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "27.9.0", + "eslint-plugin-jest": "28.9.0", "eslint-plugin-jsdoc": "^48.2.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-monorepo": "^0.3.2", diff --git a/packages/kas/.eslintrc.js b/packages/kas/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/kas/.eslintrc.js +++ b/packages/kas/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/kas/src/nodes.ts b/packages/kas/src/nodes.ts index 9d33c1fe05..12a6d5a4d0 100644 --- a/packages/kas/src/nodes.ts +++ b/packages/kas/src/nodes.ts @@ -181,7 +181,7 @@ abstract class Expr { // @ts-expect-error: TypeScript doesn't want to unify // `Function` with the `compile`'s return type. return new Function("vars", "return " + code + ";"); - } catch (e) { + } catch { throw new Error("Function did not compile: " + code); } } diff --git a/packages/kas/src/parser-generator.ts b/packages/kas/src/parser-generator.ts index 2559c6f45c..40066dc921 100755 --- a/packages/kas/src/parser-generator.ts +++ b/packages/kas/src/parser-generator.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ /* eslint-disable prettier/prettier */ diff --git a/packages/keypad-context/.eslintrc.js b/packages/keypad-context/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/keypad-context/.eslintrc.js +++ b/packages/keypad-context/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/kmath/.eslintrc.js b/packages/kmath/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/kmath/.eslintrc.js +++ b/packages/kmath/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/math-input/.eslintrc.js b/packages/math-input/.eslintrc.js index 687012161a..c859a84c08 100644 --- a/packages/math-input/.eslintrc.js +++ b/packages/math-input/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/math-input/src/components/input/math-input.tsx b/packages/math-input/src/components/input/math-input.tsx index 8114cd5fc0..2a9f5cfb52 100644 --- a/packages/math-input/src/components/input/math-input.tsx +++ b/packages/math-input/src/components/input/math-input.tsx @@ -108,8 +108,7 @@ class MathInput extends React.Component { // this `MathInput` component in an intermediary component // that translates accesses on the keypad into vanilla props, // to make this input keypad-agnostic. - this.props.keypadElement && - this.props.keypadElement.setCursor(cursor); + this.props.keypadElement?.setCursor(cursor); }, }, ); @@ -228,7 +227,7 @@ class MathInput extends React.Component { // in which case we don't want to dismiss the keypad on check. if (!isWithinKeypadBounds(x, y)) { this.blur(); - this.props.onBlur && this.props.onBlur(); + this.props.onBlur?.(); } } } @@ -613,10 +612,9 @@ class MathInput extends React.Component { cursor.insAtLeftEnd(this.mathField.mathField.controller().root); } // In that event, we need to update the cursor context ourselves. - this.props.keypadElement && - this.props.keypadElement.setCursor({ - context: this.mathField.contextForCursor(), - }); + this.props.keypadElement?.setCursor({ + context: this.mathField.contextForCursor(), + }); }; handleTouchStart = ( diff --git a/packages/math-input/src/components/input/mathquill-instance.ts b/packages/math-input/src/components/input/mathquill-instance.ts index c90f4203a0..43e6d1ff7b 100644 --- a/packages/math-input/src/components/input/mathquill-instance.ts +++ b/packages/math-input/src/components/input/mathquill-instance.ts @@ -132,6 +132,7 @@ export function createMathField( // HTTP request to fetch non-english speech rules, and cannot be easily // mocked in consuming packages now that we do not bundle source code. // When it eventually times out, it will cause arbitrary test failures. + // eslint-disable-next-line @typescript-eslint/no-unused-expressions !inJest && SpeechRuleEngine.setup(locale).then((SRE) => mathField.setMathspeakOverride(SRE.texToSpeech), diff --git a/packages/math-input/src/enums.ts b/packages/math-input/src/enums.ts index e9c32a12c1..73b73b4e03 100644 --- a/packages/math-input/src/enums.ts +++ b/packages/math-input/src/enums.ts @@ -7,6 +7,7 @@ export enum KeypadType { EXPRESSION = "EXPRESSION", } +// eslint-disable-next-line @typescript-eslint/no-unused-vars const KeyTypes = [ "EMPTY", // For numerals, variables, and any other characters that themselves diff --git a/packages/perseus-core/.eslintrc.js b/packages/perseus-core/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/perseus-core/.eslintrc.js +++ b/packages/perseus-core/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/perseus-editor/.eslintrc.js b/packages/perseus-editor/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/perseus-editor/.eslintrc.js +++ b/packages/perseus-editor/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/perseus-editor/src/components/form-wrapped-text-field.tsx b/packages/perseus-editor/src/components/form-wrapped-text-field.tsx index 5e0db3337b..302c83a790 100644 --- a/packages/perseus-editor/src/components/form-wrapped-text-field.tsx +++ b/packages/perseus-editor/src/components/form-wrapped-text-field.tsx @@ -86,14 +86,14 @@ class FormWrappedTextField extends React.Component { handleBlur = (e: React.ChangeEvent) => { const {onBlur} = this.props; - onBlur && onBlur(e); + onBlur?.(e); this.setState({focused: false}); }; handleFocus = (e: React.ChangeEvent) => { const {onFocus} = this.props; - onFocus && onFocus(e); + onFocus?.(e); this.setState({focused: true}); }; diff --git a/packages/perseus-editor/src/components/json-editor.tsx b/packages/perseus-editor/src/components/json-editor.tsx index 3c1f3186b9..1b2a0576fc 100644 --- a/packages/perseus-editor/src/components/json-editor.tsx +++ b/packages/perseus-editor/src/components/json-editor.tsx @@ -62,7 +62,7 @@ const JsonEditor: any = createReactClass({ this.props.onChange(json); }, ); - } catch (ex: any) { + } catch { this.setState({ currentValue: nextString, valid: false, @@ -93,7 +93,7 @@ const JsonEditor: any = createReactClass({ this.props.onChange(json); }, ); - } catch (ex: any) { + } catch { this.setState({ currentValue: JSON.stringify(this.props.value, null, 4), valid: true, diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts index 500fd06b00..8e3c365887 100644 --- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts +++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts @@ -151,9 +151,10 @@ export async function generateSpokenMathDetails(mathString: string) { case "specialCharacter": // We don't want the backslash from special character // to show up in the generated aria label. - piece.content.length > 1 - ? (convertedSpeech += piece.content.slice(1)) - : (convertedSpeech += piece.content); + convertedSpeech += + piece.content.length > 1 + ? piece.content.slice(1) + : piece.content; break; default: convertedSpeech += piece.content; diff --git a/packages/perseus-linter/.eslintrc.js b/packages/perseus-linter/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/perseus-linter/.eslintrc.js +++ b/packages/perseus-linter/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/perseus/.eslintrc.js b/packages/perseus/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/perseus/.eslintrc.js +++ b/packages/perseus/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/perseus/src/components/graph.tsx b/packages/perseus/src/components/graph.tsx index ca760d64c6..a3f30fb305 100644 --- a/packages/perseus/src/components/graph.tsx +++ b/packages/perseus/src/components/graph.tsx @@ -294,15 +294,13 @@ class Graph extends React.Component { const onMouseOver = $instructionsWrapper ? function () { - $instructionsWrapper && - $instructionsWrapper.css("opacity", invisible); + $instructionsWrapper?.css("opacity", invisible); } : undefined; const onMouseOut = $instructionsWrapper ? function () { - $instructionsWrapper && - $instructionsWrapper.css("opacity", visible); + $instructionsWrapper?.css("opacity", visible); } : undefined; /* eslint-enable indent */ diff --git a/packages/perseus/src/components/image-loader.tsx b/packages/perseus/src/components/image-loader.tsx index 23b69a1de9..e4c3420af5 100644 --- a/packages/perseus/src/components/image-loader.tsx +++ b/packages/perseus/src/components/image-loader.tsx @@ -129,7 +129,7 @@ class ImageLoader extends React.Component { onKeyUp = (e: React.KeyboardEvent) => { // 13 is enter key, 32 is space key if (e.keyCode === 13 || e.keyCode === 32) { - imgProps.onClick && imgProps.onClick(e); + imgProps.onClick?.(e); } }; onKeyDown = (e: React.KeyboardEvent) => { diff --git a/packages/perseus/src/components/simple-keypad-input.tsx b/packages/perseus/src/components/simple-keypad-input.tsx index aa6f9e4511..0889a92934 100644 --- a/packages/perseus/src/components/simple-keypad-input.tsx +++ b/packages/perseus/src/components/simple-keypad-input.tsx @@ -70,12 +70,12 @@ export default class SimpleKeypadInput extends React.Component { }, () => { if (_this._isMounted) { - onFocus && onFocus(); + onFocus?.(); } }, ); } else { - onFocus && onFocus(); + onFocus?.(); } }} value={value == null ? "" : "" + value} diff --git a/packages/perseus/src/components/sortable.tsx b/packages/perseus/src/components/sortable.tsx index 584b51d5da..d169d463d3 100644 --- a/packages/perseus/src/components/sortable.tsx +++ b/packages/perseus/src/components/sortable.tsx @@ -596,8 +596,7 @@ class Sortable extends React.Component { }); this.setState({items}, () => { - this.props.onMeasure && - this.props.onMeasure({widths: widths, heights: heights}); + this.props.onMeasure?.({widths: widths, heights: heights}); }); } @@ -646,7 +645,7 @@ class Sortable extends React.Component { nextItems.splice(index, 0, item); this.setState({items: nextItems}); - this.props.onChange && this.props.onChange({}); + this.props.onChange?.({}); } onMouseMove(key: SortableItem["key"]) { @@ -736,7 +735,7 @@ class Sortable extends React.Component { // HACK: We need to know *that* the widget changed, but currently it's // not set up in a nice way to tell us *how* it changed, since the // permutation of the items is stored in state. - this.props.onChange && this.props.onChange({}); + this.props.onChange?.({}); }); // @ts-expect-error - TS2339 - Property 'animationFrameRequest' does not exist on type 'Sortable'. diff --git a/packages/perseus/src/components/svg-image.tsx b/packages/perseus/src/components/svg-image.tsx index 1e2a13fc47..fc62b434ce 100644 --- a/packages/perseus/src/components/svg-image.tsx +++ b/packages/perseus/src/components/svg-image.tsx @@ -53,7 +53,7 @@ const doJSONP = function (url: string, options) { // A cleanup function to run when we're done. function cleanup() { - document.head && document.head.removeChild(script); + document.head?.removeChild(script); delete window[options.callbackName]; } @@ -71,7 +71,7 @@ const doJSONP = function (url: string, options) { }); // Insert the script to start the download. - document.head && document.head.appendChild(script); + document.head?.appendChild(script); }; // For offline exercises in the mobile app, we download the graphie data @@ -594,7 +594,7 @@ class SvgImage extends React.Component { this.props.zoomToFullSizeOnMobile, ); } - this.props.trackInteraction && this.props.trackInteraction(); + this.props.trackInteraction?.(); }; handleUpdate: (status: string) => void = (status: string) => { diff --git a/packages/perseus/src/components/visibility-observer/visibility-observer.tsx b/packages/perseus/src/components/visibility-observer/visibility-observer.tsx index 81a4465b6f..6365dbfc62 100644 --- a/packages/perseus/src/components/visibility-observer/visibility-observer.tsx +++ b/packages/perseus/src/components/visibility-observer/visibility-observer.tsx @@ -52,7 +52,7 @@ function findPositionInScrollContainer( : childRect.bottom < parentRect.top; return isAbove ? "hidden-above" : "hidden-below"; - } catch (e) { + } catch { return "unknown"; } } diff --git a/packages/perseus/src/util.ts b/packages/perseus/src/util.ts index baab945a3f..0b67bade83 100644 --- a/packages/perseus/src/util.ts +++ b/packages/perseus/src/util.ts @@ -607,7 +607,7 @@ const supportsPassiveEvents: () => boolean = () => { window.addEventListener("testPassive", null, opts); // @ts-expect-error - TS2769 - No overload matches this call. window.removeEventListener("testPassive", null, opts); - } catch (e: any) { + } catch { // Intentionally left empty! } diff --git a/packages/perseus/src/util/scroll-utils.ts b/packages/perseus/src/util/scroll-utils.ts index c8b8511cc4..7e0e30e754 100644 --- a/packages/perseus/src/util/scroll-utils.ts +++ b/packages/perseus/src/util/scroll-utils.ts @@ -73,7 +73,7 @@ const scrollElementToOffset = ( // TODO(jeff, WEB-1378): Use Wonder Blocks Timing API // eslint-disable-next-line no-restricted-syntax clearInterval(scrollInterval); - callback && callback(); + callback?.(); } }, tickLength); }; diff --git a/packages/perseus/src/widgets/cs-program/cs-program.tsx b/packages/perseus/src/widgets/cs-program/cs-program.tsx index 56327efd6e..1b60ef2159 100644 --- a/packages/perseus/src/widgets/cs-program/cs-program.tsx +++ b/packages/perseus/src/widgets/cs-program/cs-program.tsx @@ -81,7 +81,7 @@ class CSProgram extends React.Component implements Widget { let data: Record = {}; try { data = JSON.parse(e.originalEvent.data); - } catch (err: any) { + } catch { return; } diff --git a/packages/perseus/src/widgets/graded-group-set/graded-group-set.tsx b/packages/perseus/src/widgets/graded-group-set/graded-group-set.tsx index 25b5ef2c43..472847bedd 100644 --- a/packages/perseus/src/widgets/graded-group-set/graded-group-set.tsx +++ b/packages/perseus/src/widgets/graded-group-set/graded-group-set.tsx @@ -122,7 +122,6 @@ class GradedGroupSet extends React.Component implements Widget { }; shouldComponentUpdate(nextProps: Props, nextState: State): boolean { - nextProps.gradedGroups as ReadonlyArray; return nextProps !== this.props || nextState !== this.state; } diff --git a/packages/perseus/src/widgets/iframe/iframe.tsx b/packages/perseus/src/widgets/iframe/iframe.tsx index fa12214cd8..8018a529f6 100644 --- a/packages/perseus/src/widgets/iframe/iframe.tsx +++ b/packages/perseus/src/widgets/iframe/iframe.tsx @@ -78,7 +78,7 @@ class Iframe extends React.Component implements Widget { let data: Record = {}; try { data = JSON.parse(e.originalEvent.data); - } catch (err: any) { + } catch { return; } diff --git a/packages/perseus/src/widgets/interactive-graphs/graphs/polygon.tsx b/packages/perseus/src/widgets/interactive-graphs/graphs/polygon.tsx index 53b6e9f59d..d1fcf454ea 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/polygon.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/polygon.tsx @@ -339,7 +339,7 @@ export const hasFocusVisible = ( const matches = (selector: string) => element?.matches(selector) ?? false; try { return matches(":focus-visible"); - } catch (e) { + } catch { // jsdom doesn't support :focus-visible // (see https://github.com/jsdom/jsdom/issues/3426), // so the call to matches(":focus-visible") will fail in tests. diff --git a/packages/perseus/src/widgets/interactive-graphs/utils.ts b/packages/perseus/src/widgets/interactive-graphs/utils.ts index 60e4f218b3..d2f87585fd 100644 --- a/packages/perseus/src/widgets/interactive-graphs/utils.ts +++ b/packages/perseus/src/widgets/interactive-graphs/utils.ts @@ -116,6 +116,7 @@ export function replaceOutsideTeX(mathString: string) { let result = ""; for (const piece of parsed) { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions piece.type === "math" ? (result += "$" + piece.content + "$") : piece.type === "specialCharacter" diff --git a/packages/perseus/src/widgets/orderer/orderer.tsx b/packages/perseus/src/widgets/orderer/orderer.tsx index 972f50fd02..6f297b0b4d 100644 --- a/packages/perseus/src/widgets/orderer/orderer.tsx +++ b/packages/perseus/src/widgets/orderer/orderer.tsx @@ -213,7 +213,7 @@ class Card extends React.Component { if (loc) { this.setState({dragging: true}); this.bindMouseMoveUp(); - this.props.onMouseDown && this.props.onMouseDown(loc, this); + this.props.onMouseDown?.(loc, this); } }; @@ -225,7 +225,7 @@ class Card extends React.Component { event.preventDefault(); const loc = Util.extractPointerLocation(event); if (loc) { - this.props.onMouseMove && this.props.onMouseMove(loc); + this.props.onMouseMove?.(loc); } }; @@ -235,7 +235,7 @@ class Card extends React.Component { if (loc) { this.setState({dragging: false}); this.unbindMouseMoveUp(); - this.props.onMouseUp && this.props.onMouseUp(loc); + this.props.onMouseUp?.(loc); } }; diff --git a/packages/perseus/src/zoom.ts b/packages/perseus/src/zoom.ts index d20aae254a..daca6f9c56 100644 --- a/packages/perseus/src/zoom.ts +++ b/packages/perseus/src/zoom.ts @@ -125,7 +125,9 @@ function changeViewportTag( // finished resetting. // TODO(jeff, CP-3128): Use Wonder Blocks Timing API. // eslint-disable-next-line no-restricted-syntax - callback && setTimeout(callback, 0); + if (callback != null) { + setTimeout(callback, 0); + } }, 0); } diff --git a/packages/pure-markdown/.eslintrc.js b/packages/pure-markdown/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/pure-markdown/.eslintrc.js +++ b/packages/pure-markdown/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/simple-markdown/.eslintrc.js b/packages/simple-markdown/.eslintrc.js index 09c8638f13..6c26fa1595 100644 --- a/packages/simple-markdown/.eslintrc.js +++ b/packages/simple-markdown/.eslintrc.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-commonjs */ const path = require("path"); diff --git a/packages/simple-markdown/src/index.ts b/packages/simple-markdown/src/index.ts index e4ad7187b2..698ae9bd04 100644 --- a/packages/simple-markdown/src/index.ts +++ b/packages/simple-markdown/src/index.ts @@ -589,7 +589,7 @@ var sanitizeUrl = function (url?: string | null) { ) { return null; } - } catch (e: any) { + } catch { // invalid URLs should throw a TypeError // see for instance: `new URL("");` return null; diff --git a/utils/pre-publish-check-ci.ts b/utils/pre-publish-check-ci.ts index efa2912d6f..3b4f00c209 100755 --- a/utils/pre-publish-check-ci.ts +++ b/utils/pre-publish-check-ci.ts @@ -18,6 +18,7 @@ fg(path.join(__dirname, "..", "packages", "*", "package.json")).then( (pkgPaths) => { // eslint-disable-next-line promise/always-return for (const pkgPath of pkgPaths) { + // eslint-disable-next-line @typescript-eslint/no-require-imports const pkgJson = require(path.relative(__dirname, pkgPath)); if (!checkPrivate(pkgJson)) { diff --git a/yarn.lock b/yarn.lock index 2ba3f5266c..7ef8ffd5cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2014,7 +2014,12 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== @@ -2034,22 +2039,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/js@8.57.1": + version "8.57.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" + "@humanwhocodes/object-schema" "^2.0.3" debug "^4.3.1" minimatch "^3.0.5" @@ -2058,10 +2063,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@hypnosphi/create-react-context@^0.3.1": version "0.3.1" @@ -3755,11 +3760,6 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@^7.0.12": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - "@types/json-schema@^7.0.9": version "7.0.14" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" @@ -3870,11 +3870,6 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== -"@types/semver@^7.5.0": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - "@types/sinonjs__fake-timers@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" @@ -3943,32 +3938,30 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz#0d8f38a6c8a1802139e62184ee7a68ed024f30a1" - integrity sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.3.1" - "@typescript-eslint/type-utils" "7.3.1" - "@typescript-eslint/utils" "7.3.1" - "@typescript-eslint/visitor-keys" "7.3.1" - debug "^4.3.4" +"@typescript-eslint/eslint-plugin@^8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz#0901933326aea4443b81df3f740ca7dfc45c7bea" + integrity sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.18.0" + "@typescript-eslint/type-utils" "8.18.0" + "@typescript-eslint/utils" "8.18.0" + "@typescript-eslint/visitor-keys" "8.18.0" graphemer "^1.4.0" - ignore "^5.2.4" + ignore "^5.3.1" natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" -"@typescript-eslint/parser@^7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.3.1.tgz#c4ba7dc2744318a5e4506596cbc3a0086255c526" - integrity sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw== +"@typescript-eslint/parser@^8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.0.tgz#a1c9456cbb6a089730bf1d3fc47946c5fb5fe67b" + integrity sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q== dependencies: - "@typescript-eslint/scope-manager" "7.3.1" - "@typescript-eslint/types" "7.3.1" - "@typescript-eslint/typescript-estree" "7.3.1" - "@typescript-eslint/visitor-keys" "7.3.1" + "@typescript-eslint/scope-manager" "8.18.0" + "@typescript-eslint/types" "8.18.0" + "@typescript-eslint/typescript-estree" "8.18.0" + "@typescript-eslint/visitor-keys" "8.18.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -3979,14 +3972,6 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz#73fd0cb4211a7be23e49e5b6efec8820caa6ec36" - integrity sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag== - dependencies: - "@typescript-eslint/types" "7.3.1" - "@typescript-eslint/visitor-keys" "7.3.1" - "@typescript-eslint/scope-manager@8.17.0": version "8.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz#a3f49bf3d4d27ff8d6b2ea099ba465ef4dbcaa3a" @@ -3995,31 +3980,39 @@ "@typescript-eslint/types" "8.17.0" "@typescript-eslint/visitor-keys" "8.17.0" -"@typescript-eslint/type-utils@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz#cbf90d3d7e788466aa8a5c0ab3f46103f098aa0d" - integrity sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw== +"@typescript-eslint/scope-manager@8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz#30b040cb4557804a7e2bcc65cf8fdb630c96546f" + integrity sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw== + dependencies: + "@typescript-eslint/types" "8.18.0" + "@typescript-eslint/visitor-keys" "8.18.0" + +"@typescript-eslint/type-utils@8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz#6f0d12cf923b6fd95ae4d877708c0adaad93c471" + integrity sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow== dependencies: - "@typescript-eslint/typescript-estree" "7.3.1" - "@typescript-eslint/utils" "7.3.1" + "@typescript-eslint/typescript-estree" "8.18.0" + "@typescript-eslint/utils" "8.18.0" debug "^4.3.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" "@typescript-eslint/types@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.3.1.tgz#ae104de8efa4227a462c0874d856602c5994413c" - integrity sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw== - "@typescript-eslint/types@8.17.0": version "8.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.17.0.tgz#ef84c709ef8324e766878834970bea9a7e3b72cf" integrity sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA== +"@typescript-eslint/types@8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.0.tgz#3afcd30def8756bc78541268ea819a043221d5f3" + integrity sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA== + "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" @@ -4033,20 +4026,6 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz#598848195fad34c7aa73f548bd00a4d4e5f5e2bb" - integrity sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ== - dependencies: - "@typescript-eslint/types" "7.3.1" - "@typescript-eslint/visitor-keys" "7.3.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - "@typescript-eslint/typescript-estree@8.17.0": version "8.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz#40b5903bc929b1e8dd9c77db3cb52cfb199a2a34" @@ -4061,18 +4040,19 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.3.1.tgz#fc28fd508ccf89495012561b7c02a6fdad162460" - integrity sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ== +"@typescript-eslint/typescript-estree@8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz#d8ca785799fbb9c700cdff1a79c046c3e633c7f9" + integrity sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg== dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.3.1" - "@typescript-eslint/types" "7.3.1" - "@typescript-eslint/typescript-estree" "7.3.1" - semver "^7.5.4" + "@typescript-eslint/types" "8.18.0" + "@typescript-eslint/visitor-keys" "8.18.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" "@typescript-eslint/utils@8.17.0": version "8.17.0" @@ -4084,7 +4064,17 @@ "@typescript-eslint/types" "8.17.0" "@typescript-eslint/typescript-estree" "8.17.0" -"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.58.0", "@typescript-eslint/utils@^5.62.0": +"@typescript-eslint/utils@8.18.0", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.0.tgz#48f67205d42b65d895797bb7349d1be5c39a62f7" + integrity sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.18.0" + "@typescript-eslint/types" "8.18.0" + "@typescript-eslint/typescript-estree" "8.18.0" + +"@typescript-eslint/utils@^5.58.0", "@typescript-eslint/utils@^5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== @@ -4106,14 +4096,6 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@7.3.1": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz#6ddef14a3ce2a79690f01176f5305c34d7b93d8c" - integrity sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw== - dependencies: - "@typescript-eslint/types" "7.3.1" - eslint-visitor-keys "^3.4.1" - "@typescript-eslint/visitor-keys@8.17.0": version "8.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz#4dbcd0e28b9bf951f4293805bf34f98df45e1aa8" @@ -4122,6 +4104,14 @@ "@typescript-eslint/types" "8.17.0" eslint-visitor-keys "^4.2.0" +"@typescript-eslint/visitor-keys@8.18.0": + version "8.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz#7b6d33534fa808e33a19951907231ad2ea5c36dd" + integrity sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw== + dependencies: + "@typescript-eslint/types" "8.18.0" + eslint-visitor-keys "^4.2.0" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -6888,12 +6878,12 @@ eslint-plugin-import@^2.29.1: semver "^6.3.1" tsconfig-paths "^3.15.0" -eslint-plugin-jest@27.9.0: - version "27.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b" - integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== +eslint-plugin-jest@28.9.0: + version "28.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz#19168dfaed124339cd2252c4c4d1ac3688aeb243" + integrity sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ== dependencies: - "@typescript-eslint/utils" "^5.10.0" + "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" eslint-plugin-jsdoc@^48.2.1: version "48.2.1" @@ -7057,16 +7047,16 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== +eslint@^8.57.1: + version "8.57.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" + "@eslint/js" "8.57.1" + "@humanwhocodes/config-array" "^0.13.0" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" "@ungap/structured-clone" "^1.2.0" @@ -8322,7 +8312,7 @@ ignore@^5.0.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== -ignore@^5.1.8: +ignore@^5.1.8, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -8332,11 +8322,6 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -ignore@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" @@ -10414,13 +10399,6 @@ min-indent@^1.0.0, min-indent@^1.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -13627,11 +13605,6 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-api-utils@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - ts-api-utils@^1.3.0: version "1.4.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" From 701895c01bd2792a4dccc6ce0d5edc23f7483db3 Mon Sep 17 00:00:00 2001 From: Nisha Yerunkar Date: Wed, 11 Dec 2024 17:20:33 -0800 Subject: [PATCH 02/15] [Locked Figure Labels] Update placeholder to include TeX $s (#1985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: Now that TeX needs $s around it to render as TeX, update the placeholder in the interactive graph editor label settings to reflect that. While I'm here, I also updated the starting text on the locked label settings to be "label" so that it's easier to prevent empty labels. Charlie also expressed that this makes it easier to tell the labels' tab orders. The placeholder will still show up if the text is deleted. Issue: none ## Test plan: - http://localhost:6006/?path=/story/perseuseditor-widgets-interactive-graph--mafs-with-locked-figure-labels-all-flags - Go to locked label's settings - Clear the text field - Confirm that the placeholder says "ex. $x^2$ or $\frac{1}{2}$" | Before | After | | --- | --- | | ![Screenshot 2024-12-11 at 1 50 20 PM](https://github.com/user-attachments/assets/ffa1cbbc-77f9-4c5e-8507-e3369b92a109) | ![Screenshot 2024-12-11 at 1 50 24 PM](https://github.com/user-attachments/assets/703649b5-5a7d-4db3-b486-58821839e4c5) | Author: nishasy Reviewers: jeremywiebe Required Reviewers: Approved By: jeremywiebe Checks: ✅ Publish npm snapshot (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), ✅ Cypress (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x) Pull Request URL: https://github.com/Khan/perseus/pull/1985 --- .changeset/chilly-pigs-clean.md | 5 +++++ .../locked-figures/locked-label-settings.test.tsx | 1 + .../locked-figures/locked-label-settings.tsx | 2 +- .../interactive-graph-editor/locked-figures/util.test.ts | 2 +- .../widgets/interactive-graph-editor/locked-figures/util.ts | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changeset/chilly-pigs-clean.md diff --git a/.changeset/chilly-pigs-clean.md b/.changeset/chilly-pigs-clean.md new file mode 100644 index 0000000000..29fd6a4851 --- /dev/null +++ b/.changeset/chilly-pigs-clean.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus-editor": patch +--- + +[Locked Figure Labels] Update placeholder to include TeX \$s. Start new visible labels with text "label". diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.test.tsx b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.test.tsx index 4f6e1b86d0..d58bb7617b 100644 --- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.test.tsx +++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.test.tsx @@ -146,6 +146,7 @@ describe("Locked Label Settings", () => { render( , { diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.tsx b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.tsx index 2413b028c7..c41a385cbf 100644 --- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.tsx +++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/locked-label-settings.tsx @@ -125,7 +125,7 @@ export default function LockedLabelSettings(props: Props) { onChangeProps({ text: newValue, diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.test.ts b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.test.ts index 4a32da91d3..43cc54e17b 100644 --- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.test.ts +++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.test.ts @@ -106,7 +106,7 @@ describe("getDefaultFigureForType", () => { expect(figure).toEqual({ type: "label", coord: [0, 0], - text: "", + text: "label", color: "grayH", size: "medium", }); diff --git a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts index 8e3c365887..e2d8d5a30b 100644 --- a/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts +++ b/packages/perseus-editor/src/widgets/interactive-graph-editor/locked-figures/util.ts @@ -95,7 +95,7 @@ export function getDefaultFigureForType(type: LockedFigureType): LockedFigure { return { type: "label", coord: [0, 0], - text: "", + text: "label", color: DEFAULT_COLOR, size: "medium", }; From f9906728c1a8f09c91c11d824718b8a06d6a7609 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 12 Dec 2024 07:33:38 -0600 Subject: [PATCH 03/15] Remove `scoreInput` (#1973) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bulk of it removed, tests passing * odds and ends * changeset * remove i18n * respond to Jeremys feedback * remove scoring things again * changeset * Remove `guessAndScore` (#1974) ## Summary: Remove `guessAndScore` from Renderer. This hasn't been used in learner-facing logic for a little bit now. The bulk of this PR is updating internal usage - tools for testing exercise correctness were using this (specifically in Cypress and our custom matchers for Jest); so most of the work was porting tests to use `scorePerseusItem` instead. ## Test plan: From a learner's perspective, this is dead code. So while this is a major API change, it's mostly removing dead code and updating tests. Tests should continue to run successfully. Author: handeyeco Reviewers: handeyeco, Myranae, jeremywiebe Required Reviewers: Approved By: Myranae, jeremywiebe Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Cypress (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), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ⏹️ [cancelled] Publish npm snapshot (ubuntu-latest, 20.x), ⏹️ [cancelled] Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ⏹️ [cancelled] Check builds for changes in size (ubuntu-latest, 20.x), ⏹️ [cancelled] Cypress (ubuntu-latest, 20.x), ⏹️ [cancelled] Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ 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), ✅ 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) Pull Request URL: https://github.com/Khan/perseus/pull/1974 --- .changeset/bright-tomatoes-sit.md | 6 + .changeset/large-flies-divide.md | 5 + config/test/custom-matchers.ts | 90 ++------------ packages/perseus-core/src/types.ts | 1 - .../src/__tests__/renderer-api.test.tsx | 31 ++++- .../__tests__/server-item-renderer.test.tsx | 25 ---- .../src/components/__tests__/sorter.test.tsx | 15 ++- packages/perseus/src/renderer.tsx | 10 -- packages/perseus/src/server-item-renderer.tsx | 37 ------ packages/perseus/src/util/test-utils.ts | 16 +++ packages/perseus/src/widget-container.tsx | 4 +- .../widgets/categorizer/categorizer.test.ts | 8 +- .../src/widgets/definition/definition.test.ts | 11 +- .../__tests__/deprecated-standin.test.ts | 11 +- .../src/widgets/dropdown/dropdown.test.ts | 23 +++- .../widgets/expression/expression.test.tsx | 19 ++- .../widgets/expression/score-expression.ts | 3 - .../widgets/graded-group/graded-group.test.ts | 4 +- .../src/widgets/grapher/grapher.cypress.ts | 113 +++++++++++++----- .../perseus/src/widgets/image/image.test.ts | 7 +- .../widgets/input-number/input-number.test.ts | 31 ++++- .../input-number/score-input-number.ts | 2 - .../widgets/interaction/interaction.test.ts | 11 +- .../interactive-graph.test.tsx | 50 ++++++-- .../src/widgets/matcher/matcher.test.tsx | 19 ++- .../perseus/src/widgets/matrix/matrix.test.ts | 13 +- .../widgets/number-line/number-line.test.ts | 13 +- .../numeric-input/numeric-input.test.ts | 49 ++++++-- .../numeric-input/score-numeric-input.ts | 3 - .../src/widgets/orderer/orderer.test.ts | 19 ++- .../widgets/passage-ref/passage-ref.test.ts | 7 +- .../src/widgets/radio/__tests__/radio.test.ts | 101 ++++++++++++---- .../server-item-renderer-with-debug-ui.tsx | 29 ++++- 33 files changed, 517 insertions(+), 269 deletions(-) create mode 100644 .changeset/bright-tomatoes-sit.md create mode 100644 .changeset/large-flies-divide.md diff --git a/.changeset/bright-tomatoes-sit.md b/.changeset/bright-tomatoes-sit.md new file mode 100644 index 0000000000..8776d83d87 --- /dev/null +++ b/.changeset/bright-tomatoes-sit.md @@ -0,0 +1,6 @@ +--- +"@khanacademy/perseus": major +"@khanacademy/perseus-core": major +--- + +Remove `scoreInput` from ServerItemRenderer diff --git a/.changeset/large-flies-divide.md b/.changeset/large-flies-divide.md new file mode 100644 index 0000000000..9d478f80f8 --- /dev/null +++ b/.changeset/large-flies-divide.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": major +--- + +Remove `guessAndScore` from Renderer diff --git a/config/test/custom-matchers.ts b/config/test/custom-matchers.ts index 5906790cb8..afddd66c24 100644 --- a/config/test/custom-matchers.ts +++ b/config/test/custom-matchers.ts @@ -19,56 +19,17 @@ declare global { } } -type PerseusRenderer = { - guessAndScore: () => [Array, PerseusScore]; -}; - -type Answerable = PerseusRenderer | PerseusScore; - -function isRenderer(obj: Answerable): obj is PerseusRenderer { - // @ts-expect-error - TS(2339) - TS is annoying - return obj?.guessAndScore !== undefined; -} - -function check(answerable: Answerable) { - let widgetState: string = ""; - let score: PerseusScore; - - if (isRenderer(answerable)) { - const result = answerable.guessAndScore(); - widgetState = JSON.stringify(result[0]); - score = result[1]; - } else { - score = answerable; - } - - return {widgetState, score}; -} - -function maybeAddState(message: string, widgetState: string): string { - if (!widgetState) { - return message; - } - - return message + `; widget state: ${widgetState}`; -} - expect.extend({ toHaveBeenAnsweredCorrectly( - answerable: Answerable, + score: PerseusScore, options: { shouldHavePoints: boolean; }, ) { const shouldHavePoints = options?.shouldHavePoints ?? true; - const {widgetState, score} = check(answerable); if (score.type === "invalid") { - const errMessage = maybeAddState( - `Invalid answer: ${score.message || "(no message)"}`, - widgetState, - ); - + const errMessage = `Invalid answer: ${score.message || "(no message)"}`; return { pass: false, message: () => errMessage, @@ -83,10 +44,7 @@ expect.extend({ } if (score.earned !== score.total) { - const errMessage = maybeAddState( - "Problem was answered incorrectly", - widgetState, - ); + const errMessage = "Problem was answered incorrectly"; return { pass: false, @@ -95,20 +53,14 @@ expect.extend({ } if (shouldHavePoints && score.total < 1) { - const errMessage = maybeAddState( - "Score did not have any points", - widgetState, - ); + const errMessage = "Score did not have any points"; return { pass: false, message: () => errMessage, }; } else if (!shouldHavePoints && score.total > 0) { - const errMessage = maybeAddState( - "Score had points when it shouldn't have", - widgetState, - ); + const errMessage = "Score had points when it shouldn't have"; return { pass: false, @@ -119,14 +71,9 @@ expect.extend({ return {pass: true, message: () => ""}; }, - toHaveInvalidInput(answerable: Answerable, message: string | null) { - const {widgetState, score} = check(answerable); - + toHaveInvalidInput(score: PerseusScore, message: string | null) { if (score.type !== "invalid") { - const errMessage = maybeAddState( - `Answer state is not invalid. Score: ${JSON.stringify(score)}`, - widgetState, - ); + const errMessage = `Answer state is not invalid. Score: ${JSON.stringify(score)}`; return { pass: false, @@ -135,12 +82,9 @@ expect.extend({ } if (message && (!score.message || !score.message.includes(message))) { - const errMessage = maybeAddState( - `Message shown for invalid input did not include "${message}": ${ - score.message || "(no message)" - }. Score: ${JSON.stringify(score)}`, - widgetState, - ); + const errMessage = `Message shown for invalid input did not include "${message}": ${ + score.message || "(no message)" + }. Score: ${JSON.stringify(score)}`; return { pass: false, @@ -151,14 +95,9 @@ expect.extend({ return {pass: true, message: () => ""}; }, - toHaveBeenAnsweredIncorrectly(answerable: Answerable) { - const {widgetState, score} = check(answerable); - + toHaveBeenAnsweredIncorrectly(score: PerseusScore) { if (score.type === "invalid") { - const errMessage = maybeAddState( - `Invalid answer: ${score.message || "(no message)"}`, - widgetState, - ); + const errMessage = `Invalid answer: ${score.message || "(no message)"}`; return { pass: false, @@ -179,10 +118,7 @@ expect.extend({ if (score.earned !== 0) { return { pass: false, - message: () => - `Problem was answered correctly. Widget state: ${JSON.stringify( - widgetState, - )}`, + message: () => `Problem was answered correctly.`, }; } diff --git a/packages/perseus-core/src/types.ts b/packages/perseus-core/src/types.ts index f9b93fd731..2e71b875bd 100644 --- a/packages/perseus-core/src/types.ts +++ b/packages/perseus-core/src/types.ts @@ -14,7 +14,6 @@ type State = any; export interface RendererInterface { getSerializedState(): State; restoreSerializedState(state: State, callback?: () => void): void; - scoreInput(): KEScore; blur(): void; focus(): boolean | null | undefined; props: any; diff --git a/packages/perseus/src/__tests__/renderer-api.test.tsx b/packages/perseus/src/__tests__/renderer-api.test.tsx index f39e19bea8..c4c67919f3 100644 --- a/packages/perseus/src/__tests__/renderer-api.test.tsx +++ b/packages/perseus/src/__tests__/renderer-api.test.tsx @@ -12,6 +12,7 @@ import {ClassNames} from "../perseus-api"; import Renderer from "../renderer"; import {mockStrings} from "../strings"; import {registerAllWidgetsForTesting} from "../util/register-all-widgets-for-testing"; +import {scorePerseusItemTesting} from "../util/test-utils"; import {renderQuestion} from "../widgets/__testutils__/renderQuestion"; import imageItem from "./test-items/image-item"; @@ -46,8 +47,13 @@ describe("Perseus API", function () { // Act act(() => renderer.setInputValue(["input-number 1"], "5")); + const score = scorePerseusItemTesting( + inputNumber1Item.question, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should be able to produce a wrong value", function () { @@ -57,8 +63,13 @@ describe("Perseus API", function () { // Act act(() => renderer.setInputValue(["input-number 1"], "3")); + const score = scorePerseusItemTesting( + inputNumber1Item.question, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("should be able to produce an empty score", function () { @@ -66,10 +77,22 @@ describe("Perseus API", function () { const {renderer} = renderQuestion(inputNumber1Item.question); act(() => renderer.setInputValue(["input-number 1"], "3")); - expect(renderer).toHaveBeenAnsweredIncorrectly(); + + let score = scorePerseusItemTesting( + inputNumber1Item.question, + renderer.getUserInputMap(), + ); + + expect(score).toHaveBeenAnsweredIncorrectly(); act(() => renderer.setInputValue(["input-number 1"], "")); - expect(renderer).toHaveInvalidInput(); + + score = scorePerseusItemTesting( + inputNumber1Item.question, + renderer.getUserInputMap(), + ); + + expect(score).toHaveInvalidInput(); }); it("should be able to accept a callback", function (done) { diff --git a/packages/perseus/src/__tests__/server-item-renderer.test.tsx b/packages/perseus/src/__tests__/server-item-renderer.test.tsx index aca6b1a413..60ffc47268 100644 --- a/packages/perseus/src/__tests__/server-item-renderer.test.tsx +++ b/packages/perseus/src/__tests__/server-item-renderer.test.tsx @@ -118,31 +118,6 @@ describe("server item renderer", () => { expect(screen.getByRole("textbox")).toBeVisible(); }); - it("should be invalid if no input provided", async () => { - // Arrange - const {renderer} = renderQuestion(itemWithInput); - - // Act - const score = await act(() => renderer.scoreInput()); - - // Assert - expect(score.correct).toBe(false); - expect(score.empty).toBe(true); - }); - - it("should be answerable", async () => { - // Arrange - const {renderer} = renderQuestion(itemWithInput); - await userEvent.type(screen.getByRole("textbox"), "-42"); - - // Act - const score = await act(() => renderer.scoreInput()); - - // Assert - expect(score.correct).toBe(true); - expect(score.empty).toBe(false); - }); - it("should pass showSolutions to the widgets", () => { // Arrange renderQuestion(itemWithRadioAndExpressionWidgets, Object.freeze({}), { diff --git a/packages/perseus/src/components/__tests__/sorter.test.tsx b/packages/perseus/src/components/__tests__/sorter.test.tsx index 2101d87ff8..3924b4c462 100644 --- a/packages/perseus/src/components/__tests__/sorter.test.tsx +++ b/packages/perseus/src/components/__tests__/sorter.test.tsx @@ -4,6 +4,7 @@ import * as React from "react"; import {testDependencies} from "../../../../../testing/test-dependencies"; import {wait} from "../../../../../testing/wait"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../../widgets/__testutils__/renderQuestion"; import {question1} from "../__testdata__/sorter.testdata"; @@ -82,8 +83,13 @@ describe("sorter widget", () => { act(() => sorter.moveOptionToIndex(option, 3)); }); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can be answered incorrectly", () => { // Arrange @@ -101,7 +107,12 @@ describe("sorter widget", () => { }, ); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/renderer.tsx b/packages/perseus/src/renderer.tsx index 80312ba144..09a7f7b8a0 100644 --- a/packages/perseus/src/renderer.tsx +++ b/packages/perseus/src/renderer.tsx @@ -1742,16 +1742,6 @@ class Renderer return combinedScore; } - /** - * @deprecated use scorePerseusItem - */ - guessAndScore: () => [UserInputArray, PerseusScore] = () => { - const totalGuess = this.getUserInput(); - const totalScore = this.score(); - - return [totalGuess, totalScore]; - }; - // TranslationLinter callback handletranslationLintErrors: (lintErrors: ReadonlyArray) => void = ( lintErrors: ReadonlyArray, diff --git a/packages/perseus/src/server-item-renderer.tsx b/packages/perseus/src/server-item-renderer.tsx index b98db07c3d..5152db3bde 100644 --- a/packages/perseus/src/server-item-renderer.tsx +++ b/packages/perseus/src/server-item-renderer.tsx @@ -19,9 +19,7 @@ import HintsRenderer from "./hints-renderer"; import LoadingContext from "./loading-context"; import {ApiOptions} from "./perseus-api"; import Renderer from "./renderer"; -import {scorePerseusItem} from "./renderer-util"; import Util from "./util"; -import {keScoreFromPerseusScore} from "./util/scoring"; import type {PerseusItem, ShowSolutions} from "./perseus-types"; import type { @@ -348,41 +346,6 @@ export class ServerItemRenderer return this.questionRenderer.getUserInputMap(); } - /** - * Grades the item. - * - * @deprecated use scorePerseusItem - */ - scoreInput(): KEScore { - const guess = this.getUserInput(); - const score = scorePerseusItem( - this.props.item.question, - guess, - this.context.strings, - this.context.locale, - ); - - // Continue to include an empty guess for the now defunct answer area. - // TODO(alex): Check whether we rely on the format here for - // analyzing ProblemLogs. If not, remove this layer. - const maxCompatGuess = [this.questionRenderer.getUserInput(), []]; - - const keScore = keScoreFromPerseusScore( - score, - maxCompatGuess, - this.questionRenderer.getSerializedState(), - ); - - const emptyQuestionAreaWidgets = this.questionRenderer.emptyWidgets(); - - this.setState({ - questionCompleted: keScore.correct, - questionHighlightedWidgets: emptyQuestionAreaWidgets, - }); - - return keScore; - } - /** * Returns an array of all widget IDs in the order they occur in * the question content. diff --git a/packages/perseus/src/util/test-utils.ts b/packages/perseus/src/util/test-utils.ts index 15d45ac899..0106ac5338 100644 --- a/packages/perseus/src/util/test-utils.ts +++ b/packages/perseus/src/util/test-utils.ts @@ -1,11 +1,17 @@ +import {scorePerseusItem} from "../renderer-util"; +import {mockStrings} from "../strings"; + import type { CategorizerWidget, ExpressionWidget, InteractiveGraphWidget, NumericInputWidget, PerseusItem, + PerseusRenderer, RadioWidget, } from "../perseus-types"; +import type {PerseusScore} from "../types"; +import type {UserInputMap} from "../validation.types"; export const genericPerseusItemData: PerseusItem = { question: { @@ -32,6 +38,16 @@ export const genericPerseusItemData: PerseusItem = { answer: null, } as const; +/** + * Thin wrapper around scorePerseusItem for internal testing + */ +export function scorePerseusItemTesting( + perseusRenderData: PerseusRenderer, + userInputMap: UserInputMap, +): PerseusScore { + return scorePerseusItem(perseusRenderData, userInputMap, mockStrings, "en"); +} + /** * Generate a Perseus item object for testing purposes. * diff --git a/packages/perseus/src/widget-container.tsx b/packages/perseus/src/widget-container.tsx index 7396b70ba7..e10464a69e 100644 --- a/packages/perseus/src/widget-container.tsx +++ b/packages/perseus/src/widget-container.tsx @@ -153,8 +153,8 @@ class WidgetContainer extends React.Component { : {...this.props.linterContext, highlightLint: false}; // Note: if you add more props here, please consider whether or not - // it should be auto-serialized (e.g. used in scoreInput()). See - // widget-jsonify-deprecated.jsx and widget-prop-denylist.jsx + // it should be auto-serialized. + // See widget-jsonify-deprecated.jsx and widget-prop-denylist.jsx // We default to an empty object for style instead of null // because of a strange bug where the static styles aren't applied diff --git a/packages/perseus/src/widgets/categorizer/categorizer.test.ts b/packages/perseus/src/widgets/categorizer/categorizer.test.ts index 96517d76a1..faffac1441 100644 --- a/packages/perseus/src/widgets/categorizer/categorizer.test.ts +++ b/packages/perseus/src/widgets/categorizer/categorizer.test.ts @@ -5,6 +5,7 @@ import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; import {scorePerseusItem} from "../../renderer-util"; import {mockStrings} from "../../strings"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {Categorizer} from "./categorizer"; @@ -123,8 +124,13 @@ describe("categorizer widget", () => { })[1], ); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); + // assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can get user input from props", () => { diff --git a/packages/perseus/src/widgets/definition/definition.test.ts b/packages/perseus/src/widgets/definition/definition.test.ts index d1fccca161..e295cf1079 100644 --- a/packages/perseus/src/widgets/definition/definition.test.ts +++ b/packages/perseus/src/widgets/definition/definition.test.ts @@ -3,6 +3,7 @@ import {userEvent as userEventLib} from "@testing-library/user-event"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import type {UserEvent} from "@testing-library/user-event"; @@ -123,11 +124,17 @@ describe("Definition widget", () => { }); it("should not affect answerable", () => { - // Arrange / Act + // Arrange const {renderer} = renderQuestion(question); + // Act + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredCorrectly({ + expect(score).toHaveBeenAnsweredCorrectly({ shouldHavePoints: false, }); }); diff --git a/packages/perseus/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts b/packages/perseus/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts index 3aa8b98c69..f4b394980b 100644 --- a/packages/perseus/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts +++ b/packages/perseus/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts @@ -1,5 +1,6 @@ import {testDependencies} from "../../../../../../testing/test-dependencies"; import * as Dependencies from "../../../dependencies"; +import {scorePerseusItemTesting} from "../../../util/test-utils"; import {renderQuestion} from "../../__testutils__/renderQuestion"; const question = { @@ -41,10 +42,16 @@ describe("Deprecated Standin widget", () => { }); it("should be scorable and always give points", () => { - // Arrange / Act + // Arrange const {renderer} = renderQuestion(question); + // Act + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); }); diff --git a/packages/perseus/src/widgets/dropdown/dropdown.test.ts b/packages/perseus/src/widgets/dropdown/dropdown.test.ts index 6facb4099b..d327eb84f0 100644 --- a/packages/perseus/src/widgets/dropdown/dropdown.test.ts +++ b/packages/perseus/src/widgets/dropdown/dropdown.test.ts @@ -3,6 +3,7 @@ import {userEvent as userEventLib} from "@testing-library/user-event"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question1} from "./dropdown.testdata"; @@ -62,10 +63,14 @@ describe("Dropdown widget", () => { const dropdown = screen.getByRole("combobox"); await userEvent.click(dropdown); await userEvent.click(screen.getByText("less than or equal to")); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert expect(dropdown).toHaveTextContent("less than or equal to"); - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should be answerable incorrectly", async () => { @@ -76,18 +81,28 @@ describe("Dropdown widget", () => { const dropdown = screen.getByRole("combobox"); await userEvent.click(dropdown); await userEvent.click(screen.getByText("greater than or equal to")); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert expect(dropdown).toHaveTextContent("greater than or equal to"); - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("should be invalid on first render", async () => { - // Arrange and Act + // Arrange const {renderer} = renderQuestion(question1); + // Act + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); + // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); it("should be return true when focus() called", async () => { diff --git a/packages/perseus/src/widgets/expression/expression.test.tsx b/packages/perseus/src/widgets/expression/expression.test.tsx index 278e6a873e..04cb9a6591 100644 --- a/packages/perseus/src/widgets/expression/expression.test.tsx +++ b/packages/perseus/src/widgets/expression/expression.test.tsx @@ -9,6 +9,7 @@ import { import * as Dependencies from "../../dependencies"; import {scorePerseusItem} from "../../renderer-util"; import {mockStrings} from "../../strings"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import ExpressionWidgetExport from "./expression"; @@ -50,7 +51,11 @@ const assertCorrect = async ( input, true, ); - expect(renderer).toHaveBeenAnsweredCorrectly(); + const score = scorePerseusItemTesting( + itemData.question, + renderer.getUserInputMap(), + ); + expect(score).toHaveBeenAnsweredCorrectly(); }; const assertIncorrect = async ( @@ -64,7 +69,11 @@ const assertIncorrect = async ( input, false, ); - expect(renderer).toHaveBeenAnsweredIncorrectly(); + const score = scorePerseusItemTesting( + itemData.question, + renderer.getUserInputMap(), + ); + expect(score).toHaveBeenAnsweredIncorrectly(); }; // TODO: actually Assert that message is being set on the score object. @@ -80,7 +89,11 @@ const assertInvalid = async ( await userEvent.type(screen.getByRole("textbox"), input); } act(() => jest.runOnlyPendingTimers()); - expect(renderer).toHaveInvalidInput(); + const score = scorePerseusItemTesting( + itemData.question, + renderer.getUserInputMap(), + ); + expect(score).toHaveInvalidInput(); }; describe("Expression Widget", function () { diff --git a/packages/perseus/src/widgets/expression/score-expression.ts b/packages/perseus/src/widgets/expression/score-expression.ts index 029a4e987b..dfe4269d61 100644 --- a/packages/perseus/src/widgets/expression/score-expression.ts +++ b/packages/perseus/src/widgets/expression/score-expression.ts @@ -165,9 +165,6 @@ function scoreExpression( // We matched a graded answer form, so we can now tell the user // whether their input was correct or incorrect, and hand out // points accordingly - // TODO(eater): Seems silly to translate result to this - // invalid/points thing and immediately translate it back in - // ItemRenderer.scoreInput() return { type: "points", earned: matchingAnswerForm.considered === "correct" ? 1 : 0, diff --git a/packages/perseus/src/widgets/graded-group/graded-group.test.ts b/packages/perseus/src/widgets/graded-group/graded-group.test.ts index bc0ab1c861..6788c689f3 100644 --- a/packages/perseus/src/widgets/graded-group/graded-group.test.ts +++ b/packages/perseus/src/widgets/graded-group/graded-group.test.ts @@ -14,9 +14,7 @@ import type {UserEvent} from "@testing-library/user-event"; const checkAnswer = async ( userEvent: ReturnType<(typeof userEventLib)["setup"]>, ) => { - // NOTE(jeremy): The graded-group widget does not participate in - // Renderer grading. So we can't call `renderer.score()` and see that - // the widget is answered correctly. The only route to check the answer + // NOTE(jeremy): The only route to check the answer // is to use the "Check" button that is embedded _inside_ the widget. await userEvent.click(screen.getByRole("button", {name: "Check"})); }; diff --git a/packages/perseus/src/widgets/grapher/grapher.cypress.ts b/packages/perseus/src/widgets/grapher/grapher.cypress.ts index 636b69b4dc..971d5e6bd6 100644 --- a/packages/perseus/src/widgets/grapher/grapher.cypress.ts +++ b/packages/perseus/src/widgets/grapher/grapher.cypress.ts @@ -1,6 +1,7 @@ import renderQuestionWithCypress from "../../../../../testing/render-question-with-cypress"; import {cypressTestDependencies} from "../../../../../testing/test-dependencies"; import * as Perseus from "../../index"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import { absoluteValueQuestion, @@ -55,8 +56,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + absoluteValueQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -90,8 +95,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + absoluteValueQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -132,8 +141,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + exponentialQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -170,8 +183,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + exponentialQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -205,8 +222,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + linearQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -238,8 +259,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + linearQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -290,8 +315,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + logarithmQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -340,8 +369,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + logarithmQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -377,8 +410,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + quadraticQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -412,8 +449,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + quadraticQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -448,8 +489,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + sinusoidQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -482,8 +527,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + sinusoidQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, @@ -524,8 +573,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + multipleAvailableTypesQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 1, total: 1, @@ -564,8 +617,12 @@ describe("Grapher widget", () => { // Assert cy.then(() => { - const state = getRenderer().guessAndScore(); - expect(state[1]).toStrictEqual({ + const userInput = getRenderer().getUserInputMap(); + const score = scorePerseusItemTesting( + multipleAvailableTypesQuestion, + userInput, + ); + expect(score).toStrictEqual({ type: "points", earned: 0, total: 1, diff --git a/packages/perseus/src/widgets/image/image.test.ts b/packages/perseus/src/widgets/image/image.test.ts index e79f8a91ca..8f8b4234ea 100644 --- a/packages/perseus/src/widgets/image/image.test.ts +++ b/packages/perseus/src/widgets/image/image.test.ts @@ -2,6 +2,7 @@ import {describe, beforeEach, it} from "@jest/globals"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {isAccessible} from "../../widgets"; import {renderQuestion} from "../__testutils__/renderQuestion"; @@ -33,9 +34,13 @@ describe.each([true, false])("image widget - isMobile %b", (isMobile) => { // Act const {renderer} = renderQuestion(question, apiOptions); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("should be accessible if background has 'alt' prop", () => { diff --git a/packages/perseus/src/widgets/input-number/input-number.test.ts b/packages/perseus/src/widgets/input-number/input-number.test.ts index 4c99d33508..1d7c2daab9 100644 --- a/packages/perseus/src/widgets/input-number/input-number.test.ts +++ b/packages/perseus/src/widgets/input-number/input-number.test.ts @@ -9,6 +9,7 @@ import _ from "underscore"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; import {mockStrings} from "../../strings"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import InputNumber from "./input-number"; @@ -50,9 +51,13 @@ describe("input-number", function () { const textbox = screen.getByRole("textbox"); await userEvent.click(textbox); await userEvent.type(textbox, "1/2"); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should reject an incorrect answer", async () => { @@ -63,9 +68,13 @@ describe("input-number", function () { const textbox = screen.getByRole("textbox"); await userEvent.click(textbox); await userEvent.type(textbox, "0.7"); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("should refuse to score an incoherent answer", async () => { @@ -76,9 +85,13 @@ describe("input-number", function () { const textbox = screen.getByRole("textbox"); await userEvent.click(textbox); await userEvent.type(textbox, "0..7"); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); }); @@ -206,9 +219,13 @@ describe("input-number", function () { const textbox = screen.getByRole("textbox"); await userEvent.click(textbox); await userEvent.type(textbox, correct); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should reject an incorrect answer", async () => { @@ -219,9 +236,13 @@ describe("input-number", function () { const textbox = screen.getByRole("textbox"); await userEvent.click(textbox); await userEvent.type(textbox, incorrect); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/input-number/score-input-number.ts b/packages/perseus/src/widgets/input-number/score-input-number.ts index ca1a9dfcb6..30ae3a6956 100644 --- a/packages/perseus/src/widgets/input-number/score-input-number.ts +++ b/packages/perseus/src/widgets/input-number/score-input-number.ts @@ -75,8 +75,6 @@ function scoreInputNumber( const result = val(currentValue); - // TODO(eater): Seems silly to translate result to this invalid/points - // thing and immediately translate it back in ItemRenderer.scoreInput() if (result.empty) { return { type: "invalid", diff --git a/packages/perseus/src/widgets/interaction/interaction.test.ts b/packages/perseus/src/widgets/interaction/interaction.test.ts index f693ad33de..00e72ddb80 100644 --- a/packages/perseus/src/widgets/interaction/interaction.test.ts +++ b/packages/perseus/src/widgets/interaction/interaction.test.ts @@ -1,6 +1,7 @@ import {testDependencies} from "../../../../../testing/test-dependencies"; import {waitForInitialGraphieRender} from "../../../../../testing/wait"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question1} from "./interaction.testdata"; @@ -22,13 +23,19 @@ describe("interaction widget", () => { }); it("should be unanswerable", async () => { - // Arrange/Act + // Arrange const {renderer} = renderQuestion(question1); await waitForInitialGraphieRender(); + // Act + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); + // Assert // Note that this widget can never be answered correctly, no matter // what state its in. - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx index cc24d4c2d2..8972dd6963 100644 --- a/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx @@ -13,6 +13,7 @@ import {getDefaultFigureForType} from "../../../../perseus-editor/src/widgets/in import * as Dependencies from "../../dependencies"; import {ApiOptions} from "../../perseus-api"; import {lockedFigureColors} from "../../perseus-types"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {sinusoidQuestion} from "../grapher/grapher.testdata"; @@ -107,9 +108,13 @@ describe("interactive-graph widget", function () { ), ); await waitForInitialGraphieRender(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("Should render predictably", async () => { @@ -140,9 +145,13 @@ describe("interactive-graph widget", function () { // Act await waitForInitialGraphieRender(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); it("should reject an incorrect answer", async () => { @@ -158,9 +167,13 @@ describe("interactive-graph widget", function () { ), ); await waitForInitialGraphieRender(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }, ); @@ -180,8 +193,12 @@ describe("interactive-graph widget", function () { .withNoInteractiveFigure() .build(); const {renderer} = renderQuestion(question, blankOptions); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); - expect(renderer).toHaveBeenAnsweredCorrectly({ + expect(score).toHaveBeenAnsweredCorrectly({ shouldHavePoints: false, }); }); @@ -247,10 +264,13 @@ describe("a mafs graph", () => { const {renderer} = renderQuestion(question, apiOptions); // Act - // no action + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); }, ); @@ -277,7 +297,11 @@ describe("a mafs graph", () => { // Assert await waitFor( () => { - expect(renderer).toHaveBeenAnsweredIncorrectly(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); + expect(score).toHaveBeenAnsweredIncorrectly(); }, {timeout: 5000}, ); @@ -297,7 +321,11 @@ describe("a mafs graph", () => { // Assert await waitFor( () => { - expect(renderer).toHaveBeenAnsweredCorrectly(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); + expect(score).toHaveBeenAnsweredCorrectly(); }, {timeout: 5000}, ); @@ -317,7 +345,11 @@ describe("a mafs graph", () => { // Assert await waitFor( () => { - expect(renderer).toHaveInvalidInput(); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); + expect(score).toHaveInvalidInput(); }, {timeout: 5000}, ); diff --git a/packages/perseus/src/widgets/matcher/matcher.test.tsx b/packages/perseus/src/widgets/matcher/matcher.test.tsx index c583ad1490..7ed751f537 100644 --- a/packages/perseus/src/widgets/matcher/matcher.test.tsx +++ b/packages/perseus/src/widgets/matcher/matcher.test.tsx @@ -4,6 +4,7 @@ import * as React from "react"; import {testDependencies} from "../../../../../testing/test-dependencies"; import {wait} from "../../../../../testing/wait"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question1} from "./matcher.testdata"; @@ -119,9 +120,13 @@ describe("matcher widget", () => { ].forEach((option, index) => { act(() => matcher.moveRightOptionToIndex(option, 4)); }); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can be answered incorrectly", async () => { @@ -145,9 +150,13 @@ describe("matcher widget", () => { ].forEach((option, index) => { matcher.moveLeftOptionToIndex(option, 0); }); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("is scored incorrect if the math renderer hasn't loaded yet", () => { @@ -165,8 +174,12 @@ describe("matcher widget", () => { isMobile: false, }; const {renderer} = renderQuestion(question1, apiOptions); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/matrix/matrix.test.ts b/packages/perseus/src/widgets/matrix/matrix.test.ts index 27eee1a180..89f1ee0a90 100644 --- a/packages/perseus/src/widgets/matrix/matrix.test.ts +++ b/packages/perseus/src/widgets/matrix/matrix.test.ts @@ -3,6 +3,7 @@ import {userEvent as userEventLib} from "@testing-library/user-event"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question1} from "./matrix.testdata"; @@ -61,9 +62,13 @@ describe("matrix widget", () => { for (let i = 0; i < textboxes.length; i++) { await userEvent.type(textboxes[i], correctAnswers[i].toString()); } + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can be answered incorrectly", async () => { @@ -78,8 +83,12 @@ describe("matrix widget", () => { for (let i = 0; i < textboxes.length; i++) { await userEvent.type(textboxes[i], "1"); } + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/number-line/number-line.test.ts b/packages/perseus/src/widgets/number-line/number-line.test.ts index 327b8aff1d..629879ce0a 100644 --- a/packages/perseus/src/widgets/number-line/number-line.test.ts +++ b/packages/perseus/src/widgets/number-line/number-line.test.ts @@ -2,6 +2,7 @@ import {act} from "@testing-library/react"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question1} from "./number-line.testdata"; @@ -192,9 +193,13 @@ describe("number-line widget", () => { // Act const [numberLine] = renderer.findWidgets("number-line 1"); act(() => numberLine.movePosition(-2.5)); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can be answered incorrectly", () => { @@ -207,8 +212,12 @@ describe("number-line widget", () => { // Act const [numberLine] = renderer.findWidgets("number-line 1"); act(() => numberLine.movePosition(3.5)); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts b/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts index f7ce454974..d177fdb34e 100644 --- a/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts +++ b/packages/perseus/src/widgets/numeric-input/numeric-input.test.ts @@ -3,6 +3,7 @@ import {userEvent as userEventLib} from "@testing-library/user-event"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import NumericInputWidgetExport, {unionAnswerForms} from "./numeric-input"; @@ -42,9 +43,13 @@ describe("numeric-input widget", () => { screen.getByRole("textbox", {hidden: true}), correct, ); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should reject an incorrect answer", async () => { @@ -56,9 +61,13 @@ describe("numeric-input widget", () => { screen.getByRole("textbox", {hidden: true}), incorrect, ); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("Should render predictably", async () => { @@ -233,9 +242,13 @@ describe("Numeric input widget", () => { // Act await userEvent.type(screen.getByRole("textbox", {hidden: true}), "1"); + const score = scorePerseusItemTesting( + multipleAnswers, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can handle multiple correct answers (Part two)", async () => { @@ -244,9 +257,13 @@ describe("Numeric input widget", () => { // Act await userEvent.type(screen.getByRole("textbox", {hidden: true}), "2"); + const score = scorePerseusItemTesting( + multipleAnswers, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can handle duplicated answers", async () => { @@ -258,9 +275,13 @@ describe("Numeric input widget", () => { screen.getByRole("textbox", {hidden: true}), "2.4", ); + const score = scorePerseusItemTesting( + duplicatedAnswers, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can handle coefficients", async () => { @@ -272,9 +293,13 @@ describe("Numeric input widget", () => { screen.getByRole("textbox", {hidden: true}), "1.0", ); + const score = scorePerseusItemTesting( + withCoefficient, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("handles answers that are percentages", async () => { @@ -286,9 +311,13 @@ describe("Numeric input widget", () => { screen.getByRole("textbox", {hidden: true}), "33%", ); + const score = scorePerseusItemTesting( + percentageProblem, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("handles answers that are decimals", async () => { @@ -300,9 +329,13 @@ describe("Numeric input widget", () => { screen.getByRole("textbox", {hidden: true}), "12.2", ); + const score = scorePerseusItemTesting( + multipleAnswersWithDecimals, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("styles differently on mobile", () => { diff --git a/packages/perseus/src/widgets/numeric-input/score-numeric-input.ts b/packages/perseus/src/widgets/numeric-input/score-numeric-input.ts index d1aa76782f..cf23c5ad28 100644 --- a/packages/perseus/src/widgets/numeric-input/score-numeric-input.ts +++ b/packages/perseus/src/widgets/numeric-input/score-numeric-input.ts @@ -154,9 +154,6 @@ function scoreNumericInput( guess: localValue, }; - // TODO(eater): Seems silly to translate result to this - // invalid/points thing and immediately translate it - // back in ItemRenderer.scoreInput() if (result.empty) { return { type: "invalid", diff --git a/packages/perseus/src/widgets/orderer/orderer.test.ts b/packages/perseus/src/widgets/orderer/orderer.test.ts index 46befeb2b2..013a77b3f3 100644 --- a/packages/perseus/src/widgets/orderer/orderer.test.ts +++ b/packages/perseus/src/widgets/orderer/orderer.test.ts @@ -2,6 +2,7 @@ import {act} from "@testing-library/react"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import {question2} from "./orderer.testdata"; @@ -51,9 +52,13 @@ describe("orderer widget", () => { // Act act(() => orderer.setListValues(["1", "2", "3"])); + const score = scorePerseusItemTesting( + question2, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("can be answered incorrectly", () => { @@ -66,9 +71,13 @@ describe("orderer widget", () => { // Act act(() => orderer.setListValues(["3", "2", "1"])); + const score = scorePerseusItemTesting( + question2, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); it("is invalid when no options are selected", () => { @@ -81,8 +90,12 @@ describe("orderer widget", () => { // Act act(() => orderer.setListValues([])); + const score = scorePerseusItemTesting( + question2, + renderer.getUserInputMap(), + ); // assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); }); diff --git a/packages/perseus/src/widgets/passage-ref/passage-ref.test.ts b/packages/perseus/src/widgets/passage-ref/passage-ref.test.ts index 25aaba4f1d..3d9fe0ba66 100644 --- a/packages/perseus/src/widgets/passage-ref/passage-ref.test.ts +++ b/packages/perseus/src/widgets/passage-ref/passage-ref.test.ts @@ -2,6 +2,7 @@ import {act, screen} from "@testing-library/react"; import {testDependencies} from "../../../../../testing/test-dependencies"; import * as Dependencies from "../../dependencies"; +import {scorePerseusItemTesting} from "../../util/test-utils"; import {renderQuestion} from "../__testutils__/renderQuestion"; import PassageExport from "../passage"; @@ -160,8 +161,12 @@ describe("passage-ref widget", () => { // Act const {renderer} = renderQuestion(question1); act(() => jest.runOnlyPendingTimers()); + const score = scorePerseusItemTesting( + question1, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/packages/perseus/src/widgets/radio/__tests__/radio.test.ts b/packages/perseus/src/widgets/radio/__tests__/radio.test.ts index 593f5a94c4..76eba90bdd 100644 --- a/packages/perseus/src/widgets/radio/__tests__/radio.test.ts +++ b/packages/perseus/src/widgets/radio/__tests__/radio.test.ts @@ -6,6 +6,7 @@ import {clone} from "../../../../../../testing/object-utils"; import {testDependencies} from "../../../../../../testing/test-dependencies"; import * as Dependencies from "../../../dependencies"; import {mockStrings} from "../../../strings"; +import {scorePerseusItemTesting} from "../../../util/test-utils"; import {renderQuestion} from "../../__testutils__/renderQuestion"; import PassageWidget from "../../passage"; import RadioWidgetExport from "../radio"; @@ -99,9 +100,13 @@ describe("single-choice question", () => { // Act await selectOption(userEvent, correct); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should accept the right answer (touch)", async () => { @@ -117,9 +122,13 @@ describe("single-choice question", () => { // does not support touch events so we have to do this ourselves. // eslint-disable-next-line testing-library/prefer-user-event fireEvent.click(correctRadio); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it.each(incorrect)( @@ -130,9 +139,13 @@ describe("single-choice question", () => { // Act await selectOption(userEvent, incorrect); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }, ); @@ -281,12 +294,13 @@ describe("single-choice question", () => { // item in the original choices. But because of enforced ordering, // it is now at the top of the list (and thus our correct answer). await userEvent.click(screen.getAllByRole("radio")[0]); + const score = scorePerseusItemTesting(q, renderer.getUserInputMap()); // Assert const items = screen.getAllByRole("listitem"); expect(items[0]).toHaveTextContent(answers[1]); expect(items[1]).toHaveTextContent(answers[0]); - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should not change ordering of non-common answers", async () => { @@ -568,9 +582,13 @@ describe("single-choice question", () => { // Act const {renderer} = renderQuestion(question, apiOptions); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); it("Should render correct option select statuses (rationales) when review mode enabled", async () => { @@ -649,9 +667,10 @@ describe("single-choice question", () => { name: "(Choice D) None of the above", }); await userEvent.click(noneOption); + const score = scorePerseusItemTesting(q, renderer.getUserInputMap()); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); }); @@ -681,9 +700,13 @@ describe("multi-choice question", () => { for (const i of correct) { await userEvent.click(options[i]); } + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(score).toHaveBeenAnsweredCorrectly(); }); it("should select multiple options when clicked", async () => { @@ -796,9 +819,13 @@ describe("multi-choice question", () => { // Act const {renderer} = renderQuestion(question, apiOptions); + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }); it("should be invalid when incorrect number of choices selected", async () => { @@ -842,9 +869,13 @@ describe("multi-choice question", () => { await userEvent.click(option[0]); // correct await userEvent.click(option[1]); // correct await userEvent.click(option[2]); // incorrect + const score = scorePerseusItemTesting( + multipleCorrectChoicesQuestion, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput( + expect(score).toHaveInvalidInput( "Please choose the correct number of answers", ); }); @@ -860,9 +891,13 @@ describe("multi-choice question", () => { for (let i = 0; i < choices.length; i++) { await userEvent.click(option[i]); } + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(score).toHaveBeenAnsweredIncorrectly(); }, ); @@ -877,9 +912,13 @@ describe("multi-choice question", () => { for (const i of choices) { await userEvent.click(option[i]); } + const score = scorePerseusItemTesting( + question, + renderer.getUserInputMap(), + ); // Assert - expect(renderer).toHaveInvalidInput(); + expect(score).toHaveInvalidInput(); }, ); }); @@ -912,11 +951,15 @@ describe("scoring", () => { const userInput = renderer.getUserInput()[0] as PerseusRadioUserInput; const rubric = shuffledQuestion.widgets["radio 1"].options; - const score = scoreRadio(userInput, rubric, mockStrings); + const widgetScore = scoreRadio(userInput, rubric, mockStrings); + const rendererScore = scorePerseusItemTesting( + shuffledQuestion, + renderer.getUserInputMap(), + ); // Assert - expect(score).toHaveBeenAnsweredCorrectly(); - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(widgetScore).toHaveBeenAnsweredCorrectly(); + expect(rendererScore).toHaveBeenAnsweredCorrectly(); }); /** @@ -935,11 +978,15 @@ describe("scoring", () => { const userInput = renderer.getUserInput()[0] as PerseusRadioUserInput; const rubric = shuffledQuestion.widgets["radio 1"].options; - const score = scoreRadio(userInput, rubric, mockStrings); + const widgetScore = scoreRadio(userInput, rubric, mockStrings); + const rendererScore = scorePerseusItemTesting( + shuffledQuestion, + renderer.getUserInputMap(), + ); // Assert - expect(score).toHaveBeenAnsweredIncorrectly(); - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(widgetScore).toHaveBeenAnsweredIncorrectly(); + expect(rendererScore).toHaveBeenAnsweredIncorrectly(); }); /** @@ -958,11 +1005,15 @@ describe("scoring", () => { const userInput = renderer.getUserInput()[0] as PerseusRadioUserInput; const rubric = shuffledNoneQuestion.widgets["radio 1"].options; - const score = scoreRadio(userInput, rubric, mockStrings); + const widgetScore = scoreRadio(userInput, rubric, mockStrings); + const rendererScore = scorePerseusItemTesting( + shuffledNoneQuestion, + renderer.getUserInputMap(), + ); // Assert - expect(score).toHaveBeenAnsweredCorrectly(); - expect(renderer).toHaveBeenAnsweredCorrectly(); + expect(widgetScore).toHaveBeenAnsweredCorrectly(); + expect(rendererScore).toHaveBeenAnsweredCorrectly(); }); /** @@ -981,11 +1032,15 @@ describe("scoring", () => { const userInput = renderer.getUserInput()[0] as PerseusRadioUserInput; const rubric = shuffledNoneQuestion.widgets["radio 1"].options; - const score = scoreRadio(userInput, rubric, mockStrings); + const widgetScore = scoreRadio(userInput, rubric, mockStrings); + const rendererScore = scorePerseusItemTesting( + shuffledQuestion, + renderer.getUserInputMap(), + ); // Assert - expect(score).toHaveBeenAnsweredIncorrectly(); - expect(renderer).toHaveBeenAnsweredIncorrectly(); + expect(widgetScore).toHaveBeenAnsweredIncorrectly(); + expect(rendererScore).toHaveBeenAnsweredIncorrectly(); }); }); diff --git a/testing/server-item-renderer-with-debug-ui.tsx b/testing/server-item-renderer-with-debug-ui.tsx index 029ca1c87b..c53cd86408 100644 --- a/testing/server-item-renderer-with-debug-ui.tsx +++ b/testing/server-item-renderer-with-debug-ui.tsx @@ -4,6 +4,8 @@ import {Strut} from "@khanacademy/wonder-blocks-layout"; import * as React from "react"; import * as Perseus from "../packages/perseus/src/index"; +import {mockStrings} from "../packages/perseus/src/strings"; +import {keScoreFromPerseusScore} from "../packages/perseus/src/util/scoring"; import KEScoreUI from "./ke-score-ui"; import SideBySide from "./side-by-side"; @@ -29,6 +31,31 @@ export const ServerItemRendererWithDebugUI = ({ const [state, setState] = React.useState(null); const options = apiOptions || Object.freeze({}); + const getKeScore = () => { + const renderer = ref.current; + if (!renderer) { + return; + } + + const userInput = renderer.getUserInput(); + const score = Perseus.scorePerseusItem( + item.question, + userInput, + mockStrings, + "en", + ); + + // Continue to include an empty guess for the now defunct answer area. + // TODO(alex): Check whether we rely on the format here for + // analyzing ProblemLogs. If not, remove this layer. + const maxCompatGuess = [renderer.getUserInputLegacy(), []]; + return keScoreFromPerseusScore( + score, + maxCompatGuess, + renderer.getSerializedState().question, + ); + }; + return ( Check From a90fb8ea5372c9b4a3981059d8583f8c70a0d2e0 Mon Sep 17 00:00:00 2001 From: Khan Actions Bot <56267880+khan-actions-bot@users.noreply.github.com> Date: Thu, 12 Dec 2024 08:44:15 -0500 Subject: [PATCH 04/15] Version Packages (#1987) Co-authored-by: github-actions[bot] --- .changeset/bright-tomatoes-sit.md | 6 ------ .changeset/chilly-pigs-clean.md | 5 ----- .changeset/large-flies-divide.md | 5 ----- .changeset/many-squids-relate.md | 14 -------------- .changeset/strange-lies-talk.md | 6 ------ dev/CHANGELOG.md | 13 +++++++++++++ dev/package.json | 16 ++++++++-------- packages/kas/CHANGELOG.md | 9 +++++++++ packages/kas/package.json | 4 ++-- packages/keypad-context/CHANGELOG.md | 9 +++++++++ packages/keypad-context/package.json | 4 ++-- packages/kmath/CHANGELOG.md | 9 +++++++++ packages/kmath/package.json | 4 ++-- packages/math-input/CHANGELOG.md | 10 ++++++++++ packages/math-input/package.json | 6 +++--- packages/perseus-core/CHANGELOG.md | 10 ++++++++++ packages/perseus-core/package.json | 2 +- packages/perseus-editor/CHANGELOG.md | 19 +++++++++++++++++++ packages/perseus-editor/package.json | 18 +++++++++--------- packages/perseus-linter/CHANGELOG.md | 9 +++++++++ packages/perseus-linter/package.json | 6 +++--- packages/perseus/CHANGELOG.md | 24 ++++++++++++++++++++++++ packages/perseus/package.json | 18 +++++++++--------- packages/pure-markdown/CHANGELOG.md | 10 ++++++++++ packages/pure-markdown/package.json | 6 +++--- packages/simple-markdown/CHANGELOG.md | 9 +++++++++ packages/simple-markdown/package.json | 4 ++-- 27 files changed, 175 insertions(+), 80 deletions(-) delete mode 100644 .changeset/bright-tomatoes-sit.md delete mode 100644 .changeset/chilly-pigs-clean.md delete mode 100644 .changeset/large-flies-divide.md delete mode 100644 .changeset/many-squids-relate.md delete mode 100644 .changeset/strange-lies-talk.md diff --git a/.changeset/bright-tomatoes-sit.md b/.changeset/bright-tomatoes-sit.md deleted file mode 100644 index 8776d83d87..0000000000 --- a/.changeset/bright-tomatoes-sit.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@khanacademy/perseus": major -"@khanacademy/perseus-core": major ---- - -Remove `scoreInput` from ServerItemRenderer diff --git a/.changeset/chilly-pigs-clean.md b/.changeset/chilly-pigs-clean.md deleted file mode 100644 index 29fd6a4851..0000000000 --- a/.changeset/chilly-pigs-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@khanacademy/perseus-editor": patch ---- - -[Locked Figure Labels] Update placeholder to include TeX \$s. Start new visible labels with text "label". diff --git a/.changeset/large-flies-divide.md b/.changeset/large-flies-divide.md deleted file mode 100644 index 9d478f80f8..0000000000 --- a/.changeset/large-flies-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@khanacademy/perseus": major ---- - -Remove `guessAndScore` from Renderer diff --git a/.changeset/many-squids-relate.md b/.changeset/many-squids-relate.md deleted file mode 100644 index a2f19b5be9..0000000000 --- a/.changeset/many-squids-relate.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@khanacademy/kas": patch -"@khanacademy/keypad-context": patch -"@khanacademy/kmath": patch -"@khanacademy/math-input": patch -"@khanacademy/perseus": patch -"@khanacademy/perseus-core": patch -"@khanacademy/perseus-editor": patch -"@khanacademy/perseus-linter": patch -"@khanacademy/pure-markdown": patch -"@khanacademy/simple-markdown": patch ---- - -Move to using optional chaining in a few places to resolve new lint rule violations. diff --git a/.changeset/strange-lies-talk.md b/.changeset/strange-lies-talk.md deleted file mode 100644 index 232af4f94f..0000000000 --- a/.changeset/strange-lies-talk.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@khanacademy/perseus": patch -"@khanacademy/perseus-editor": patch ---- - -Fixed crashing behavior that occurs in when selecting "unlimited" in polygon option of interactive graph editor. diff --git a/dev/CHANGELOG.md b/dev/CHANGELOG.md index 5619529864..d80730a1b3 100644 --- a/dev/CHANGELOG.md +++ b/dev/CHANGELOG.md @@ -1,5 +1,18 @@ # @khanacademy/perseus-dev-ui +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + - @khanacademy/kas@0.4.3 + - @khanacademy/kmath@0.1.17 + - @khanacademy/math-input@21.1.7 + - @khanacademy/perseus-linter@1.2.5 + - @khanacademy/pure-markdown@0.3.14 + - @khanacademy/simple-markdown@0.13.7 + ## 4.0.3 ### Patch Changes diff --git a/dev/package.json b/dev/package.json index e11d359a03..b7d94bb9e5 100644 --- a/dev/package.json +++ b/dev/package.json @@ -3,7 +3,7 @@ "description": "Perseus dev UI", "author": "Khan Academy", "license": "MIT", - "version": "4.0.3", + "version": "4.0.4", "private": true, "repository": { "type": "git", @@ -14,13 +14,13 @@ "dev": "vite" }, "dependencies": { - "@khanacademy/kas": "^0.4.2", - "@khanacademy/kmath": "^0.1.16", - "@khanacademy/math-input": "^21.1.6", - "@khanacademy/perseus-core": "1.5.3", - "@khanacademy/perseus-linter": "^1.2.4", - "@khanacademy/pure-markdown": "^0.3.13", - "@khanacademy/simple-markdown": "^0.13.6", + "@khanacademy/kas": "^0.4.3", + "@khanacademy/kmath": "^0.1.17", + "@khanacademy/math-input": "^21.1.7", + "@khanacademy/perseus-core": "2.0.0", + "@khanacademy/perseus-linter": "^1.2.5", + "@khanacademy/pure-markdown": "^0.3.14", + "@khanacademy/simple-markdown": "^0.13.7", "@khanacademy/wonder-blocks-banner": "3.1.7", "@khanacademy/wonder-blocks-icon": "4.1.3", "@khanacademy/wonder-blocks-icon-button": "5.3.4", diff --git a/packages/kas/CHANGELOG.md b/packages/kas/CHANGELOG.md index 2510c98ba5..d686d05f1e 100644 --- a/packages/kas/CHANGELOG.md +++ b/packages/kas/CHANGELOG.md @@ -1,5 +1,14 @@ # @khanacademy/kas +## 0.4.3 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + ## 0.4.2 ### Patch Changes diff --git a/packages/kas/package.json b/packages/kas/package.json index 238809566c..ea34a093d4 100644 --- a/packages/kas/package.json +++ b/packages/kas/package.json @@ -3,7 +3,7 @@ "description": "A lightweight JavaScript CAS for comparing expressions and equations.", "author": "Khan Academy", "license": "MIT", - "version": "0.4.2", + "version": "0.4.3", "publishConfig": { "access": "public" }, @@ -26,7 +26,7 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3" + "@khanacademy/perseus-core": "2.0.0" }, "devDependencies": { "jison": "0.4.15", diff --git a/packages/keypad-context/CHANGELOG.md b/packages/keypad-context/CHANGELOG.md index e14fda793f..91bdc313e3 100644 --- a/packages/keypad-context/CHANGELOG.md +++ b/packages/keypad-context/CHANGELOG.md @@ -1,5 +1,14 @@ # @khanacademy/keypad-context +## 1.0.5 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + ## 1.0.4 ### Patch Changes diff --git a/packages/keypad-context/package.json b/packages/keypad-context/package.json index b912fed47e..435a4143af 100644 --- a/packages/keypad-context/package.json +++ b/packages/keypad-context/package.json @@ -3,7 +3,7 @@ "description": "Perseus keypad context", "author": "Khan Academy", "license": "MIT", - "version": "1.0.4", + "version": "1.0.5", "publishConfig": { "access": "public" }, @@ -25,7 +25,7 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3" + "@khanacademy/perseus-core": "2.0.0" }, "devDependencies": { "react": "^18.2.0" diff --git a/packages/kmath/CHANGELOG.md b/packages/kmath/CHANGELOG.md index 7ca3e8f206..3983b1a984 100644 --- a/packages/kmath/CHANGELOG.md +++ b/packages/kmath/CHANGELOG.md @@ -1,5 +1,14 @@ # @khanacademy/kmath +## 0.1.17 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + ## 0.1.16 ### Patch Changes diff --git a/packages/kmath/package.json b/packages/kmath/package.json index 7771b68c8f..5b9b040910 100644 --- a/packages/kmath/package.json +++ b/packages/kmath/package.json @@ -3,7 +3,7 @@ "description": "Khan Academy's Javascript Numeric Math Utilities", "author": "Khan Academy", "license": "MIT", - "version": "0.1.16", + "version": "0.1.17", "publishConfig": { "access": "public" }, @@ -24,7 +24,7 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3" + "@khanacademy/perseus-core": "2.0.0" }, "devDependencies": { "perseus-build-settings": "^0.4.1", diff --git a/packages/math-input/CHANGELOG.md b/packages/math-input/CHANGELOG.md index 157421927c..4c0c10151c 100644 --- a/packages/math-input/CHANGELOG.md +++ b/packages/math-input/CHANGELOG.md @@ -1,5 +1,15 @@ # @khanacademy/math-input +## 21.1.7 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + - @khanacademy/keypad-context@1.0.5 + ## 21.1.6 ### Patch Changes diff --git a/packages/math-input/package.json b/packages/math-input/package.json index 0db48f1a6c..a54a893167 100644 --- a/packages/math-input/package.json +++ b/packages/math-input/package.json @@ -3,7 +3,7 @@ "description": "Khan Academy's new expression editor for the mobile web.", "author": "Khan Academy", "license": "MIT", - "version": "21.1.6", + "version": "21.1.7", "publishConfig": { "access": "public" }, @@ -38,8 +38,8 @@ ], "scripts": {}, "dependencies": { - "@khanacademy/keypad-context": "^1.0.4", - "@khanacademy/perseus-core": "1.5.3", + "@khanacademy/keypad-context": "^1.0.5", + "@khanacademy/perseus-core": "2.0.0", "mathquill": "https://github.com/Khan/mathquill/releases/download/v1.0.0/mathquill-v1.0.0.tgz" }, "devDependencies": { diff --git a/packages/perseus-core/CHANGELOG.md b/packages/perseus-core/CHANGELOG.md index 256d57f13f..c07316cc35 100644 --- a/packages/perseus-core/CHANGELOG.md +++ b/packages/perseus-core/CHANGELOG.md @@ -1,5 +1,15 @@ # @khanacademy/perseus-core +## 2.0.0 + +### Major Changes + +- [#1973](https://github.com/Khan/perseus/pull/1973) [`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609) Thanks [@handeyeco](https://github.com/handeyeco)! - Remove `scoreInput` from ServerItemRenderer + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + ## 1.5.3 ### Patch Changes diff --git a/packages/perseus-core/package.json b/packages/perseus-core/package.json index d8a96562d8..53fe1b29e9 100644 --- a/packages/perseus-core/package.json +++ b/packages/perseus-core/package.json @@ -3,7 +3,7 @@ "description": "Shared Perseus infrastructure", "author": "Khan Academy", "license": "MIT", - "version": "1.5.3", + "version": "2.0.0", "publishConfig": { "access": "public" }, diff --git a/packages/perseus-editor/CHANGELOG.md b/packages/perseus-editor/CHANGELOG.md index 541affc004..c502602d28 100644 --- a/packages/perseus-editor/CHANGELOG.md +++ b/packages/perseus-editor/CHANGELOG.md @@ -1,5 +1,24 @@ # @khanacademy/perseus-editor +## 16.0.2 + +### Patch Changes + +- [#1985](https://github.com/Khan/perseus/pull/1985) [`701895c01`](https://github.com/Khan/perseus/commit/701895c01bd2792a4dccc6ce0d5edc23f7483db3) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] Update placeholder to include TeX \$s. Start new visible labels with text "label". + +* [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- [#1984](https://github.com/Khan/perseus/pull/1984) [`990a3170c`](https://github.com/Khan/perseus/commit/990a3170c2111ddc2c6e6f8f6420a4908cc71c82) Thanks [@catandthemachines](https://github.com/catandthemachines)! - Fixed crashing behavior that occurs in when selecting "unlimited" in polygon option of interactive graph editor. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82), [`990a3170c`](https://github.com/Khan/perseus/commit/990a3170c2111ddc2c6e6f8f6420a4908cc71c82)]: + - @khanacademy/perseus@48.0.0 + - @khanacademy/perseus-core@2.0.0 + - @khanacademy/kas@0.4.3 + - @khanacademy/keypad-context@1.0.5 + - @khanacademy/kmath@0.1.17 + - @khanacademy/math-input@21.1.7 + - @khanacademy/pure-markdown@0.3.14 + ## 16.0.1 ### Patch Changes diff --git a/packages/perseus-editor/package.json b/packages/perseus-editor/package.json index 59a4b3ab59..6d5939df33 100644 --- a/packages/perseus-editor/package.json +++ b/packages/perseus-editor/package.json @@ -3,7 +3,7 @@ "description": "Perseus editors", "author": "Khan Academy", "license": "MIT", - "version": "16.0.1", + "version": "16.0.2", "publishConfig": { "access": "public" }, @@ -34,17 +34,17 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/kas": "^0.4.2", - "@khanacademy/keypad-context": "^1.0.4", - "@khanacademy/kmath": "^0.1.16", - "@khanacademy/math-input": "^21.1.6", - "@khanacademy/perseus": "^47.0.1", - "@khanacademy/perseus-core": "1.5.3", - "@khanacademy/pure-markdown": "^0.3.13", + "@khanacademy/kas": "^0.4.3", + "@khanacademy/keypad-context": "^1.0.5", + "@khanacademy/kmath": "^0.1.17", + "@khanacademy/math-input": "^21.1.7", + "@khanacademy/perseus": "^48.0.0", + "@khanacademy/perseus-core": "2.0.0", + "@khanacademy/pure-markdown": "^0.3.14", "mafs": "^0.19.0" }, "devDependencies": { - "@khanacademy/perseus-linter": "^1.2.4", + "@khanacademy/perseus-linter": "^1.2.5", "@khanacademy/wonder-blocks-accordion": "1.3.6", "@khanacademy/wonder-blocks-banner": "3.1.7", "@khanacademy/wonder-blocks-button": "6.3.8", diff --git a/packages/perseus-linter/CHANGELOG.md b/packages/perseus-linter/CHANGELOG.md index 1cf4d6c5a2..71b67a4d18 100644 --- a/packages/perseus-linter/CHANGELOG.md +++ b/packages/perseus-linter/CHANGELOG.md @@ -1,5 +1,14 @@ # @khanacademy/perseus-linter +## 1.2.5 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + ## 1.2.4 ### Patch Changes diff --git a/packages/perseus-linter/package.json b/packages/perseus-linter/package.json index 0db263a939..36b3e164c9 100644 --- a/packages/perseus-linter/package.json +++ b/packages/perseus-linter/package.json @@ -3,7 +3,7 @@ "description": "Linter engine for Perseus", "author": "Khan Academy", "license": "MIT", - "version": "1.2.4", + "version": "1.2.5", "publishConfig": { "access": "public" }, @@ -25,10 +25,10 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3" + "@khanacademy/perseus-core": "2.0.0" }, "devDependencies": { - "@khanacademy/pure-markdown": "^0.3.13", + "@khanacademy/pure-markdown": "^0.3.14", "prop-types": "15.6.1" }, "peerDependencies": { diff --git a/packages/perseus/CHANGELOG.md b/packages/perseus/CHANGELOG.md index 03ddb05036..4ced9403cc 100644 --- a/packages/perseus/CHANGELOG.md +++ b/packages/perseus/CHANGELOG.md @@ -1,5 +1,29 @@ # @khanacademy/perseus +## 48.0.0 + +### Major Changes + +- [#1973](https://github.com/Khan/perseus/pull/1973) [`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609) Thanks [@handeyeco](https://github.com/handeyeco)! - Remove `scoreInput` from ServerItemRenderer + +* [#1973](https://github.com/Khan/perseus/pull/1973) [`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609) Thanks [@handeyeco](https://github.com/handeyeco)! - Remove `guessAndScore` from Renderer + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +* [#1984](https://github.com/Khan/perseus/pull/1984) [`990a3170c`](https://github.com/Khan/perseus/commit/990a3170c2111ddc2c6e6f8f6420a4908cc71c82) Thanks [@catandthemachines](https://github.com/catandthemachines)! - Fixed crashing behavior that occurs in when selecting "unlimited" in polygon option of interactive graph editor. + +* Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + - @khanacademy/kas@0.4.3 + - @khanacademy/keypad-context@1.0.5 + - @khanacademy/kmath@0.1.17 + - @khanacademy/math-input@21.1.7 + - @khanacademy/perseus-linter@1.2.5 + - @khanacademy/pure-markdown@0.3.14 + - @khanacademy/simple-markdown@0.13.7 + ## 47.0.1 ### Patch Changes diff --git a/packages/perseus/package.json b/packages/perseus/package.json index 1b55c34495..478b62fac5 100644 --- a/packages/perseus/package.json +++ b/packages/perseus/package.json @@ -3,7 +3,7 @@ "description": "Core Perseus API (includes renderers and widgets)", "author": "Khan Academy", "license": "MIT", - "version": "47.0.1", + "version": "48.0.0", "publishConfig": { "access": "public" }, @@ -40,14 +40,14 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/kas": "^0.4.2", - "@khanacademy/keypad-context": "^1.0.4", - "@khanacademy/kmath": "^0.1.16", - "@khanacademy/math-input": "^21.1.6", - "@khanacademy/perseus-core": "1.5.3", - "@khanacademy/perseus-linter": "^1.2.4", - "@khanacademy/pure-markdown": "^0.3.13", - "@khanacademy/simple-markdown": "^0.13.6", + "@khanacademy/kas": "^0.4.3", + "@khanacademy/keypad-context": "^1.0.5", + "@khanacademy/kmath": "^0.1.17", + "@khanacademy/math-input": "^21.1.7", + "@khanacademy/perseus-core": "2.0.0", + "@khanacademy/perseus-linter": "^1.2.5", + "@khanacademy/pure-markdown": "^0.3.14", + "@khanacademy/simple-markdown": "^0.13.7", "@types/classnames": "2.2.0", "@use-gesture/react": "^10.2.27", "mafs": "0.19.0", diff --git a/packages/pure-markdown/CHANGELOG.md b/packages/pure-markdown/CHANGELOG.md index 7983af68d3..9625e770a1 100644 --- a/packages/pure-markdown/CHANGELOG.md +++ b/packages/pure-markdown/CHANGELOG.md @@ -1,5 +1,15 @@ # @khanacademy/pure-markdown +## 0.3.14 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + - @khanacademy/simple-markdown@0.13.7 + ## 0.3.13 ### Patch Changes diff --git a/packages/pure-markdown/package.json b/packages/pure-markdown/package.json index c33fa41a6c..8511ce73aa 100644 --- a/packages/pure-markdown/package.json +++ b/packages/pure-markdown/package.json @@ -3,7 +3,7 @@ "description": "SimpleMarkdown instance with non-react Perseus rules", "author": "Khan Academy", "license": "MIT", - "version": "0.3.13", + "version": "0.3.14", "publishConfig": { "access": "public" }, @@ -25,8 +25,8 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3", - "@khanacademy/simple-markdown": "^0.13.6" + "@khanacademy/perseus-core": "2.0.0", + "@khanacademy/simple-markdown": "^0.13.7" }, "devDependencies": {}, "peerDependencies": {}, diff --git a/packages/simple-markdown/CHANGELOG.md b/packages/simple-markdown/CHANGELOG.md index b5a2e8106d..24c9958bc4 100644 --- a/packages/simple-markdown/CHANGELOG.md +++ b/packages/simple-markdown/CHANGELOG.md @@ -1,5 +1,14 @@ # @khanacademy/simple-markdown +## 0.13.7 + +### Patch Changes + +- [#1971](https://github.com/Khan/perseus/pull/1971) [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Move to using optional chaining in a few places to resolve new lint rule violations. + +- Updated dependencies [[`f9906728c`](https://github.com/Khan/perseus/commit/f9906728c1a8f09c91c11d824718b8a06d6a7609), [`341d316aa`](https://github.com/Khan/perseus/commit/341d316aa8727ebb9e7fde28fc4e2d8779aa3e82)]: + - @khanacademy/perseus-core@2.0.0 + ## 0.13.6 ### Patch Changes diff --git a/packages/simple-markdown/package.json b/packages/simple-markdown/package.json index 7bd62e6c71..f7405998ef 100644 --- a/packages/simple-markdown/package.json +++ b/packages/simple-markdown/package.json @@ -3,7 +3,7 @@ "description": "Javascript markdown parsing, made simple", "author": "Khan Academy", "license": "MIT", - "version": "0.13.6", + "version": "0.13.7", "publishConfig": { "access": "public" }, @@ -25,7 +25,7 @@ "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, "dependencies": { - "@khanacademy/perseus-core": "1.5.3" + "@khanacademy/perseus-core": "2.0.0" }, "devDependencies": { "perseus-build-settings": "^0.4.1" From cc9d3a4bc8866bbdaa09e2bf3fdb321fb9a125c1 Mon Sep 17 00:00:00 2001 From: Sarah Third Date: Thu, 12 Dec 2024 09:41:06 -0800 Subject: [PATCH 05/15] One weird trick that delights screen readers (#1988) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: This is a simple PR that adds an aria-hidden tag to our graphie container so that we don't read out axis labels or "Made by Raphael" on screen readers. As a result, screen readers should have an easier time navigating the website. While this may hide some labels within graphie, we've taken the position that the alt tags should be the sole source of truth for our screen readers. Issue: LEMS-2712 ## Test plan: - manual testing Author: SonicScrewdriver Reviewers: mark-fitzgerald Required Reviewers: Approved By: mark-fitzgerald Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (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: https://github.com/Khan/perseus/pull/1988 --- .changeset/cool-moons-reply.md | 5 +++++ .../__tests__/__snapshots__/graph.test.tsx.snap | 1 + packages/perseus/src/util/graphie.ts | 3 +++ .../widgets/grapher/__snapshots__/grapher.test.ts.snap | 2 ++ .../interaction/__snapshots__/interaction.test.ts.snap | 1 + .../__snapshots__/interactive-graph.test.tsx.snap | 9 +++++++++ .../number-line/__snapshots__/number-line.test.ts.snap | 10 ++++++++++ 7 files changed, 31 insertions(+) create mode 100644 .changeset/cool-moons-reply.md diff --git a/.changeset/cool-moons-reply.md b/.changeset/cool-moons-reply.md new file mode 100644 index 0000000000..a71cab37b6 --- /dev/null +++ b/.changeset/cool-moons-reply.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": minor +--- + +Hiding graphie labels from screen readers. diff --git a/packages/perseus/src/components/__tests__/__snapshots__/graph.test.tsx.snap b/packages/perseus/src/components/__tests__/__snapshots__/graph.test.tsx.snap index 6e245cd588..a5722937de 100644 --- a/packages/perseus/src/components/__tests__/__snapshots__/graph.test.tsx.snap +++ b/packages/perseus/src/components/__tests__/__snapshots__/graph.test.tsx.snap @@ -7,6 +7,7 @@ exports[`graph should render 1`] = ` style="width: 400px; height: 400px;" >