diff --git a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/Matchers.ts b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/Matchers.ts index fe7ae378890..ca64367f1e2 100644 --- a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/Matchers.ts +++ b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/Matchers.ts @@ -1,6 +1,6 @@ import { getComparator } from './Comparators'; import { appendWhiteSpaceToMatchLength, color } from './stringFormatUtils'; -import { ComparisonMode, OperationUpdate, TestCase, TestValue, TrackerCallCount } from './types'; +import { ComparisonMode, OperationUpdate, TestCase, TestValue, NullableTestValue, TrackerCallCount } from './types'; type MatcherFunction = ( currentValue: TestValue, @@ -210,3 +210,15 @@ export class Matchers { return `Expected ${expected} snapshots, but received ${received} snapshots\n`; } } + +export function nullableMatch(currentValue: NullableTestValue, testCase: TestCase, negation: boolean = false) { + const pass = currentValue === null || currentValue === undefined; + + const coloredExpected = color('nullable', 'green'); + const coloredReceived = color(currentValue, 'red'); + const message = `Expected${negation ? ' NOT' : ''} ${coloredExpected} received ${coloredReceived}`; + + if ((!pass && !negation) || (pass && negation)) { + testCase.errors.push(message); + } +} diff --git a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsApi.ts b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsApi.ts index 3a766c2d345..47982213c60 100644 --- a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsApi.ts +++ b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsApi.ts @@ -2,7 +2,7 @@ import { Component, ReactElement } from 'react'; import { TestRunner } from './TestRunner'; import { TestComponent } from './TestComponent'; import type { SharedValue } from 'react-native-reanimated'; -import { TestConfiguration, TestValue } from './types'; +import { TestConfiguration, TestValue, NullableTestValue } from './types'; export { Presets } from './Presets'; @@ -100,6 +100,14 @@ export function expect(value: TestValue) { return testRunner.expect(value); } +export function expectNullable(currentValue: NullableTestValue) { + return testRunner.expectNullable(currentValue); +} + +export function expectNotNullable(currentValue: NullableTestValue) { + return testRunner.expectNotNullable(currentValue); +} + export function configure(config: TestConfiguration) { return testRunner.configure(config); } diff --git a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/TestRunner.ts b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/TestRunner.ts index 219c8329cf3..745a980e116 100644 --- a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/TestRunner.ts +++ b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/TestRunner.ts @@ -1,5 +1,6 @@ import { Component, MutableRefObject, ReactElement, useRef } from 'react'; import type { + NullableTestValue, LockObject, Operation, SharedValueSnapshot, @@ -15,7 +16,7 @@ import { render, stopRecordingAnimationUpdates, unmockAnimationTimer } from './R import { makeMutable, runOnUI, runOnJS, SharedValue } from 'react-native-reanimated'; import { color, formatString, indentNestingLevel } from './stringFormatUtils'; import { createUpdatesContainer } from './UpdatesContainer'; -import { Matchers } from './Matchers'; +import { Matchers, nullableMatch } from './Matchers'; import { assertMockedAnimationTimestamp, assertTestCase, assertTestSuite } from './Asserts'; let callTrackerRegistryJS: Record = {}; @@ -258,6 +259,16 @@ export class TestRunner { return new Matchers(currentValue, this._currentTestCase); } + public expectNullable(currentValue: NullableTestValue) { + assertTestCase(this._currentTestCase); + nullableMatch(currentValue, this._currentTestCase); + } + + public expectNotNullable(currentValue: NullableTestValue) { + assertTestCase(this._currentTestCase); + nullableMatch(currentValue, this._currentTestCase, true); + } + public beforeAll(job: () => void) { assertTestSuite(this._currentTestSuite); this._currentTestSuite.beforeAll = job; diff --git a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/stringFormatUtils.ts b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/stringFormatUtils.ts index b0450543285..1d3190f9f39 100644 --- a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/stringFormatUtils.ts +++ b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/stringFormatUtils.ts @@ -1,4 +1,4 @@ -import { TestValue } from './types'; +import { NullableTestValue } from './types'; export const RUNTIME_TEST_ERRORS = { UNDEFINED_TEST_SUITE: 'Undefined test suite context', @@ -16,7 +16,7 @@ export function appendWhiteSpaceToMatchLength(message: string | number, length: return `${messageStr}${' '.repeat(length - messageLen)}`; } -export function color(value: TestValue, color: 'yellow' | 'cyan' | 'green' | 'red' | 'gray') { +export function color(value: NullableTestValue, color: 'yellow' | 'cyan' | 'green' | 'red' | 'gray') { const COLOR_CODES = { red: '\x1b[31m', green: '\x1b[32m', diff --git a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/types.ts b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/types.ts index c5234e224fd..001b72b2864 100644 --- a/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/types.ts +++ b/app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/types.ts @@ -65,6 +65,7 @@ export interface Operation { } export type TestValue = TrackerCallCount | string | Array | number | bigint | Record; +export type NullableTestValue = TestValue | null | undefined; export type TestConfiguration = { render: Dispatch>;