Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .nx/version-plans/version-plan-1785943295154.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
__default__: patch
---

Skipped tests now appear as skipped in Jest output and compatible result consumers.
55 changes: 55 additions & 0 deletions packages/jest/src/__tests__/execute-run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,61 @@ describe('executeRun', () => {
]);
});

it.each([
['it.skip', 'skip', 0],
['context.skip', undefined, 5],
] as const)('reports %s to Jest as pending', async (_label, declarationMode, duration) => {
let testRunnerListener:
| ((event: TestRunnerTestStartedEvent | TestRunnerTestFinishedEvent) => void)
| undefined;
const { emitEvent, calls: emittedEvents } = makeEmitEvent();
const session = makeSession({
onTestRunnerEvent: vi.fn((listener) => {
testRunnerListener = listener as typeof testRunnerListener;
return () => undefined;
}),
});

mockRunHarnessTestFile.mockImplementation(async () => {
testRunnerListener?.({
type: 'test-started',
file: 'example.ts',
suite: 'suite',
name: 'does not run',
ancestorTitles: ['suite'],
fullName: 'suite does not run',
startedAt: 10,
declarationMode,
});
testRunnerListener?.({
type: 'test-finished',
file: 'example.ts',
suite: 'suite',
name: 'does not run',
ancestorTitles: ['suite'],
fullName: 'suite does not run',
startedAt: 10,
declarationMode,
duration,
status: 'skipped',
});

return makeFileRunResult();
});

await executeRun(session, [makeTest()], makeWatcher(), emitEvent, makeGlobalConfig());

expect(emittedEvents).toContainEqual([
'test-case-result',
'example.ts',
expect.objectContaining({
fullName: 'suite does not run',
numPassingAsserts: 0,
status: 'pending',
}),
]);
});

it('includes pending promise diagnostics in live test-case failures', async () => {
let testRunnerListener:
| ((event: TestRunnerTestStartedEvent | TestRunnerTestFinishedEvent) => void)
Expand Down
39 changes: 39 additions & 0 deletions packages/jest/src/__tests__/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,43 @@ describe('runHarnessTestFile', () => {
expect.objectContaining({ testTimeout: 15000 }),
);
});

it('reports declaration-time and runtime skips to Jest as pending', async () => {
const session = createSession(15000);
vi.mocked(session.runTestFile).mockResolvedValue({
...createHarnessResult(),
tests: [
{
name: 'passes',
status: 'passed',
duration: 1,
},
{
name: 'declaration skip',
status: 'skipped',
duration: 0,
declarationMode: 'skip',
},
{
name: 'runtime skip',
status: 'skipped',
duration: 1,
},
],
});

const { jestResult } = await runHarnessTestFile({
testPath: '/project/example.harness.ts',
session,
globalConfig: createGlobalConfig(),
projectConfig: createProjectConfig(),
});

expect(jestResult.numPendingTests).toBe(2);
expect(jestResult.testResults).toEqual([
expect.objectContaining({ title: 'passes', status: 'passed' }),
expect.objectContaining({ title: 'declaration skip', status: 'pending' }),
expect.objectContaining({ title: 'runtime skip', status: 'pending' }),
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('createPlatformSkippedTestResult', () => {
expect(result.testResults).toHaveLength(1);
expect(result.testResults[0]).toEqual(
expect.objectContaining({
status: 'skipped',
status: 'pending',
title: 'swift.ios.harness.ts',
fullName: 'swift.ios.harness.ts',
}),
Expand Down
3 changes: 2 additions & 1 deletion packages/jest/src/execute-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import { formatHarnessErrorMessage } from './format-harness-error.js';
import { logger } from '@react-native-harness/tools';
import { printSummary, writeTraceFile } from './diagnostics/index.js';
import { toJestStatus } from './toJestStatus.js';

const diagnosticsLogger = logger.child('diagnostics');

Expand Down Expand Up @@ -109,7 +110,7 @@ const emitHarnessTestFinished = async (
location,
numPassingAsserts: event.status === 'passed' ? 1 : 0,
startedAt: event.startedAt,
status: event.status,
status: toJestStatus(event.status),
title: event.name,
};

Expand Down
6 changes: 6 additions & 0 deletions packages/jest/src/toJestStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Status } from '@jest/test-result';
import type { TestResultStatus } from '@react-native-harness/bridge';

// Jest's own runners expose skipped assertions as `pending` to reporters.
export const toJestStatus = (status: TestResultStatus): Status =>
status === 'skipped' ? 'pending' : status;
8 changes: 5 additions & 3 deletions packages/jest/src/toTestResult.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Status, TestResult } from '@jest/test-result';
import type { TestResult } from '@jest/test-result';
import type { TestResultStatus } from '@react-native-harness/bridge';
import { toJestStatus } from './toJestStatus.js';

export type Options = {
stats: {
Expand All @@ -17,7 +19,7 @@ export type Options = {
testPath?: string;
title?: string;
fullName?: string;
status: Status;
status: TestResultStatus;
location?: {
column: number;
line: number;
Expand Down Expand Up @@ -75,7 +77,7 @@ const getTestResults = ({
failureMessages: actualErrorMessage ? [actualErrorMessage] : [],
fullName: test.fullName || test.testPath || jestTestPath || '',
numPassingAsserts: test.status === 'passed' ? 1 : 0,
status: test.status,
status: toJestStatus(test.status),
title: test.title || '',
location: test.location,
};
Expand Down
Loading