Skip to content
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

Unify nullable comparison #6344

Merged
merged 2 commits into from
Jul 30, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Component, ReactElement } from 'react';
import { TestRunner } from './TestRunner/TestRunner';
import type { TestComponent } from './TestComponent';
import type { SharedValue } from 'react-native-reanimated';
import type { TestConfiguration, TestValue, NullableTestValue, BuildFunction } from './types';
import type { TestConfiguration, TestValue, BuildFunction } from './types';
import { DescribeDecorator, TestDecorator } from './types';

export { Presets } from './Presets';
Expand Down Expand Up @@ -164,14 +164,6 @@ 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Component, MutableRefObject, ReactElement } from 'react';
import { useRef } from 'react';
import type {
BuildFunction,
NullableTestValue,
Operation,
SharedValueSnapshot,
TestCase,
Expand All @@ -21,7 +20,7 @@ import type {
SharedTransitionAnimationsValues,
LayoutAnimation,
} from 'react-native-reanimated';
import { Matchers, nullableMatch } from '../matchers/Matchers';
import { Matchers } from '../matchers/Matchers';
import { assertMockedAnimationTimestamp, assertTestCase, assertTestSuite } from './Asserts';
import { createUpdatesContainer } from './UpdatesContainer';
import { makeMutable, runOnJS } from 'react-native-reanimated';
Expand Down Expand Up @@ -326,16 +325,6 @@ 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { color } from '../utils/stringFormatUtils';
import type { TestCase, TestValue, NullableTestValue } from '../types';
import type { TestCase, TestValue } from '../types';
import type { Matcher, MatcherArguments } from './rawMatchers';
import {
toBeMatcher,
toBeWithinRangeMatcher,
toBeCalledMatcher,
toBeCalledUIMatcher,
toBeCalledJSMatcher,
toBeNullableMatcher,
} from './rawMatchers';
import { compareSnapshots } from './snapshotMatchers';
import type { SingleViewSnapshot } from '../TestRunner/UpdatesContainer';
Expand All @@ -31,6 +31,7 @@ export class Matchers {
}

public toBe = this.decorateMatcher(toBeMatcher);
public toBeNullable = this.decorateMatcher(toBeNullableMatcher);
public toBeWithinRange = this.decorateMatcher(toBeWithinRangeMatcher);
public toBeCalled = this.decorateMatcher(toBeCalledMatcher);
public toBeCalledUI = this.decorateMatcher(toBeCalledUIMatcher);
Expand All @@ -56,15 +57,3 @@ export class Matchers {
}
}
}

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { ComparisonMode } from '../types';
import { getComparator } from './Comparators';

type ToBeArgs = [TestValue, ComparisonMode?];
type ToBeNullArgs = [];
type ToBeWithinRangeArgs = [number, number];
type ToBeCalledArgs = [number];

export type MatcherArguments = ToBeArgs | ToBeCalledArgs | ToBeWithinRangeArgs;
export type MatcherArguments = ToBeArgs | ToBeNullArgs | ToBeCalledArgs | ToBeWithinRangeArgs;

export type Matcher<Args extends MatcherArguments> = (
currentValue: TestValue,
Expand Down Expand Up @@ -39,6 +40,16 @@ export const toBeMatcher: Matcher<ToBeArgs> = (currentValue, negation, expectedV
};
};

export const toBeNullableMatcher: Matcher<ToBeNullArgs> = (currentValue, negation) => {
const coloredExpected = green('nullable');
const coloredReceived = red(currentValue);

return {
pass: currentValue === null || currentValue === undefined,
message: `Expected${negation ? ' NOT' : ''} ${coloredExpected} received ${coloredReceived}`,
};
};

export const toBeWithinRangeMatcher: Matcher<ToBeWithinRangeArgs> = (
currentValue,
negation,
Expand All @@ -51,7 +62,7 @@ export const toBeWithinRangeMatcher: Matcher<ToBeWithinRangeArgs> = (

return {
pass: isWithinRange && validInputTypes,
message: `Expected the value ${negation ? ' NOT' : ''}to be in range ${green(
message: `Expected the value${negation ? ' NOT' : ''} to be in range ${green(
`[${minimumValue}, ${maximumValue}]`,
)} received ${red(currentValue)}`,
};
Expand Down
4 changes: 1 addition & 3 deletions apps/common-app/src/examples/RuntimeTests/ReJest/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,11 @@ export type TestValue =
| number
| bigint
| Record<string, unknown>
| boolean
| null
| undefined
| boolean
| OperationUpdate;

export type NullableTestValue = TestValue | null | undefined;

export type TestConfiguration = {
render: Dispatch<SetStateAction<ReactNode | null>>;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Mismatch, NullableTestValue } from '../types';
import type { Mismatch, TestValue } from '../types';

export function indentNestingLevel(nestingLevel: number) {
return ` ${' '.repeat(nestingLevel)}`;
}

function valueToPrettyString(message: NullableTestValue): string {
function valueToPrettyString(message: TestValue): string {
if (message === undefined) {
return 'undefined';
} else if (message === null) {
Expand All @@ -25,7 +25,7 @@ function valueToPrettyString(message: NullableTestValue): string {
}
}

function adjustValueToLength(value: NullableTestValue, length: number) {
function adjustValueToLength(value: TestValue, length: number) {
const valueStr = valueToPrettyString(value);

const messageLen = valueStr.length;
Expand All @@ -37,10 +37,7 @@ function adjustValueToLength(value: NullableTestValue, length: number) {
}
}

export function color(
value: NullableTestValue,
color: 'cyan' | 'gray' | 'green' | 'yellow' | 'red' | 'lightGray' | 'orange',
) {
export function color(value: TestValue, color: 'cyan' | 'gray' | 'green' | 'yellow' | 'red' | 'lightGray' | 'orange') {
const COLOR_CODES = {
cyan: '\x1b[36m',
gray: '\x1b[38;5;242m',
Expand All @@ -55,22 +52,22 @@ export function color(
return `${COLOR_CODES[color]}${stringValue}${COLOR_CODES.reset}`;
}

export function cyan(x: NullableTestValue) {
export function cyan(x: TestValue) {
return color(x, 'cyan');
}
export function gray(x: NullableTestValue) {
export function gray(x: TestValue) {
return color(x, 'gray');
}
export function green(x: NullableTestValue) {
export function green(x: TestValue) {
return color(x, 'green');
}
export function yellow(x: NullableTestValue) {
export function yellow(x: TestValue) {
return color(x, 'yellow');
}
export function red(x: NullableTestValue) {
export function red(x: TestValue) {
return color(x, 'red');
}
export function orange(x: NullableTestValue) {
export function orange(x: TestValue) {
return color(x, 'orange');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,33 @@ function WarningComponent() {
}

describe('Tests of Test Framework', () => {
test('Test comparators', () => {
expect(1).toBe(1.0);
expect(2).not.toBe(1.0);

expect(1).not.toBe('1');
expect('1').toBe(1);

expect('cornflowerblue').not.toBe('#6495edff');
expect('cornflowerblue').toBe('#6495edff', ComparisonMode.COLOR);

expect({ backgroundColor: 'cornflowerblue' }).toBe({ backgroundColor: '#6495edff' });
expect({ width: 'cornflowerblue' }).not.toBe({ width: '#6495edff' });

expect(2).toBeWithinRange(1, 3);
expect(2).toBeWithinRange(1.99999999, 2.0000001);
expect(2).toBeWithinRange(2, 2);

expect(null).toBeNullable();
expect(undefined).toBeNullable();
expect([]).not.toBeNullable();
expect(0).not.toBeNullable();
});
test('Test comparators - expect error', () => {
expect(0).toBeNullable();
expect(2).not.toBeWithinRange(1.99999999, 2.0000001);
});

test('withTiming - expect error', async () => {
await render(<AnimatedComponent />);
const component = getTestComponent('BrownComponent');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@ import type { FlexStyle, ViewStyle } from 'react-native';
import { StyleSheet } from 'react-native';
import type { ComponentCoords } from 'react-native-reanimated';
import Animated, { runOnUI, measure, getRelativeCoords, useAnimatedRef, useSharedValue } from 'react-native-reanimated';
import {
describe,
test,
expect,
expectNotNullable,
render,
wait,
registerValue,
getRegisteredValue,
} from '../../ReJest/RuntimeTestsApi';
import { describe, test, expect, render, wait, registerValue, getRegisteredValue } from '../../ReJest/RuntimeTestsApi';

const REGISTERED_VALUE_KEY = 'sv';

Expand Down Expand Up @@ -68,7 +59,7 @@ describe('getRelativeCoords', () => {
await render(<CoordsComponent justifyContent={justifyContent} alignItems={alignItems} />);
await wait(300);
const coords = (await getRegisteredValue(REGISTERED_VALUE_KEY)).onUI;
expectNotNullable(coords);
expect(coords).not.toBeNullable();
if (coords) {
expect(Math.floor((coords as unknown as ComponentCoords).x)).toBe(expectedValueX);
expect(Math.floor((coords as unknown as ComponentCoords).y)).toBe(expectedValueY);
Expand Down