Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,8 @@ No guarantees are made about the atomicity of the copy operation. If an
error occurs after the destination file has been opened for writing, an attempt
will be made to remove the destination.

`fsPromises.copyFile()` always dereferences symlinks.

```mjs
import { copyFile, constants } from 'node:fs/promises';

Expand Down Expand Up @@ -2754,6 +2756,8 @@ callback function. Node.js makes no guarantees about the atomicity of the copy
operation. If an error occurs after the destination file has been opened for
writing, Node.js will attempt to remove the destination.

`fs.copyFile()` always dereferences symlinks.

`mode` is an optional integer that specifies the behavior
of the copy operation. It is possible to create a mask consisting of the bitwise
OR of two or more values (e.g.
Expand Down Expand Up @@ -5857,6 +5861,8 @@ already exists. Returns `undefined`. Node.js makes no guarantees about the
atomicity of the copy operation. If an error occurs after the destination file
has been opened for writing, Node.js will attempt to remove the destination.

`fs.copyFileSync()` always dereferences symlinks.

`mode` is an optional integer that specifies the behavior
of the copy operation. It is possible to create a mask consisting of the bitwise
OR of two or more values (e.g.
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/test_runner/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class TestCoverage {
ArrayPrototypePush(branchReports, {
__proto__: null,
line: range.lines[0]?.line,
count: range.count,
count: range.ignoredLines === range.lines.length ? 1 : range.count,
});

if (range.count !== 0 ||
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/test-runner/coverage-ignore-branch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

function getValue(condition) {
if (condition) {
return 'truthy';
}
/* node:coverage ignore next */
return 'falsy';
}

module.exports = { getValue };
10 changes: 10 additions & 0 deletions test/fixtures/test-runner/coverage-ignore-branch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';
const { describe, it } = require('node:test');
const assert = require('node:assert');
const { getValue } = require('./coverage-ignore-branch.js');

describe('getValue', () => {
it('should return truthy when condition is true', () => {
assert.strictEqual(getValue(true), 'truthy');
});
});
25 changes: 25 additions & 0 deletions test/parallel/test-runner-coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,28 @@ test('coverage with directory and file named "file"', skipIfNoInspector, () => {
assert.strictEqual(result.status, 0);
assert(result.stdout.toString().includes('start of coverage report'));
});

// Regression test for https://github.com/nodejs/node/issues/61586
// When a branch leads to ignored code, it should be marked as covered.
test('coverage ignores branches leading to ignored code', skipIfNoInspector, async (t) => {
const fixture = fixtures.path('test-runner', 'coverage-ignore-branch.test.js');
const child = spawnSync(process.execPath,
[
'--test',
'--experimental-test-coverage',
'--test-coverage-exclude=!test/**',
'--test-reporter',
fixtures.fileURL('test-runner/custom_reporters/coverage.mjs'),
fixture,
]);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
const coverage = JSON.parse(stdout);

const file = coverage.summary.files.find((f) => f.path.endsWith('coverage-ignore-branch.js'));
assert(file, 'Expected coverage-ignore-branch.js in coverage report');

// All branches should be covered because the untaken falsy branch
// leads to code that is ignored via /* node:coverage ignore next */.
assert.strictEqual(file.coveredBranchCount, file.totalBranchCount);
});
Loading