Skip to content

test_runner: fix Date serialization in TAP reporter YAML output #58762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions lib/internal/test_runner/reporter/tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ function jsToYaml(indent, name, value, seen) {
if (internalBinding('types').isDate(value)) {
// YAML uses the ISO-8601 standard to express dates.
result += ' ' + DatePrototypeToISOString(value);
result += '\n';
return result; // Early return to prevent processing Date as object
}
result += '\n';
propsIndent += ' ';
Expand Down
31 changes: 31 additions & 0 deletions test/fixtures/test-runner/output/tap_date_serialization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Flags: --test-reporter=tap
'use strict';
const { test } = require('node:test');
const assert = require('node:assert');

// Test Date vs Date comparison
test('date vs date comparison', () => {
const expected = new Date('2023-01-01T12:00:00.000Z');
const actual = new Date('2023-01-01T13:00:00.000Z');
assert.deepStrictEqual(actual, expected);
});

// Test Date vs String comparison
test('date vs string comparison', () => {
const expected = '2023-01-01T12:00:00.000Z';
const actual = new Date('2023-01-01T13:00:00.000Z');
assert.deepStrictEqual(actual, expected);
});

// Test nested Date objects
test('nested date objects', () => {
const expected = {
timestamp: new Date('2023-01-01T12:00:00.000Z'),
message: 'test'
};
const actual = {
timestamp: new Date('2023-01-01T13:00:00.000Z'),
message: 'test'
};
assert.deepStrictEqual(actual, expected);
});
99 changes: 99 additions & 0 deletions test/fixtures/test-runner/output/tap_date_serialization.snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
TAP version 13
# Subtest: date vs date comparison
not ok 1 - date vs date comparison
---
duration_ms: *
type: 'test'
location: '*test-runner*tap_date_serialization.js:7:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly deep-equal:
+ actual - expected

+ 2023-01-01T13:00:00.000Z
- 2023-01-01T12:00:00.000Z

code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: 2023-01-01T12:00:00.000Z
actual: 2023-01-01T13:00:00.000Z
operator: 'deepStrictEqual'
stack: |-
TestContext.<anonymous> (*test-runner*tap_date_serialization.js:10:10)
Test.runInAsyncScope (node:async_hooks:214:14)
Test.run (node:internal/test_runner/test:1047:25)
Test.start (node:internal/test_runner/test:944:17)
startSubtestAfterBootstrap (node:internal/test_runner/harness:297:17)
...
# Subtest: date vs string comparison
not ok 2 - date vs string comparison
---
duration_ms: *
type: 'test'
location: '*test-runner*tap_date_serialization.js:14:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly deep-equal:
+ actual - expected

+ 2023-01-01T13:00:00.000Z
- '2023-01-01T12:00:00.000Z'

code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: '2023-01-01T12:00:00.000Z'
actual: 2023-01-01T13:00:00.000Z
operator: 'deepStrictEqual'
stack: |-
TestContext.<anonymous> (*test-runner*tap_date_serialization.js:17:10)
Test.runInAsyncScope (node:async_hooks:214:14)
Test.run (node:internal/test_runner/test:1047:25)
Test.processPendingSubtests (node:internal/test_runner/test:744:18)
Test.postRun (node:internal/test_runner/test:1173:19)
Test.run (node:internal/test_runner/test:1101:12)
async startSubtestAfterBootstrap (node:internal/test_runner/harness:297:3)
...
# Subtest: nested date objects
not ok 3 - nested date objects
---
duration_ms: *
type: 'test'
location: '*test-runner*tap_date_serialization.js:21:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly deep-equal:
+ actual - expected

{
message: 'test',
+ timestamp: 2023-01-01T13:00:00.000Z
- timestamp: 2023-01-01T12:00:00.000Z
}

code: 'ERR_ASSERTION'
name: 'AssertionError'
expected:
timestamp: 2023-01-01T12:00:00.000Z
message: 'test'
actual:
timestamp: 2023-01-01T13:00:00.000Z
message: 'test'
operator: 'deepStrictEqual'
stack: |-
TestContext.<anonymous> (*test-runner*tap_date_serialization.js:30:10)
Test.runInAsyncScope (node:async_hooks:214:14)
Test.run (node:internal/test_runner/test:1047:25)
Test.processPendingSubtests (node:internal/test_runner/test:744:18)
Test.postRun (node:internal/test_runner/test:1173:19)
Test.run (node:internal/test_runner/test:1101:12)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
1..3
# tests 3
# suites 0
# pass 0
# fail 3
# cancelled 0
# skipped 0
# todo 0
# duration_ms *
8 changes: 8 additions & 0 deletions test/parallel/test-runner-output.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ const tests = [
),
flags: ['--test-reporter=tap'],
},
{
name: 'test-runner/output/tap_date_serialization.js',
transform: snapshot.transform(
snapshot.replaceWindowsLineEndings,
replaceTestDuration,
),
flags: ['--test-reporter=tap'],
},
{
name: 'test-runner/output/test-runner-plan.js',
flags: ['--test-reporter=tap'],
Expand Down
21 changes: 21 additions & 0 deletions test/parallel/test-tap-yaml-date-serialization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

// This file documents that Date serialization in TAP reporter YAML output
// is tested via the fixture test: test/fixtures/test-runner/output/tap_date_serialization.js
//
// The fixture test verifies that:
// 1. Date objects are serialized as clean ISO strings (e.g., "2023-01-01T12:00:00.000Z")
// 2. Date vs String comparisons show clear distinction (Date vs '2023-01-01T12:00:00.000Z')
// 3. Nested Date objects in error details are properly serialized
// 4. Date objects do NOT include their methods/properties (getTime, valueOf, etc.)
//
// This behavioral testing approach is more robust than testing implementation details
// and is resistant to code refactoring.

const { test } = require('node:test');

// Simple placeholder test to ensure this file is valid
test('Date serialization is tested via fixture', () => {
// The actual testing is done via test/fixtures/test-runner/output/tap_date_serialization.js
// and verified against test/fixtures/test-runner/output/tap_date_serialization.snapshot
});