Skip to content

test(e2e): cover the TOTP modal flow through ddpOverREST#40431

Merged
ggazzo merged 5 commits into
developfrom
test/sdk-v2-totp-modal-regression
May 7, 2026
Merged

test(e2e): cover the TOTP modal flow through ddpOverREST#40431
ggazzo merged 5 commits into
developfrom
test/sdk-v2-totp-modal-regression

Conversation

@ggazzo

@ggazzo ggazzo commented May 6, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on top of #40430 — adds a regression test for the ddpOverREST catch handler that PR fixes.

The test mocks /api/v1/method.call/<name> instead of enabling real TOTP on a user. process.env.TEST_MODE short-circuits 2FA in CI except for requireSecondFactor: true, and the only method using that flag (saveUserProfileWithTwoFactor) is not registered as a Meteor method — only the typed REST endpoint exposes it. Replaying the exact mountResult({ id, error }) envelope the server produces hits the catch we changed without depending on TOTP being enforceable end-to-end.

What it asserts:

  • Meteor.callAsync against a method whose REST response is a 400 with a DDP result frame carrying error.error === 'totp-required' opens the Enter TOTP password modal.
  • After the user submits a code, the retry includes { twoFactorCode, twoFactorMethod: 'totp' } and the call resolves with the result the mock returns.
  • The mocked endpoint is hit exactly twice (challenge + retry).

Verified locally: with the fix the test passes in ~3.5s; reverting the catch handler to the synthetic-error rebuild times out at the modal-visible expect.

Test plan

Task: ARCH-2130

Summary by CodeRabbit

  • Tests
    • Added end-to-end coverage for the TOTP two-factor flow: verifies the app preserves server TOTP-required responses, displays the “Enter TOTP password” dialog, accepts a verification code, retries the call, and hides the dialog on success. Confirms the retry succeeds and that the REST interaction occurs the expected number of times.

ggazzo added 2 commits May 6, 2026 18:06
…on status snapshot

Two regressions reintroduced by reapplying #40301:

- `ddpOverREST` rebuilt every REST-side error with `error: 'unknown'`,
  dropping the original DDP error code. The Rocket.Chat REST middleware
  encodes the original Meteor error inside `body.message` as a DDP `result`
  frame for `method.call` / `method.callAnon`, so forward that frame
  untouched when present. Only fall back to a synthetic frame for
  auth-middleware errors (e.g. 401) where `body.message` is a plain string.
  Without this, `withAsyncTOTP` no longer recognised `totp-required` and
  the 2FA modal never opened for any Meteor method protected by
  `twoFactorRequired`.

- `ServerProvider.getStatus` dropped the `{ ...Meteor.status() }` spread on
  the legacy path. `Meteor.status()` returns the same internal object on
  every call (mutated in place), so `useReactiveValue` /
  `useSyncExternalStore` compared snapshots by identity and stopped
  re-rendering. `ConnectionStatusBar` froze on connect/drop until a hard
  reload. Restore the spread.
@ggazzo ggazzo requested a review from a team as a code owner May 6, 2026 23:18
@dionisio-bot

dionisio-bot Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot

changeset-bot Bot commented May 6, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0555430

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 83519c15-9857-4c0b-bbbb-ef2b91e0d0dc

📥 Commits

Reviewing files that changed from the base of the PR and between 3d67e4a and 0555430.

📒 Files selected for processing (1)
  • apps/meteor/tests/e2e/account-totp.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/meteor/tests/e2e/account-totp.spec.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build

Walkthrough

Adds a Playwright end-to-end test that intercepts REST-carried DDP method calls to simulate a totp-required error, verifies the TOTP modal appears, submits a code, and verifies the retry succeeds and the endpoint was called twice.

Changes

TOTP Modal E2E Test

Layer / File(s) Summary
Test Setup & Imports
apps/meteor/tests/e2e/account-totp.spec.ts
Adds new Playwright e2e spec with admin storageState, fixtures, and a fixed METHOD_NAME.
Request Interception / Mocking
apps/meteor/tests/e2e/account-totp.spec.ts
Intercepts **/api/v1/method.call/<METHOD_NAME> and implements two-step behavior: first respond 400 with a DDP-like totp-required error when no twoFactorMethod: 'totp', then respond 200 echoing twoFactorCode on retry.
Client Invocation & UI Interaction
apps/meteor/tests/e2e/account-totp.spec.ts
Calls window.Meteor.callAsync in page context, asserts the "Enter TOTP password" modal appears, fills the code, clicks Verify, and asserts the modal is dismissed.
Assertions / Verification
apps/meteor/tests/e2e/account-totp.spec.ts
Asserts the captured retry result contains the submitted twoFactorCode and that the intercepted endpoint was called exactly twice.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding an e2e test for the TOTP modal flow via ddpOverREST, which aligns with the file addition and test implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • ARCH-2130: Request failed with status code 401

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ggazzo ggazzo added this to the 8.5.0 milestone May 6, 2026
@ggazzo

ggazzo commented May 6, 2026

Copy link
Copy Markdown
Member Author

/jira ARCH-2021

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/meteor/tests/e2e/account-totp.spec.ts (2)

4-9: ⚡ Quick win

Remove inline implementation comments from the test body

This file has several inline explanatory comments; for this repo’s TS/JS guideline, these should be removed and expressed via test/step naming instead.

As per coding guidelines: “**/*.{ts,tsx,js}: Avoid code comments in the implementation”.

Also applies to: 29-34, 57-57, 72-75

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/tests/e2e/account-totp.spec.ts` around lines 4 - 9, Remove the
inline explanatory comments inside the test body and instead surface that
context in test/step names; specifically, delete the inline comment block
explaining why the REST `method.call` is mocked and incorporate that rationale
into the surrounding test/it/describe title (or individual step names) so
readers know we mock the REST `method.call` to exercise the `ddpOverREST`
`.catch` path rather than wiring up TOTP; apply the same change for the other
inline comments referenced (around the mocks and assertions) so no
implementation comments remain in the body and the test names fully describe the
intent.

15-93: ⚡ Quick win

Split this scenario into test.step() blocks

This test covers multiple phases (challenge, modal interaction, retry verification). Adding test.step() would improve structure and failure diagnostics.

Suggested structure
 test.describe('account-totp ddpOverREST preserves the totp-required error', () => {
 	test('opens the TOTP modal when the REST envelope carries a `totp-required` DDP frame, and resolves on retry', async ({ page }) => {
-		await page.goto('/home');
-		await expect(page.getByRole('main')).toBeVisible();
+		await test.step('open home and register method.call route mock', async () => {
+			await page.goto('/home');
+			await expect(page.getByRole('main')).toBeVisible();
+			// route setup...
+		});
 
-		await page.evaluate((method) => {
-			(window as any).__totpCallResult = (window as any).Meteor.callAsync(method)
-				.then((value: unknown) => ({ ok: true, value }))
-				.catch((err: unknown) => ({ ok: false, error: String((err as Error)?.message ?? err) }));
-		}, METHOD_NAME);
+		await test.step('trigger call and verify TOTP modal appears', async () => {
+			await page.evaluate((method) => {
+				(window as any).__totpCallResult = (window as any).Meteor.callAsync(method)
+					.then((value: unknown) => ({ ok: true, value }))
+					.catch((err: unknown) => ({ ok: false, error: String((err as Error)?.message ?? err) }));
+			}, METHOD_NAME);
+			const totpModal = page.getByRole('dialog', { name: 'Enter TOTP password' });
+			await expect(totpModal).toBeVisible({ timeout: 10_000 });
+		});
 
-		await totpModal.getByPlaceholder('Enter code here').fill('123456');
-		await totpModal.getByRole('button', { name: 'Verify' }).click();
+		await test.step('submit TOTP and assert retry success', async () => {
+			const totpModal = page.getByRole('dialog', { name: 'Enter TOTP password' });
+			await totpModal.getByPlaceholder('Enter code here').fill('123456');
+			await totpModal.getByRole('button', { name: 'Verify' }).click();
+			await expect(totpModal).toBeHidden();
+			const result = await page.evaluate(() => (window as any).__totpCallResult);
+			expect(result).toEqual({ ok: true, value: { ok: true, code: '123456' } });
+			expect(calls).toBe(2);
+		});
 	});
 });

As per coding guidelines: “apps/meteor/tests/e2e/**/*.spec.ts: Use test.step() for complex test scenarios to improve organization in Playwright tests”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/tests/e2e/account-totp.spec.ts` around lines 15 - 93, The test is
too monolithic—split it into logical Playwright test.step() blocks to improve
structure and diagnostics: create steps such as "mock REST route / set up
responses" (wrap the page.route handler that inspects METHOD_NAME and increments
calls), "trigger Meteor.callAsync" (the page.evaluate that sets
window.__totpCallResult), "wait for and interact with TOTP modal" (the
assertions on totpModal, fill and click Verify), and "assert result and call
count" (the final page.evaluate result and expect(calls)). Keep existing
handlers and identifiers (METHOD_NAME, window.__totpCallResult, totpModal,
calls) unchanged—just wrap the existing code ranges into separate await
test.step('name', async () => { ... }) calls to isolate phases and improve
failure messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/meteor/tests/e2e/account-totp.spec.ts`:
- Line 17: Replace the non-semantic Playwright locator call
page.locator('#main-content') with the semantic role-based locator
page.getByRole('main'); update the assertion that uses page.locator to use
page.getByRole('main') (the element is a <main>) so the test reads the semantic
locator and still calls expect(...).toBeVisible(); ensure any nearby references
to '#main-content' in this spec are similarly replaced.

---

Nitpick comments:
In `@apps/meteor/tests/e2e/account-totp.spec.ts`:
- Around line 4-9: Remove the inline explanatory comments inside the test body
and instead surface that context in test/step names; specifically, delete the
inline comment block explaining why the REST `method.call` is mocked and
incorporate that rationale into the surrounding test/it/describe title (or
individual step names) so readers know we mock the REST `method.call` to
exercise the `ddpOverREST` `.catch` path rather than wiring up TOTP; apply the
same change for the other inline comments referenced (around the mocks and
assertions) so no implementation comments remain in the body and the test names
fully describe the intent.
- Around line 15-93: The test is too monolithic—split it into logical Playwright
test.step() blocks to improve structure and diagnostics: create steps such as
"mock REST route / set up responses" (wrap the page.route handler that inspects
METHOD_NAME and increments calls), "trigger Meteor.callAsync" (the page.evaluate
that sets window.__totpCallResult), "wait for and interact with TOTP modal" (the
assertions on totpModal, fill and click Verify), and "assert result and call
count" (the final page.evaluate result and expect(calls)). Keep existing
handlers and identifiers (METHOD_NAME, window.__totpCallResult, totpModal,
calls) unchanged—just wrap the existing code ranges into separate await
test.step('name', async () => { ... }) calls to isolate phases and improve
failure messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7ac081c6-ec72-4d69-bd40-ce2bca9887c6

📥 Commits

Reviewing files that changed from the base of the PR and between 57e1e2d and 76acf7c.

📒 Files selected for processing (1)
  • apps/meteor/tests/e2e/account-totp.spec.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
apps/meteor/tests/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.spec.ts: All test files must be created in apps/meteor/tests/e2e/ directory
Avoid using page.locator() in Playwright tests - always prefer semantic locators such as page.getByRole(), page.getByLabel(), page.getByText(), or page.getByTitle()
Use test.beforeAll() and test.afterAll() for setup/teardown in Playwright tests
Use test.step() for complex test scenarios to improve organization in Playwright tests
Group related tests in the same file
Utilize Playwright fixtures (test, page, expect) for consistency in test files
Prefer web-first assertions (toBeVisible, toHaveText, etc.) in Playwright tests
Use expect matchers for assertions (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements in Playwright tests
Use page.waitFor() with specific conditions instead of hardcoded timeouts in Playwright tests
Implement proper wait strategies for dynamic content in Playwright tests
Maintain test isolation between test cases in Playwright tests
Ensure clean state for each test execution in Playwright tests
Ensure tests run reliably in parallel without shared state conflicts

Files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
apps/meteor/tests/e2e/**/*.{ts,spec.ts}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,spec.ts}: Store commonly used locators in variables/constants for reuse
Follow Page Object Model pattern consistently in Playwright tests

Files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
🧠 Learnings (6)
📚 Learning: 2026-02-24T19:22:48.358Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts:66-67
Timestamp: 2026-02-24T19:22:48.358Z
Learning: In Playwright end-to-end tests (e.g., under apps/meteor/tests/e2e/...), prefer locating elements by translated text (getByText) and ARIA roles (getByRole) over data-qa attributes. If translation values change, update the corresponding test locators accordingly. Never use data-qa locators. This guideline applies to all Playwright e2e test specs in the repository and helps keep tests robust to UI text changes and accessible semantics.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
📚 Learning: 2026-02-24T19:39:42.247Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/message.ts:7-7
Timestamp: 2026-02-24T19:39:42.247Z
Learning: In RocketChat e2e tests, avoid using data-qa attributes to locate elements. Prefer semantic locators such as getByRole, getByLabel, getByText, getByTitle and ARIA-based selectors. Apply this rule to all TypeScript files under apps/meteor/tests/e2e to improve test reliability, accessibility, and maintainability.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
📚 Learning: 2026-03-06T18:10:15.268Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39397
File: packages/gazzodown/src/code/CodeBlock.spec.tsx:47-68
Timestamp: 2026-03-06T18:10:15.268Z
Learning: In tests (especially those using testing-library/dom/jsdom) for Rocket.Chat components, the HTML <code> element has an implicit ARIA role of 'code'. Therefore, screen.getByRole('code') or screen.findByRole('code') will locate <code> elements even without a role attribute. Do not flag findByRole('code') as invalid in reviews; prefer using the implicit role instead of adding role="code" unless necessary for accessibility.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/tests/e2e/account-totp.spec.ts

Comment thread apps/meteor/tests/e2e/account-totp.spec.ts Outdated
Base automatically changed from fix/sdk-v2-totp-and-status-regressions to develop May 6, 2026 23:24
@ggazzo ggazzo requested a review from a team as a code owner May 6, 2026 23:24
@codecov

codecov Bot commented May 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.60%. Comparing base (dbce434) to head (0555430).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #40431      +/-   ##
===========================================
+ Coverage    69.57%   69.60%   +0.02%     
===========================================
  Files         3317     3317              
  Lines       121867   121867              
  Branches     21801    21826      +25     
===========================================
+ Hits         84794    84826      +32     
+ Misses       33740    33717      -23     
+ Partials      3333     3324       -9     
Flag Coverage Δ
e2e 58.97% <ø> (+0.09%) ⬆️
e2e-api 46.29% <ø> (ø)
unit 70.43% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Locks down the regression fixed in the prior commit: when REST returns the
`mountResult({ id, error })` envelope from `apps/meteor/app/api/server/v1/misc.ts`
with `error.error === 'totp-required'`, the client must forward the original
DDP frame to `_streamHandlers.onMessage` so `withAsyncTOTP` →
`process2faAsyncReturn` opens the 2FA modal.

The test mocks `/api/v1/method.call/<name>` rather than enabling real TOTP on
a user — `process.env.TEST_MODE` short-circuits 2FA except for
`requireSecondFactor: true`, and the only method using that flag is
`saveUserProfileWithTwoFactor`, which isn't registered as a Meteor method
(only the typed REST endpoint surfaces it). Mocking the exact server
envelope exercises the `ddpOverREST` catch handler we changed.
@ggazzo ggazzo force-pushed the test/sdk-v2-totp-modal-regression branch from 76acf7c to 3d67e4a Compare May 7, 2026 00:47
ggazzo and others added 2 commits May 7, 2026 10:49
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label May 7, 2026
@dionisio-bot dionisio-bot Bot added the stat: ready to merge PR tested and approved waiting for merge label May 7, 2026
@ggazzo ggazzo merged commit f129bf5 into develop May 7, 2026
81 of 84 checks passed
@ggazzo ggazzo deleted the test/sdk-v2-totp-modal-regression branch May 7, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge type: chore

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants