feat: Add per-test configurable TypeScript mocks for flexible offline testing#12
Conversation
Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
franky47
left a comment
There was a problem hiding this comment.
@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>
Done! I've implemented the requested changes: ✅ Versioned packages instead of .gitignored cache - The mock TypeScript packages are now committed to the repo in 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 |
franky47
left a comment
There was a problem hiding this comment.
@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:
- 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.
- In each test, configure the handlers with a config object that is appropriate for the intent of the test
- Remove all local caching and setup code
Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
…move static cache infrastructure Co-authored-by: franky47 <1174092+franky47@users.noreply.github.com>
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 ✅ 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>
| status: 200, | ||
| headers: { | ||
| 'Content-Type': 'application/javascript', | ||
| 'Cache-Control': 'public, max-age=86400' |
There was a problem hiding this comment.
@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?
There was a problem hiding this comment.
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>
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
configureTestServer()function that accepts per-test version configurations with pass/fail behaviorRecord<string, boolean>where keys are version numbers and values indicate pass (true) or fail (false)MSW Handler Abstraction
Infrastructure Cleanup
tests/mocks/cache/src/test-config.tscentralized version managementscripts/setup-ts-cache.jsbuild-time setupComprehensive Test Coverage
TypeScriptMemoryCacheandTypeScriptCDNCachewith configurable mocksAPI Usage Examples
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:
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.