Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Type configured userEvent field for easier testing DX #1421

Merged
merged 4 commits into from
Jul 22, 2024

Conversation

jeremywiebe
Copy link
Collaborator

@jeremywiebe jeremywiebe commented Jul 17, 2024

Summary:

When I upgraded Perseus to user-event v14, tests that used fake timers needed to initialize an instance of the user-event library (because we needed to tell it how to advance the fake timers in Jest).

The configured variable was untyped and meant that we don't get any intellisense/code completion when using it, so this PR properly types the let userEvent declarations!

Before

image

After

image

Issue: "none"

Test plan:

Open one of the affected test files and type userEvent. in one of the tests. Note that your editor (if it supports this) should list the functions available on the userEvent instance!

@jeremywiebe jeremywiebe self-assigned this Jul 17, 2024
Copy link
Contributor

github-actions bot commented Jul 17, 2024

Size Change: +240 B (+0.03%)

Total Size: 854 kB

Filename Size Change
packages/perseus-editor/dist/es/index.js 273 kB +240 B (+0.09%)
ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 38.2 kB
packages/kmath/dist/es/index.js 4.27 kB
packages/math-input/dist/es/index.js 80.8 kB
packages/math-input/dist/es/strings.js 1.73 kB
packages/perseus-core/dist/es/index.js 1.48 kB
packages/perseus-linter/dist/es/index.js 21.6 kB
packages/perseus/dist/es/index.js 414 kB
packages/perseus/dist/es/strings.js 3.21 kB
packages/pure-markdown/dist/es/index.js 3.67 kB
packages/simple-markdown/dist/es/index.js 12.4 kB

compressed-size-action

Copy link

codecov bot commented Jul 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 70.22%. Comparing base (c3726e3) to head (d122224).
Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1421      +/-   ##
==========================================
+ Coverage   69.37%   70.22%   +0.85%     
==========================================
  Files         504      508       +4     
  Lines      105315   105698     +383     
  Branches     7565    10799    +3234     
==========================================
+ Hits        73062    74229    +1167     
+ Misses      32071    31469     -602     
+ Partials      182        0     -182     

Impacted file tree graph

see 150 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c3726e3...d122224. Read the comment docs.

@jeremywiebe jeremywiebe requested a review from a team July 17, 2024 17:38
@jeremywiebe jeremywiebe marked this pull request as ready for review July 17, 2024 17:38
@khan-actions-bot
Copy link
Contributor

khan-actions-bot commented Jul 17, 2024

Gerald

Required Reviewers
  • @Khan/perseus for changes to .changeset/funny-nails-know.md, packages/perseus/src/__tests__/renderer.test.tsx, packages/perseus/src/__tests__/server-item-renderer.test.tsx, packages/perseus/src/widgets/label-image.test.ts, packages/perseus-editor/src/__tests__/editor.test.tsx, packages/perseus-editor/src/__tests__/hint-editor.test.tsx, packages/perseus-editor/src/__tests__/item-extras-editor.test.tsx, packages/math-input/src/components/__tests__/integration.test.tsx, packages/perseus/src/components/__tests__/math-input.test.tsx, packages/perseus/src/components/__tests__/zoomable.test.tsx, packages/perseus/src/multi-items/__tests__/multi-renderer.test.tsx, packages/perseus/src/widgets/__tests__/categorizer.test.ts, packages/perseus/src/widgets/__tests__/definition.test.ts, packages/perseus/src/widgets/__tests__/dropdown.test.ts, packages/perseus/src/widgets/__tests__/explanation.test.ts, packages/perseus/src/widgets/__tests__/expression-mobile.test.tsx, packages/perseus/src/widgets/__tests__/expression.test.tsx, packages/perseus/src/widgets/__tests__/graded-group-set.test.ts, packages/perseus/src/widgets/__tests__/graded-group.test.ts, packages/perseus/src/widgets/__tests__/group.test.tsx, packages/perseus/src/widgets/__tests__/input-number.test.ts, packages/perseus/src/widgets/__tests__/matrix.test.ts, packages/perseus/src/widgets/__tests__/numeric-input.test.ts, packages/perseus/src/widgets/__tests__/radio.test.ts, packages/perseus-editor/src/components/__tests__/blur-input.test.tsx, packages/perseus-editor/src/components/__tests__/graph-settings.test.tsx, packages/perseus-editor/src/components/__tests__/interactive-graph-settings.test.tsx, packages/perseus-editor/src/components/__tests__/start-coord-settings.test.tsx, packages/perseus-editor/src/widgets/__tests__/categorizer-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/definition-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/dropdown-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/explanation-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/expression-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/input-number-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor-locked-figures.test.tsx, packages/perseus-editor/src/widgets/__tests__/interactive-graph-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/matcher-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/number-line-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/numeric-input-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/python-program-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/radio-editor.test.tsx, packages/perseus-editor/src/widgets/__tests__/sorter-editor.test.tsx, packages/math-input/src/components/keypad/__tests__/keypad-button.test.tsx, packages/math-input/src/components/keypad/__tests__/keypad-v2-mathquill.test.tsx, packages/math-input/src/components/keypad/__tests__/keypad.test.tsx, packages/math-input/src/components/tabbar/__tests__/item.test.tsx, packages/math-input/src/components/tabbar/__tests__/tabbar.test.tsx, packages/perseus/src/widgets/__tests__/radio/base-radio.test.tsx, packages/perseus/src/widgets/__tests__/radio/choice.test.tsx, packages/perseus/src/widgets/interactive-graphs/graphs/use-draggable.test.tsx, packages/perseus/src/widgets/label-image/__tests__/hide-answers-toggle.test.tsx

Don't want to be involved in this pull request? Comment #removeme and we won't notify you of further changes.

Copy link
Contributor

@handeyeco handeyeco left a comment

Choose a reason for hiding this comment

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

Nice

@@ -80,8 +80,9 @@ describe("Editor", () => {
render(<Harnessed onChange={onChangeMock} />);

// Act
screen.getByRole("button", {name: "Remove image widget"}),
await userEvent.click();
await userEvent.click(
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@@ -80,7 +80,7 @@ function ConnectedMathInput({keypadConfiguration = defaultConfiguration}) {
}

describe("math input integration", () => {
let userEvent;
let userEvent: ReturnType<typeof userEventLib.setup>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if it'd be useful to alias this so it's clearer.

type UserEvent = ReturnType<typeof userEventLib.setup>;

Then

let userEvent: UserEvent;

Not a blocker, I'll defer to you.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nice. The library even provides an exported type for this: UserEvent!

Copy link
Contributor

@Myranae Myranae left a comment

Choose a reason for hiding this comment

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

Was able to go into an affected test and see options after typing userEvent. into it! Yay code completion~ Added a couple questions just for learning purposes, but this looks pretty straightforward to me :) I'm curious though, why didn't it get a type after it was redeclared?

@@ -80,7 +80,7 @@ function ConnectedMathInput({keypadConfiguration = defaultConfiguration}) {
}

describe("math input integration", () => {
let userEvent;
let userEvent: ReturnType<typeof userEventLib.setup>;
Copy link
Contributor

Choose a reason for hiding this comment

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

question, nb: So this means whatever the return type is for the userEventLib.setup function is the type of this userEvent variable, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's exactly correct.

Comment on lines +83 to +85
await userEvent.click(
screen.getByRole("button", {name: "Remove image widget"}),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

question, nb: Did the syntax that was previously here not work? Or is this change mostly for readability?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was incorrect. It looks like deep in the library there's some defaulting to use the previous target as the target when click() is called, but the API types definitely don't allow for a missing element. I think it was sheer luck that this worked.

@jeremywiebe
Copy link
Collaborator Author

I'm curious though, why didn't it get a type after it was redeclared?

I just didn't think to! :(

@Myranae
Copy link
Contributor

Myranae commented Jul 22, 2024

@jeremywiebe Oh, no, I meant, why didn't it automatically happen after this line: userEvent = userEventLib.setup({ advanceTimers: jest.advanceTimersByTime, });? Shouldn't this show that now userEvent should be the type returned by userEventLib.setup? I thought with TypeScript it would then infer the type of userEvent moving forward, but we needed to declare the type manually.

@jeremywiebe
Copy link
Collaborator Author

@jeremywiebe Oh, no, I meant, why didn't it automatically happen after this line: userEvent = userEventLib.setup({ advanceTimers: jest.advanceTimersByTime, });? Shouldn't this show that now userEvent should be the type returned by userEventLib.setup? I thought with TypeScript it would then infer the type of userEvent moving forward, but we needed to declare the type manually.

Ah, that! When we declare let userEvent; TypeScript has no way of knowing what type it will be so it's typed as any. TypeScript doesn't know Jest and so it doesn't understand when beforeEach() will be called or if will be called at all. In a normal function TS would be able to do flow analysis and narrow a type based on if and switch case checks.

Copy link
Contributor

npm Snapshot: Published

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

Example:

yarn add @khanacademy/perseus@PR1421

If you are working in Khan Academy's webapp, you can run:

./dev/tools/bump_perseus_version.sh -t PR1421

@jeremywiebe jeremywiebe merged commit 9a3bce3 into main Jul 22, 2024
11 checks passed
@jeremywiebe jeremywiebe deleted the jer/user-event-type branch July 22, 2024 20:44
jeremywiebe pushed a commit that referenced this pull request Jul 22, 2024
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.


# Releases
## @khanacademy/math-input@20.0.0

### Major Changes

-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18

### Patch Changes

-   [#1421](#1421) [`9a3bce37f`](9a3bce3) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Enhance types in tests using @testing-library/user-event


-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Fix: prevent `react` and `react-dom` from being bundled

## @khanacademy/perseus@26.0.0

### Major Changes

-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18

### Minor Changes

-   [#1426](#1426) [`4b6fc712e`](4b6fc71) Thanks [@benchristel](https://github.com/benchristel)! - Tweak the animation of the protractor rotation handle. It's now slightly slower and the magnification is less extreme.

### Patch Changes

-   [#1421](#1421) [`9a3bce37f`](9a3bce3) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Enhance types in tests using @testing-library/user-event


-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Fix: prevent `react` and `react-dom` from being bundled

-   Updated dependencies \[[`9a3bce37f`](9a3bce3), [`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe)]:
    -   @khanacademy/math-input@20.0.0
    -   @khanacademy/simple-markdown@0.13.0
    -   @khanacademy/pure-markdown@0.3.7

## @khanacademy/perseus-editor@9.0.0

### Major Changes

-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18

### Patch Changes

-   [#1421](#1421) [`9a3bce37f`](9a3bce3) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Enhance types in tests using @testing-library/user-event

-   Updated dependencies \[[`4b6fc712e`](4b6fc71), [`9a3bce37f`](9a3bce3), [`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe)]:
    -   @khanacademy/perseus@26.0.0
    -   @khanacademy/math-input@20.0.0

## @khanacademy/simple-markdown@0.13.0

### Minor Changes

-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18


-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18

## @khanacademy/pure-markdown@0.3.7

### Patch Changes

-   Updated dependencies \[[`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe)]:
    -   @khanacademy/simple-markdown@0.13.0

## @khanacademy/perseus-dev-ui@2.0.0

### Major Changes

-   [#1064](#1064) [`c6a5cbe13`](c6a5cbe) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - React 18

### Patch Changes

-   Updated dependencies \[[`9a3bce37f`](9a3bce3), [`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe), [`c6a5cbe13`](c6a5cbe)]:
    -   @khanacademy/math-input@20.0.0
    -   @khanacademy/simple-markdown@0.13.0
    -   @khanacademy/pure-markdown@0.3.7

Author: khan-actions-bot

Reviewers: jeremywiebe

Required Reviewers:

Approved By: jeremywiebe

Checks: ✅ Upload Coverage (ubuntu-latest, 20.x), ⏭️  Publish npm snapshot, ✅ Cypress (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1433
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants