Skip to content

feat: Add per-test configurable TypeScript mocks for flexible offline testing#12

Merged
franky47 merged 7 commits into
nextfrom
copilot/fix-11
Sep 10, 2025
Merged

feat: Add per-test configurable TypeScript mocks for flexible offline testing#12
franky47 merged 7 commits into
nextfrom
copilot/fix-11

Conversation

Copilot AI commented Sep 10, 2025

Copy link
Copy Markdown
Contributor

This PR implements a comprehensive per-test configurable mocking infrastructure for TypeScript CDN testing, enabling flexible offline testing scenarios without network dependencies or static cache files.

What's Changed

Per-Test Configurable Mock Infrastructure

  • Dynamic TypeScript mocks: Created configureTestServer() function that accepts per-test version configurations with pass/fail behavior
  • Flexible test scenarios: Each test defines its own mock setup using Record<string, boolean> where keys are version numbers and values indicate pass (true) or fail (false)
  • On-the-fly mock generation: TypeScript modules are generated dynamically with configurable diagnostics behavior
  • No global dependencies: Removed all static cache files, centralized version config, and setup scripts

MSW Handler Abstraction

  • Configurable handlers: MSW handlers now accept per-test configuration objects and generate appropriate mock implementations
  • NPM registry mocking: Registry responses are dynamically generated based on test configuration
  • CDN handler flexibility: TypeScript CDN requests return mocks that either pass or emit diagnostics based on test needs
  • Fixed caching issue: Removed Cache-Control header to prevent HTTP caching conflicts when same version needs different behavior across tests

Infrastructure Cleanup

  • Removed static mocks: Deleted all versioned TypeScript packages from tests/mocks/cache/
  • Removed global config: Deleted src/test-config.ts centralized version management
  • Removed setup scripts: Deleted scripts/setup-ts-cache.js build-time setup
  • Migrated all tests: Updated cache tests, services tests, and CLI tests to use per-test configuration

Comprehensive Test Coverage

  • Cache functionality: Tests for TypeScriptMemoryCache and TypeScriptCDNCache with configurable mocks
  • Flexible scenarios: Example tests demonstrating version progression, breaking changes, minimum version detection
  • Interface compliance: Validation that both cache implementations follow the same contract
  • Error handling: Tests for missing versions, cache operations (clear, free, purge)

API Usage Examples

// Configure specific version behavior per test
configureTestServer({
  '4.0.0': true,   // This version passes (no diagnostics)
  '3.9.0': false   // This version fails (emits diagnostics)
})

// Use predefined configurations
configureTestServer(testConfigs.singlePass('4.0.0'))
configureTestServer(testConfigs.mixed())

Testing

All tests now pass (35/35), including new configurable handler tests and comprehensive example scenarios. The new architecture enables testing any combination of TypeScript version behaviors without being limited to pre-defined global versions.

Benefits:

  • Complete offline testing: No network dependencies or static cache files required
  • Unlimited flexibility: Tests can simulate any scenario (breaking changes, version progression, edge cases)
  • Maintainable: Each test is self-contained and defines exactly what it needs
  • Faster: Dynamic mock generation is more efficient than file-based caching
  • No caching conflicts: Removed HTTP cache headers to prevent issues when same version needs different behavior across tests

Fixes #11.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
Copilot AI changed the title [WIP] Mock the TypeScript CDN feat: Add TypeScript CDN mocking infrastructure for testing Sep 10, 2025
Copilot AI requested a review from franky47 September 10, 2025 05:33

@franky47 franky47 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot we should version those packages rather than populate a .gitignored cache, so the test process can run offline after checkout (the whole point is to abstract from the network if the CDN is down for any reason).

This means we also need to centralise the version numbers to test against, so that the NPM registry mock returns something consistent with the cache.

The filesystem should be the source of truth in this case: derive an array of version numbers from it, consume that in the NPM registry MSW handler. Tests should still use hardcoded versions, we want those to fail if the cache changes so we can detect it and update the tests if needed (eg: caching a new version).

…sting

Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>

Copilot AI commented Sep 10, 2025

Copy link
Copy Markdown
Contributor Author

@copilot we should version those packages rather than populate a .gitignored cache, so the test process can run offline after checkout (the whole point is to abstract from the network if the CDN is do...

Done! I've implemented the requested changes:

Versioned packages instead of .gitignored cache - The mock TypeScript packages are now committed to the repo in tests/mocks/cache/ for offline testing
Centralized version numbers - Created src/test-config.ts as a single source of truth for test versions
Filesystem as source of truth - MSW handlers now derive available versions from what's actually present in the filesystem via getAvailableVersions()
Tests use hardcoded versions - Tests still use hardcoded versions ('4.0.0', '5.0.0', etc.) so they'll fail if the cache changes, enabling detection

The mock packages are minimal CommonJS modules that provide just the essential TypeScript API surface (ScriptTarget, version, etc.) needed for testing. The setup script now creates mocks instead of downloading real packages. All tests pass (27/27) and work completely offline.

Commit: f6d64f3

Copilot AI changed the title feat: Add TypeScript CDN mocking infrastructure for testing feat: Add versioned TypeScript mocks for offline testing infrastructure Sep 10, 2025
Copilot AI requested a review from franky47 September 10, 2025 06:13

@franky47 franky47 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot oh this is giving me a better idea.

If we can mock the typescript package like this, we should drop the idea of versioning actual versions from the CDN (for offline use), and instead configure both MSW handlers per test with the appropriate versions, by injecting a mocked typescript package that either passes or emits diagnostics errors, whether we want that version to fail or pass for a given test.

So there would be no globally defined version set, each test would define what setup it needs.

New plan:

  1. Abstract the MSW handlers to be configurable per test, taking in an object where the keys are version numbers and values are booleans (true = pass, false = fail by emitting diagnostics). Have the CDN handler return the correct mock implementation for each package of that config object, and the NPM registry mock return just those versions.
  2. In each test, configure the handlers with a config object that is appropriate for the intent of the test
  3. Remove all local caching and setup code

Copilot AI and others added 2 commits September 10, 2025 07:05
Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
…move static cache infrastructure

Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>

Copilot AI commented Sep 10, 2025

Copy link
Copy Markdown
Contributor Author

@copilot oh this is giving me a better idea.

If we can mock the typescript package like this, we should drop the idea of versioning actual versions from the CDN (for offline use), and instead configu...

Absolutely! This is a much better approach. I've implemented exactly what you described:

Per-test configuration: Each test now defines its own mock setup using configureTestServer({ '4.0.0': true, '3.9.0': false })

Dynamic TypeScript mocks: Generated on-the-fly with configurable pass/fail behavior based on whether they should emit diagnostics

No global versions: Removed all static cache files, centralized config, and setup scripts

MSW handlers abstracted: The handlers take version/boolean config objects and return appropriate mock implementations

The new API is much more flexible - tests can simulate any scenario (breaking changes, minimum version detection, edge cases) without being limited to pre-defined global versions. All 35 tests pass and work completely offline.

Commit: 20a615f

…ation flexibility

Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
Copilot AI changed the title feat: Add versioned TypeScript mocks for offline testing infrastructure feat: Add per-test configurable TypeScript mocks for flexible offline testing Sep 10, 2025
Copilot AI requested a review from franky47 September 10, 2025 07:13
@franky47 franky47 marked this pull request as ready for review September 10, 2025 11:24
status: 200,
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=86400'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot question: Could this cache be problematic if we need to fetch a passing 1.2.3 and then a failing 1.2.3 in the same test run?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! You're absolutely right - the Cache-Control header could cause problems when the same version needs to behave differently across tests in the same test run. I've removed the Cache-Control header entirely since these are dynamic test mocks that shouldn't be cached. All tests continue to pass (35/35).

Commit: 390bc9a

…t configurations

Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
@franky47 franky47 merged commit 2b8cdc6 into next Sep 10, 2025
2 checks passed
@franky47 franky47 deleted the copilot/fix-11 branch September 10, 2025 11:31
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.

Mock the TypeScript CDN

2 participants