Skip to content

Commit d284733

Browse files
authored
fix(core): temp cleanup does not work with jest (#36226)
Our temporary cleanup fix submitted in #36043 doesn't work for tests run with `jest`, because `jest` suppresses the standard Node `exit` event, causing the cleanup to never run. Instead, we introduce a new public static function which people using `jest` can call: ```ts afterAll(CloudAssembly.cleanupTemporaryDirectories); ``` As well as a convenience script to automatically inject this handler into all jest tests: ``` $ jest --setupFilesAfterEnv aws-cdk-lib/testhelpers/jest-autoclean ``` Once this PR has been merged and released we will add the above to all CLI init templates. Closes #802, hopefully for good. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent b956492 commit d284733

File tree

4 files changed

+76
-5
lines changed

4 files changed

+76
-5
lines changed

packages/aws-cdk-lib/cx-api/lib/cloud-assembly.ts

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,53 @@ export class CloudAssembly implements ICloudAssembly {
3333
return x !== null && typeof(x) === 'object' && CLOUD_ASSEMBLY_SYMBOL in x;
3434
}
3535

36+
/**
37+
* Cleans up any temporary assembly directories that got created in this process
38+
*
39+
* If a Cloud Assembly is emitted to a temporary directory, its directory gets
40+
* added to a list. This function iterates over that list and deletes each
41+
* directory in it, to free up disk space.
42+
*
43+
* This function will normally be called automatically during Node process
44+
* exit and so you don't need to call this. However, some test environments do
45+
* not properly trigger Node's `exit` event. Notably: Jest does not trigger
46+
* the `exit` event (<https://github.com/jestjs/jest/issues/10927>).
47+
*
48+
* ## Cleaning up temporary directories in jest
49+
*
50+
* For Jest, you have to make sure this function is called at the end of the
51+
* test suite instead:
52+
*
53+
* ```js
54+
* import { CloudAssembly } from 'aws-cdk-lib/cx-api';
55+
*
56+
* afterAll(CloudAssembly.cleanupTemporaryDirectories);
57+
* ```
58+
*
59+
* Alternatively, you can use the `setupFilesAfterEnv` feature and use a
60+
* provided helper script to automatically inject the above into every
61+
* test file, so you don't have to do it by hand.
62+
*
63+
* ```
64+
* $ npx jest --setupFilesAfterEnv aws-cdk-lib/testhelpers/jest-autoclean
65+
* ```
66+
*
67+
* Or put the following into `jest.config.js`:
68+
*
69+
* ```js
70+
* module.exports = {
71+
* // ...
72+
* setupFilesAfterEnv: ['aws-cdk-lib/testhelpers/jest-cleanup'],
73+
* };
74+
* ```
75+
*/
76+
public static cleanupTemporaryDirectories() {
77+
for (const dir of TEMPORARY_ASSEMBLY_DIRS) {
78+
fs.rmSync(dir, { recursive: true, force: true });
79+
}
80+
TEMPORARY_ASSEMBLY_DIRS.splice(0, TEMPORARY_ASSEMBLY_DIRS.length);
81+
}
82+
3683
/**
3784
* The root directory of the cloud assembly.
3885
*/
@@ -498,8 +545,4 @@ function ensureDirSync(dir: string) {
498545

499546
// On process exit, delete all temporary assembly directories
500547
const TEMPORARY_ASSEMBLY_DIRS: string[] = [];
501-
process.on('exit', () => {
502-
for (const dir of TEMPORARY_ASSEMBLY_DIRS) {
503-
fs.rmSync(dir, { recursive: true, force: true });
504-
}
505-
});
548+
process.on('exit', () => CloudAssembly.cleanupTemporaryDirectories());

packages/aws-cdk-lib/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@
530530
"./pipelines/package.json": "./pipelines/package.json",
531531
"./recommended-feature-flags.json": "./recommended-feature-flags.json",
532532
"./region-info": "./region-info/index.js",
533+
"./testhelpers/jest-autoclean": "./testhelpers/jest-autoclean.js",
533534
"./triggers": "./triggers/index.js"
534535
},
535536
"publishConfig": {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* A file designed to be used with Jest's `--setupFilesAfterEnv` flag, to automatically clean temporary directories.
3+
*
4+
* This is an effective alternative to adding an `afterAll()` to every individual test file.
5+
*
6+
* Can be used as follows:
7+
*
8+
* ```
9+
* $ jest --setupFilesAfterEnv aws-cdk-lib/testhelpers/jest-autoclean
10+
* ```
11+
*/
12+
import { CloudAssembly } from '../cx-api';
13+
14+
// eslint-disable-next-line @typescript-eslint/unbound-method
15+
afterAll(CloudAssembly.cleanupTemporaryDirectories);

tools/@aws-cdk/cdk-build-tools/config/jest.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
const thisPackagesPackageJson = require(`${process.cwd()}/package.json`);
2+
const setupFilesAfterEnv = [];
3+
if ('aws-cdk-lib' in thisPackagesPackageJson.devDependencies ?? {}) {
4+
// If we depend on aws-cdk-lib, use the provided autoclean hook
5+
setupFilesAfterEnv.push('aws-cdk-lib/testhelpers/jest-autoclean');
6+
} else if (thisPackagesPackageJson.name === 'aws-cdk-lib') {
7+
// If we *ARE* aws-cdk-lib, use the hook in a slightly different way
8+
setupFilesAfterEnv.push('./testhelpers/jest-autoclean.ts');
9+
}
10+
111
module.exports = {
212
// The preset deals with preferring TS over JS
313
moduleFileExtensions: [
@@ -31,4 +41,6 @@ module.exports = {
3141
],
3242
coveragePathIgnorePatterns: ['\\.generated\\.[jt]s$', '<rootDir>/test/', '.warnings.jsii.js$', '/node_modules/'],
3343
reporters: ['default', ['jest-junit', { suiteName: 'jest tests', outputDirectory: 'coverage' }]],
44+
45+
setupFilesAfterEnv,
3446
};

0 commit comments

Comments
 (0)