Rules Hub
Coding Rules Library
Wrap global mutations in try-finally for safe test cleanup
When modifying global objects (prototypes, window) in a test, use try-finally to guarantee cleanup even upon failure.
Bad example
| 1 | test('polyfills missing feature', () => { |
| 2 | const original = String.prototype.includes; |
| 3 | |
| 4 | // Mutation: we delete a global property to simulate an old browser |
| 5 | Reflect.deleteProperty(String.prototype, 'includes'); |
| 6 |
|
| 7 | // If this assertion fails, the code throws immediately |
| 8 | expect('foo'.includes).toBeUndefined(); |
| 9 |
|
| 10 | // This line is never reached, leaving the global environment broken for future tests |
| 11 | String.prototype.includes = original; |
| 12 | }); |
Explanation (EN)
If the assertion fails, the execution stops immediately, and the global `String.prototype` is never restored. This causes 'test pollution', where subsequent tests fail mysteriously because the environment remains broken.
Objašnjenje (HR)
Ako tvrdnja (assertion) ne prođe, izvršavanje se odmah prekida i globalni `String.prototype` se nikada ne vraća u prvobitno stanje. To uzrokuje 'zagađenje testova', gdje naredni testovi misteriozno padaju jer je okruženje ostalo pokvareno.
Good example
| 1 | test('polyfills missing feature', () => { |
| 2 | const originalDescriptor = Object.getOwnPropertyDescriptor(String.prototype, 'includes'); |
| 3 | Reflect.deleteProperty(String.prototype, 'includes'); |
| 4 |
|
| 5 | try { |
| 6 | // Even if this fails... |
| 7 | expect('foo'.includes).toBeUndefined(); |
| 8 | } finally { |
| 9 | // ...this always runs, restoring the environment |
| 10 | if (originalDescriptor) { |
| 11 | Object.defineProperty(String.prototype, 'includes', originalDescriptor); |
| 12 | } |
| 13 | } |
| 14 | }); |
Explanation (EN)
Wrapping the critical section in a `try...finally` block ensures that the cleanup code runs regardless of whether the test passes or throws an error. This keeps the test suite isolated and reliable.
Objašnjenje (HR)
Omotavanje kritičnog dijela u `try...finally` blok osigurava da se kod za čišćenje izvrši bez obzira na to prođe li test ili baci grešku. To održava testove izoliranima i pouzdanima.
Notes (EN)
While `beforeEach`/`afterEach` hooks handle common setups, `try...finally` is often cleaner for single-test specific mutations like checking polyfill behavior.
Bilješke (HR)
Iako `beforeEach`/`afterEach` kuke rješavaju uobičajene postavke, `try...finally` je često čišći za mutacije specifične za jedan test, poput provjere ponašanja polyfilla.