Skip to content

test(frontend): use orval to generate MSW mocks DEV-2232#7219

Open
magicznyleszek wants to merge 89 commits into
mainfrom
leszek/dev-2232-orval-msw-gen
Open

test(frontend): use orval to generate MSW mocks DEV-2232#7219
magicznyleszek wants to merge 89 commits into
mainfrom
leszek/dev-2232-orval-msw-gen

Conversation

@magicznyleszek

@magicznyleszek magicznyleszek commented Jul 7, 2026

Copy link
Copy Markdown
Member

🗒️ Checklist

  1. run linter locally
  2. update developer docs (API, README, inline, etc.), if any
  3. for user-facing doc changes create a Zulip thread at #Support Docs Updates, if any
  4. draft PR with a title <type>(<scope>)<!>: <title> DEV-1234
  5. assign yourself, tag PR: at least Front end and/or Back end or workflow
  6. fill in the template below and delete template comments
  7. review thyself: read the diff and repro the preview as written
  8. open PR & confirm that CI passes & request reviewers, if needed
  9. act on any greptile review below a 5/5 score or leave comment explaining why you won't
  10. delete this checklist section from the final squash commit before merging

📣 Summary

Migrates from manually maintained API mocks to Orval-generated ones for type-safe mocking in Storybook stories and tests. Ensures OpenAPI schema is the single source of truth for both API types and mock data.

💭 Notes

Changes in this branch are quite extensive. Unfortunatelly enabling mock generation through Orval spilled into type inconsistencies that needed to be addressed.

Orval MSW Integration

  • Configured Orval to generate TypeScript types and MSW v2 mock handlers from OpenAPI schema
  • Generated TypeScript model files in jsapp/js/api/models/
  • Generated complete MSW handlers with mock factories in jsapp/js/api/react-query/
  • Updated all existing .mocks.ts files to use Orval-generated factories instead of manual mocks

Mock Generation Strategy

  • mode: 'tags-split' - Generates mocks in separate files to prevent bundling faker/msw (~600KB) in production
  • Structure: react-query/module-name/index.ts (runtime) + react-query/module-name/msw.ts (mocks)
  • Enables proper tree-shaking - production code never imports test dependencies
  • Mock imports: from '#/api/react-query/module-name/msw'
  • Runtime imports unchanged: from '#/api/react-query/module-name'

Post-Processing Scripts (6 scripts run after Orval generation)

  1. orval-rename-to-index.js - Renames module/module.tsmodule/index.ts, module/module.msw.tsmodule/msw.ts for clean imports
  2. orval-fix-referenced-additional-properties.js - Fixes Orval bug with $ref in additionalProperties (issue #1077)
  3. orval-fix-mock-factory-type-assertions.js - Adds as TypeName for types with conflicting index signatures (updated for new file structure)
  4. orval-make-trailing-slash-optional.js - Makes trailing slashes optional in MSW URL patterns (Django REST Framework compatibility)
  5. orval-remove-mock-delays.js - Removes await delay(1000) that slows down tests
  6. Biome formatting - Final step ensures consistent formatting after all modifications

Enhanced OpenAPI Schema

  • Fixed Nullable Format: Changed from {type: 'string', nullable: true} to {type: ['string', 'null']} for Orval compatibility
  • Added Constants: NULLABLE_STRING_SCHEMA, NULLABLE_ARRAY_SCHEMA to replace inline dict spreads
  • Fixed Naming Conflict: Split ASSET_CONTENT_SCHEMA into ASSET_CONTENT_REQUEST_SCHEMA (string for PATCH) and ASSET_CONTENT_RESPONSE_SCHEMA (object for GET)
  • Detailed nested types for Asset model (analysis_form_json, advanced_features, permissions, files)
  • Proper oneOf unions for supplemental data (handling 6 action types)
  • Complete field definitions for bulk actions and submission data
  • Named schema components for proper TypeScript generation (avoiding index signature conflicts)

Jest Configuration

  • Added MSW ES modules transformation to unit.config.ts
  • Added BroadcastChannel polyfill for MSW in test environment
  • Updated setupUnitTest.ts to initialize MSW server

Storybook Migration

  • All stories now use Orval-generated mocks instead of manual factories
  • Handler arrays replace handler objects (MSW v2 requirement)
  • Added decorators for MobX store initialization (subscription data for banners)
  • Legacy asset loading bridges for Reflux store compatibility
  • Deleted jsapp/js/components/submissions/DataTableWrapperPollingStoriesUtils.tsx as I wasn't able to make them work with the modified code and didn't want to spend too much time on this

Obsolete Factories (replaced by Orval generation)

  • jsapp/js/endpoints/asset.factory.ts
  • jsapp/js/endpoints/bulkAction.factory.ts
  • jsapp/js/endpoints/formMedia.factory.ts
  • jsapp/js/endpoints/assetHistoryLog.factory.ts
  • jsapp/js/endpoints/assetHistoryActions.mocks.ts

Kept Factories (dynamic data that can't be generated)

  • assetData.factory.ts - Creates submission data with randomized values
  • serviceUsage.factory.ts - Dynamic usage metrics
  • organizationServiceUsage.factory.ts - Dynamic organization metrics

Module System Fix

  • Converted orval.operationName.js from ES modules to CommonJS (require/module.exports)
  • Fixed ERR_REQUIRE_ESM error when orval.config.js loads the custom operation name function
  • Node treats .js as CommonJS without "type": "module" in package.json

TypeScript Type Cleanup

  • Removed dead code branches for legacy single-object country format in assetUtils.ts and LibraryAssetForm.tsx
  • Kept defensive Array.isArray() checks with as any casts - backend standardization (Dec 2022) ensures array, but pre-migration assets may have single object
  • Fixed test imports: separated runtime imports from mock imports (/msw suffix)
  • Removed unsafe cast in FormLanguagesManager.tsx - content is now correctly typed as string

Python Linting Fixes

  • Removed unused imports: SURVEY_ROW_SCHEMA, SURVEY_CHOICE_SCHEMA
  • Fixed line length violations (E501) - split long lines/arrays
  • All files pass flake8 with --max-line-length=88

Other changes

  • Had to update some code after updating dataInterface.ts types (mainly AssetResponse) as some properties are now optional and some required

👀 Preview steps

Ensure that:

  1. Tests pass (unit, storybook, backend)
  2. Storybook stories work (run storybook)

@magicznyleszek

Copy link
Copy Markdown
Member Author

@greptile-apps review

@magicznyleszek

Copy link
Copy Markdown
Member Author

@greptile-apps review

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (174 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

@magicznyleszek

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

…-msw-gen

# Conflicts:
#	jsapp/js/api/react-query/survey-data/index.ts

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflict in jsapp/js/api/react-query/survey-data/index.ts. The conflict was caused by the main branch adding a QATagTracker import to the old survey-data.ts file, while our branch had reorganized it into survey-data/index.ts with updated relative import paths. Resolved by including both imports (QATagTracker and ReportResponse) with the correct ../../models/ path for the new file location.

@magicznyleszek

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

…-msw-gen

# Conflicts:
#	jsapp/js/components/submissions/DataTableWrapper.stories.tsx
#	orval.config.js

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved two merge conflicts:

  1. orval.config.js — kept our branch's explicit .js extension in require('./jsapp/js/api/orval.operationName.js') over main's extension-less version.
  2. jsapp/js/components/submissions/DataTableWrapper.stories.tsx — discarded main's re-addition of assetFactory/assetMock/AssetResponse imports, which our branch replaced with Orval-generated mocks (and asset.factory.ts itself was deleted in this branch).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants