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

Fix eslint rules and types of tests #6103

Merged
merged 7 commits into from
Jun 14, 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
9 changes: 9 additions & 0 deletions apps/common-app/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ module.exports = {
'reanimated/animated-style-non-animated-component': 'error',
'react/jsx-fragments': ['error', 'syntax'],
},
overrides: [
{
files: ['./src/examples/RuntimeTests/tests/**'],
rules: {
'no-template-curly-in-string': 'off',
'no-inline-styles/no-inline-styles': 'off',
},
},
],
};
Original file line number Diff line number Diff line change
@@ -1,96 +1,82 @@
import { Component, ReactElement } from 'react';
import type { Component, ReactElement } from 'react';
import { TestRunner } from './TestRunner';
import { TestComponent } from './TestComponent';
import type { TestComponent } from './TestComponent';
import type { SharedValue } from 'react-native-reanimated';
import { TestConfiguration, TestValue, NullableTestValue, DescribeDecorator, TestDecorator } from './types';
import type { TestConfiguration, TestValue, NullableTestValue, BuildFunction } from './types';
import { DescribeDecorator, TestDecorator } from './types';

export { Presets } from './Presets';

const testRunner = new TestRunner();

type DescribeFunction = (name: string, buildSuite: () => void) => void;
export const describe: {
(name: string, buildSuite: () => void): void;
skip: DescribeFunction;
only: DescribeFunction;
} = Object.assign(
(name: string, buildSuite: () => void) => {
testRunner.describe(name, buildSuite, null);
},
{
skip: (name: string, buildSuite: () => void) => {
testRunner.describe(name, buildSuite, DescribeDecorator.SKIP);
},
only: (name: string, buildSuite: () => void) => {
testRunner.describe(name, buildSuite, DescribeDecorator.ONLY);
},
},
);

type DescribeFunction = (name: string, buildSuite: BuildFunction) => void;
type TestFunction = (name: string, buildTest: BuildFunction) => void;
type TestFunctionWithWarning = (name: string, warningMessage: string, buildTest: BuildFunction) => void;
type TestEachFunction = <T>(
examples: Array<T>,
) => (name: string, testCase: (example: T, index?: number) => void) => void;
) => (name: string, testCase: (example: T, index?: number) => void | Promise<void>) => void;
type TestEachFunctionWithWarning = <T>(
examples: Array<T>,
) => (name: string, expectedWarning: string, testCase: (example: T, index?: number) => void) => void;

export const test: {
(name: string, testCase: () => void): void;
each: TestEachFunction;
skip: { (name: string, testCase: () => void): void; each: TestEachFunction };
only: { (name: string, testCase: () => void): void; each: TestEachFunction };
failing: { (name: string, warningMessage: string, testCase: () => void): void; each: TestEachFunctionWithWarning };
warn: { (name: string, warningMessage: string, testCase: () => void): void; each: TestEachFunctionWithWarning };
} = Object.assign(
(name: string, testCase: () => void) => {
testRunner.test(name, testCase, null);
},
{
each: <T>(examples: Array<T>) => {
return testRunner.testEach(examples, null);
},
skip: Object.assign(
(name: string, testCase: () => void) => {
testRunner.test(name, testCase, TestDecorator.SKIP);
},
{
each: <T>(examples: Array<T>) => {
return testRunner.testEach(examples, TestDecorator.SKIP);
},
},
),
only: Object.assign(
(name: string, testCase: () => void) => {
testRunner.test(name, testCase, TestDecorator.ONLY);
},
{
each: <T>(examples: Array<T>) => {
return testRunner.testEach(examples, TestDecorator.ONLY);
},
},
),
failing: Object.assign(
(name: string, expectedWarning: string, testCase: () => void) => {
testRunner.test(name, testCase, TestDecorator.FAILING, expectedWarning);
},
{
each: <T>(examples: Array<T>) => {
return testRunner.testEachErrorMsg(examples, TestDecorator.FAILING);
},
},
),
warn: Object.assign(
(name: string, expectedWarning: string, testCase: () => void) => {
testRunner.test(name, testCase, TestDecorator.WARN, expectedWarning);
},
{
each: <T>(examples: Array<T>) => {
return testRunner.testEachErrorMsg(examples, TestDecorator.WARN);
},
},
),
},
);
) => (name: string, expectedWarning: string, testCase: (example: T, index?: number) => void | Promise<void>) => void;
type DecoratedTestFunction = TestFunction & { each: TestEachFunction };
type DecoratedTestFunctionWithWarning = TestFunctionWithWarning & { each: TestEachFunctionWithWarning };

const describeBasic = (name: string, buildSuite: BuildFunction) => {
testRunner.describe(name, buildSuite, null);
};

export const describe = <DescribeFunction & Record<DescribeDecorator, DescribeFunction>>describeBasic;
describe.skip = (name, buildSuite) => {
testRunner.describe(name, buildSuite, DescribeDecorator.SKIP);
};
describe.only = (name, buildSuite) => {
testRunner.describe(name, buildSuite, DescribeDecorator.ONLY);
};

const testBasic: DecoratedTestFunction = (name: string, testCase: BuildFunction) => {
testRunner.test(name, testCase, null);
};
testBasic.each = <T>(examples: Array<T>) => {
return testRunner.testEach(examples, null);
};
const testSkip: DecoratedTestFunction = (name: string, testCase: BuildFunction) => {
testRunner.test(name, testCase, TestDecorator.SKIP);
};
testSkip.each = <T>(examples: Array<T>) => {
return testRunner.testEach(examples, TestDecorator.SKIP);
};
const testOnly: DecoratedTestFunction = (name: string, testCase: BuildFunction) => {
testRunner.test(name, testCase, TestDecorator.ONLY);
};
testOnly.each = <T>(examples: Array<T>) => {
return testRunner.testEach(examples, TestDecorator.ONLY);
};
const testFailing: DecoratedTestFunctionWithWarning = (
name: string,
expectedWarning: string,
testCase: BuildFunction,
) => {
testRunner.test(name, testCase, TestDecorator.FAILING, expectedWarning);
};
testFailing.each = <T>(examples: Array<T>) => {
return testRunner.testEachErrorMsg(examples, TestDecorator.FAILING);
};
const testWarn: DecoratedTestFunctionWithWarning = (name: string, expectedWarning: string, testCase: BuildFunction) => {
testRunner.test(name, testCase, TestDecorator.WARN, expectedWarning);
};
testWarn.each = <T>(examples: Array<T>) => {
return testRunner.testEachErrorMsg(examples, TestDecorator.WARN);
};

type TestType = DecoratedTestFunction &
Record<TestDecorator.SKIP | TestDecorator.ONLY, DecoratedTestFunction> &
Record<TestDecorator.FAILING | TestDecorator.WARN, DecoratedTestFunctionWithWarning>;

export const test = <TestType>testBasic;
test.skip = testSkip;
test.only = testOnly;
test.failing = testFailing;
test.warn = testWarn;

export function beforeAll(job: () => void) {
testRunner.beforeAll(job);
Expand Down Expand Up @@ -120,6 +106,7 @@ export function useTestRef(name: string) {
return testRunner.useTestRef(name);
}

// eslint-disable-next-line @typescript-eslint/unbound-method
Latropos marked this conversation as resolved.
Show resolved Hide resolved
const testRunnerCallTrackerFn = testRunner.callTracker;
export function callTracker(name: string) {
'worklet';
Expand Down Expand Up @@ -158,8 +145,9 @@ export async function wait(delay: number) {
return testRunner.wait(delay);
}

// eslint-disable-next-line @typescript-eslint/unbound-method
Latropos marked this conversation as resolved.
Show resolved Hide resolved
const testRunnerNotifyFn = testRunner.notify;
export async function notify(name: string) {
export function notify(name: string) {
'worklet';
return testRunnerNotifyFn(name);
}
Expand Down Expand Up @@ -209,5 +197,5 @@ export async function recordAnimationUpdates() {
}

export async function stopRecordingAnimationUpdates() {
testRunner.stopRecordingAnimationUpdates();
await testRunner.stopRecordingAnimationUpdates();
Latropos marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { Component, MutableRefObject, ReactElement, useRef } from 'react';
import {
type NullableTestValue,
type LockObject,
type Operation,
type SharedValueSnapshot,
type TestCase,
type TestConfiguration,
type TestSuite,
type TestSummary,
type TestValue,
type TrackerCallCount,
ComparisonMode,
DescribeDecorator,
TestDecorator,
import type { Component, MutableRefObject, ReactElement } from 'react';
import { useRef } from 'react';
import type {
BuildFunction,
NullableTestValue,
LockObject,
Operation,
SharedValueSnapshot,
TestCase,
TestConfiguration,
TestSuite,
TestSummary,
TestValue,
TrackerCallCount,
} from './types';
import { ComparisonMode, DescribeDecorator, TestDecorator } from './types';
import { TestComponent } from './TestComponent';
import { getTrackerCallCount, render, stopRecordingAnimationUpdates, unmockAnimationTimer } from './RuntimeTestsApi';
import { makeMutable, runOnUI, runOnJS, SharedValue } from 'react-native-reanimated';
import type { SharedValue } from 'react-native-reanimated';
import { makeMutable, runOnUI, runOnJS } from 'react-native-reanimated';
import { applyMarkdown, color, formatString, indentNestingLevel } from './stringFormatUtils';
import { createUpdatesContainer } from './UpdatesContainer';
import { Matchers, nullableMatch } from './Matchers';
Expand Down Expand Up @@ -101,7 +102,7 @@ export class TestRunner {
return await this.render(null);
}

public describe(name: string, buildSuite: () => void, decorator: DescribeDecorator | null) {
public describe(name: string, buildSuite: BuildFunction, decorator: DescribeDecorator | null) {
if (decorator === DescribeDecorator.ONLY) {
this._includesOnly = true;
}
Expand All @@ -127,11 +128,12 @@ export class TestRunner {
buildSuite,
testCases: [],
nestingLevel: (this._currentTestSuite?.nestingLevel || 0) + 1,
// eslint-disable-next-line no-unneeded-ternary
Latropos marked this conversation as resolved.
Show resolved Hide resolved
decorator: decorator ? decorator : this._currentTestSuite?.decorator ? this._currentTestSuite?.decorator : null,
});
}

public test(name: string, run: () => void, decorator: TestDecorator | null, warningMessage = '') {
public test(name: string, run: BuildFunction, decorator: TestDecorator | null, warningMessage = '') {
assertTestSuite(this._currentTestSuite);
if (decorator === TestDecorator.ONLY) {
this._includesOnly = true;
Expand All @@ -145,7 +147,7 @@ export class TestRunner {
callsRegistry: {},
errors: [],
decorator,
warningMessage: warningMessage,
warningMessage,
skip: false,
}
: {
Expand All @@ -161,7 +163,7 @@ export class TestRunner {
}

public testEachErrorMsg<T>(examples: Array<T>, decorator: TestDecorator) {
return (name: string, expectedWarning: string, testCase: (example: T) => void) => {
return (name: string, expectedWarning: string, testCase: (example: T) => void | Promise<void>) => {
examples.forEach((example, index) => {
const currentTestCase = async () => {
await testCase(example);
Expand All @@ -175,8 +177,9 @@ export class TestRunner {
});
};
}

public testEach<T>(examples: Array<T>, decorator: TestDecorator | null) {
return (name: string, testCase: (example: T, index?: number) => void) => {
return (name: string, testCase: (example: T, index?: number) => void | Promise<void>) => {
examples.forEach((example, index) => {
const currentTestCase = async () => {
await testCase(example, index);
Expand Down Expand Up @@ -260,7 +263,9 @@ export class TestRunner {
for (const testCase of testSuite.testCases) {
if (testCase.decorator === TestDecorator.ONLY) {
skipTestSuite = false;
} else testCase.skip = testCase.skip || !(testSuite.decorator === DescribeDecorator.ONLY);
} else {
testCase.skip = testCase.skip || !(testSuite.decorator === DescribeDecorator.ONLY);
}
}
}
testSuite.skip = skipTestSuite;
Expand Down Expand Up @@ -323,6 +328,7 @@ export class TestRunner {
console.error = newConsoleFuncJS;
console.warn = newConsoleFuncJS;

// eslint-disable-next-line @typescript-eslint/unbound-method
Latropos marked this conversation as resolved.
Show resolved Hide resolved
const callTrackerCopy = this.callTracker;

runOnUI(() => {
Expand Down Expand Up @@ -500,12 +506,13 @@ export class TestRunner {
return global.mockedAnimationTimestamp;
};

let originalRequestAnimationFrame = global.requestAnimationFrame;
const originalRequestAnimationFrame = global.requestAnimationFrame;
global.originalRequestAnimationFrame = originalRequestAnimationFrame;
(global as any).requestAnimationFrame = (callback: Function) => {
global.requestAnimationFrame = (callback: (time: number) => void) => {
originalRequestAnimationFrame(() => {
callback(global._getAnimationTimestamp());
});
return 0;
};

global.originalFlushAnimationFrame = global.__flushAnimationFrame;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Dispatch, MutableRefObject, ReactNode, SetStateAction } from 'react';
import { AnimatedStyle, StyleProps } from 'react-native-reanimated';
import type { Component, Dispatch, MutableRefObject, ReactNode, SetStateAction } from 'react';
import type { AnimatedStyle, StyleProps } from 'react-native-reanimated';

export type CallTracker = {
UICallsCount: number;
Expand All @@ -25,22 +25,22 @@ export type SharedValueSnapshot = {
export type ComponentRef = MutableRefObject<(Component & { props: { style: Record<string, unknown> } }) | null>;

export enum DescribeDecorator {
ONLY = 'ONLY',
SKIP = 'SKIP',
NONE = 'NONE',
ONLY = 'only',
SKIP = 'skip',
Latropos marked this conversation as resolved.
Show resolved Hide resolved
}

export enum TestDecorator {
ONLY = 'ONLY',
SKIP = 'SKIP',
FAILING = 'FAILING',
WARN = 'WARN',
NONE = 'NONE',
ONLY = 'only',
SKIP = 'skip',
FAILING = 'failing',
WARN = 'warn',
}

export type BuildFunction = () => void | Promise<void>;

export type TestCase = {
name: string;
run: () => void | Promise<void>;
run: BuildFunction;
componentsRefs: Record<string, ComponentRef>;
callsRegistry: Record<string, CallTracker>;
errors: string[];
Expand All @@ -55,7 +55,7 @@ export type TestCase = {

export type TestSuite = {
name: string;
buildSuite: () => void;
buildSuite: BuildFunction;
testCases: TestCase[];
nestingLevel: number;
beforeAll?: () => void | Promise<void>;
Expand Down Expand Up @@ -104,6 +104,7 @@ export type TestConfiguration = {
render: Dispatch<SetStateAction<ReactNode | null>>;
};

/* eslint-disable no-var */
Latropos marked this conversation as resolved.
Show resolved Hide resolved
declare global {
var mockedAnimationTimestamp: number | undefined;
var originalRequestAnimationFrame: ((callback: (timestamp: number) => void) => void) | undefined;
Expand All @@ -123,6 +124,7 @@ declare global {
var _obtainPropFabric: (shadowNodeWrapper: unknown, propName: string) => string;
var __flushAnimationFrame: (frameTimestamp: number) => void;
}
/* eslint-enable no-var */

export type TestSummary = {
passed: number;
Expand Down
Loading