analog
analog copied to clipboard
Automatically exclude spec.ts files from Nitro server bundling
Which scope/s are relevant/related to the feature request?
vite-plugin-nitro
Information
Background
If a user creates any unit test files (spec.ts or otherwise) under any paths in src/server that Nitro checks when bundling the server the unit test code will be bundled into the server application. This can lead to the built server crashing it attempts to run the unit test code. In my scenario, this happened when the vitest library identified that it was being imported / used without being invoked by the vitest executable.
Nitro does not check whether a file has a typical unit test file extension when scanning for files. They simply look for any valid JS or TS based file / module.. Unit test files by nature are valid modules.
Currently it is up to the user to configure Nitro to ignore any files to exclude during bundling. The Nitro config has an ignore property that accepts an array of glob patterns to ignore from scan results. Adding an exclude of **/*.spec.ts ignores bundling all spec.ts files under the server directory.
Proposal
Add an ignore pattern of **/*.spec.ts when configuring Nitro as a default configuration for all analog projects.
In addition to spec.ts files other common unit test related file names / extensions could be ignored, such as test.ts, mock.ts, and mocks.ts.
Rationale In Favor
Co-locating spec.ts files is a very common pattern used in the angular ecosystem.
New analog users do not have an understanding of all the technologies used in analog and how they integrate together. Due to this it is easy for someone to place unit test files within the Nitro server directory, causing their unit test code to be bundled into their application, and leading to the application crashing when run. The user then needs to analyze the analog stack to understand why the server is failing, why unit test code is being included in their application code, which library/framework dependency is responsible, and how the dependencies need to be configured to avoid bundling test code. This all may lead to a lot of confusion, technical overhead, and frustration for people new to analog and its technologies.
Defaulting to ignoring **/*.spec.ts files allows the common co-location pattern to be used without a second thought by new analog users.
Rationale Against
Co-locating unit test files is just one of many valid patterns for structuring/organizing tests. By no means is it the one and only way things could or should be done.
One key issue with adding this default ignore is that a valid route named e.g. /spec would not be able to be created. For this reason alone I question if setting a default is the right approach. However, I think the value may outweigh this route naming concern.
Additionally, just because a default ignore may be supplied doesn't mean analog cannot allow the user to remove the ignore and fully override what is ignored, similar to how the user can configure which routes to prerender.
Alternative 1 - Documentation
Listing this as an alternative, but it should be done in all paths. The analog site should clearly document how Nitro is used and may be configured an analog application. I see this being an extension of #812 which only mentions the analog and angular vite plugin currently.
Specific to this unit test scenario we should ensure the documentation calls out that unit test files will be bundled if co-located under the server directories Nitro scans and that configuration would be needed to exclude these files, whether via the default or as an added configuration on a per-project basis.
Alternative 2 - Different Test File Organization Pattern
This whole request / issue stems from the pattern of co-locating test code directly with the application code. Instead of this pattern analog could recommend a different pattern for organizing the server tests, possibly the angular app tests too.
One option would be to add a tests directory within the analog project that can mirror how src is organized, so tests/server, tests/server/routes, tests/app, and similar. Another is to place a tests directory under the server directory that can mirror the structure under the server directory, so server/tests, server/tests/routes, and similar.
Additional Thoughts
Experimenting with and learning how testing is set up in analog today, I have been thinking there would be value in having a different test setup for the server code compared to the app / frontend code.
The out-of-the-box test setup and execution is very angular / frontend focused, patching vitest for zone support and configuring the TestBed as well. Additionally, tests are run via the jsdom environment.
Testing Nitro server code does not require zone and TestBed. The server tests may be run in the jsdom environment without issue, but jsdom is inherently slower and has more overhead instantiating the DOM than using the node environment . This, along with the unit test file bundling, is enough to make me think testing in analog could/should be thought through further.
At minimum I'd like to see more documentation, details, and recommendations on how to go about testing an analog application. Additionally, I'd also love for the framework to make it as simple and "dumb" as possible to do things, including testing. If this means prescribing exactly how / what / where tests should be placed, developed, etc. then I think that would be a beneficial thing for analog.
I will caveat all this with saying this is my first venture into any meta-framework, and definitely my first time looking to develop tests for both frontend and backend code that do not have some logical separation, such as being different libraries or different repositories. I'm not sure if there are other common patterns in the ecosystem from other frameworks that may work well here in the analog space.
Describe any alternatives/workarounds you're currently using
No response
I would be willing to submit a PR to fix this issue
- [X] Yes
- [ ] No
I think adding defaults to the ignore configuration in Nitro would be ideal and commonly expected. A /spec folder should still be recognized, but any .spec.ts files within that folder should be ignored.