Skip to content

Commit 10efeb6

Browse files
authored
feat(test): jest 27 support (#3189)
this commit restores running the `npm test` command as a part of the root level package.json's `test.end-to-end` script (and readds it to CI). this commit provides support for jest 27 in stencil. this is accomplished by no longer pulling default options from the jest-cli package, which now encapsulates its contents through an `exports` field in its package.json file. during the course of this work, it was discovered the same fields/defaults were used with Jest 24, 25, & 26. Those options have been pulled out into a helper function to be provided for Jest v24 thru 27 to ensure a consistent experience. this helper will be removed in a future version of Stencil. the test runner for consumers is locked to jest-jasmine2 for backwards compatibility in this commit. jest-runner exposes its default export differently in jest 27. the creation of a stencil test runner has been updated to handle the differences between jest v27 and v26 (and under). jest, jest-cli, jest-environment-node were all updated to the latest patch version to test with the latest and greatest versions of the libraries. update @types/jest to v27, set as recommended version add an adr for jest 27 work
1 parent 51b3e44 commit 10efeb6

9 files changed

+1107
-3002
lines changed

docs/adr/0004-jest-27-support.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Date: 2021-07-30
44

55
## Status
66

7-
accepted
7+
historical - see [ADR 0015](./0015-jest-27-implementation.md) for updated information
88

99
## Context
1010

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# 0015. jest 27 implementation
2+
3+
Date: 2021.12.16
4+
5+
## Status
6+
7+
historical
8+
9+
## Context
10+
11+
In 2021.Q2, the team decided to perform a more comprehensive evaluation of the Jest 27 upgrade & split the effort into
12+
multiple user stories (see [ADR-0004](./0004-jest-27-support.md)). This document explains various design decisions that
13+
were accounted for as a part of the upgrade itself.
14+
15+
## Decisions Made
16+
17+
### Jest was Upgraded Internally before Exposing Functionality to End Users
18+
19+
Stencil's Jest infrastructure is configured such that the compiler uses the same base Jest configuration as consumers
20+
of Stencil's testing functionality. This coupling allows for the compiler to test the base configuration while running
21+
its own unit tests. A consequence of this design is that upgrade Jest requires either doing the upgrade in such a way
22+
that affects the core team and end users (all at once), or splitting up the work (where the internal upgrade occurs
23+
first). Due to the number of breaking changes in Jest 27, we opted for the latter in order to work more carefully and
24+
ensure we understood the infrastructure as a whole.
25+
26+
The work to add Jest support internally was completed in [#3171](https://github.com/ionic-team/stencil/pull/3171).
27+
28+
#### Use `jest-jasmine2` as the Test Runner
29+
30+
One of the more impactful changes that Jest 27 introduces is moving away from a Jasmine-based test runner
31+
(`jest-jasmine2`) in favor of `jest-circus`. Stencil's existing infrastructure around environment set up assumes a
32+
Jasmine-based environment. Swapping out the environment type would expand the scope of the upgrade and potentially be a
33+
further breaking change for consumers. As a result, we opted to continue to use `jest-jasmine`, with an eye to moving
34+
`jest-circus` at a later date.
35+
36+
#### Backwards Compatability for Earlier Versions of Jest in Preprocessor
37+
38+
Stencil comes with a standard preprocessor for Jest that transforms non-CommonJS-based files (that are not written in
39+
JavaScript). Between Jest versions 23 (when the preprocessor was written) and version 27, the function signatures of
40+
two important functions have changed:
41+
42+
1. `process()` - performs the transformation of files when running Jest tests
43+
2. `getCacheKey()` - generates a cache key for each file transformed by `process()`, and is used to prevent unnecessary
44+
transformations of files that have not changed between runs of Jest.
45+
46+
Care was taken to allow for a high degree of backwards compatability between versions 24 (the current minimum supported
47+
version) and version 27 of Jest. This led to the creation of boilerplate type checking code. To minimize maintenance of
48+
these checks, they will be eliminated in a future major release of Stencil, when the minimum supported version of Jest
49+
is incremented to v27.
50+
51+
However, Stencil's cache naming strategy did still have to change in order to ensure a positive user experience. The
52+
result of changing the naming strategy is that existing caches on a user's machine will be stale until tests are run
53+
for the first time using the version of Stencil v2.12.0 (which includes this support). After the first run of tests,
54+
the cache should be properly populated.
55+
56+
#### Temporarily Disable Certain Tests in Continuous Integration Runs
57+
58+
Stencil's end-to-end testing suite uses the version of Jest that is installed at the root of the project, as if it were
59+
the version of Jest that an end user had installed themselves. This was a problematic aspect of the migration in that
60+
the separation of work assumed that the first half wouldn't break existing tests (which it did, as support for Stencil
61+
consumers to use Jest 27 had not yet been implemented). Although this broke tests, it did not break Stencil itself. To
62+
work around this issue, the end-to-end tests were temporarily disabled, and re-enabled in the follow-up PR for adding
63+
Jest 27 support for end users
64+
65+
### User Facing Decisions Made
66+
67+
The work to add Jest support for end users was completed in [#3189](https://github.com/ionic-team/stencil/pull/3189).
68+
69+
#### Legacy Jest Options
70+
71+
One of the largest indicators of users wanting to use Jest 27 came in the form of GitHub issues, Slack questions, and
72+
the like with the following error message after upgrading to Jest 27 (before support was implemented):
73+
74+
> Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './build/cli/args' is not defined by "exports" in ../node_modules/jext-cli/package.json
75+
76+
The reason for this error message is the Jest team decided to encapsulate `'./build/cli/args.js'` using the `exports`
77+
keyword in the `jest-cli` subpackage as a part of the Jest 27 release. This prevents the Node runtime from importing
78+
the file by design. This posed a problem, as said file was used to generated a series of arguments to be provided to
79+
Jest when tests were run.
80+
81+
When evaluating the behavior of how Stencil used this file with Jest versions 24 through 26, it was realized that
82+
`args.js` (that is no longer available in v27) was used to generate the same arguments under all three versions of
83+
Jest. Given that this list is small, the team has decided to extract it into the Stencil codebase rather than
84+
dynamically generate it.
85+
86+
Like any other static list, there is the chance of the one added to the codebase to grow stale. To help prevent this,
87+
the team intends to remove this list when Jest 27 is the minimum version of the library supported by Stencil.
88+
89+
Alternatively, the team could have taken the route of attempting to circumvent this encapsulation (and did in fact
90+
prototype this), but ultimately decided against it for two reasons:
91+
1. The Jest team has been explicit about the contract between consumers of `jest-cli` and the package itself, and the
92+
Stencil team should honor it
93+
2. The Jest team would be fully within their right to move the `args.js` file in _any_ release of Jest moving forward,
94+
which would break Stencil testing support
95+
96+
#### `@types/jest` Continued to be Used
97+
98+
Jest is (largely) written in TypeScript. When a library migrates from JavaScript to TypeScript, that type migration can
99+
be a signal to move to the typings provided by the library instead of those provided by the Definitely Typed community.
100+
For this effort, the team has decided to continue to use `@types/jest` rather than attempt to use any typings provided
101+
by Jest itself. The reason for this decision is to align ourselves with the guidance provided by Jest on using
102+
Jest with TypeScript. As of v27.4 of Jest, the current guidance is:
103+
104+
> You may also want to install the @types/jest module for the version of Jest you're using. This will help provide full
105+
> typing when writing your tests with TypeScript.
106+
107+
Should this advice change the Stencil team shall revisit this decision.
108+
109+
### Future Work
110+
111+
#### "Which Versions of Jest does Stencil Support?"
112+
113+
Stencil does not make it clear in its documentation which versions of Jest are supported. The team shall take efforts
114+
to clarify the versions of Jest that are currently supported.
115+
116+
## Links
117+
118+
- [ADR-0004-jest-27-support](./0004-jest-27-support.md)

docs/adr/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
* [12. output-markdown-format](0012-output-markdown-format.md)
1515
* [13. deno-removal](0013-deno-removal.md)
1616
* [14. adopt-volta](0014-adopt-volta.md)
17+
* [15. jest-27-implementation](0015-jest-27-implementation.md)

0 commit comments

Comments
 (0)