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
2 changes: 2 additions & 0 deletions .changeset/rude-pears-open.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
4 changes: 4 additions & 0 deletions .cspell/contributors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Zhiyuan
ZhiyuanHong
HongZhiyuan

Yiming
YimingLi
LiYiming

# Webpack Contributors
Koppers
sokra
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,15 @@ jobs:
npx --registry http://localhost:4873 create-rspeedy-canary@latest --template react --dir create-rspeedy-regression
cd create-rspeedy-regression
pnpm install --registry=http://localhost:4873
pnpm tsc --noEmit
pnpm run build
pnpm tsc --noEmit
npx --registry http://localhost:4873 create-rspeedy-canary@latest --template react-vitest-rltl --dir create-rspeedy-regression-vitest-rltl
cd create-rspeedy-regression-vitest-rltl
pnpm install --registry=http://localhost:4873
pnpm tsc --noEmit
pnpm run build
pnpm tsc --noEmit
pnpm run test
test-tools:
needs: build
Expand Down
3 changes: 0 additions & 3 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,8 @@
"preact": "npm:@hongzhiyuan/preact@10.24.0-319c684e"
},
"devDependencies": {
"@lynx-js/test-environment": "workspace:*",
"@lynx-js/types": "^3.2.1",
"@microsoft/api-extractor": "catalog:",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@types/react": "^18.3.20"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/testing-library/api-extractor.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "../../../api-extractor.json",
"mainEntryPointFilePath": "<projectFolder>/types/index.d.ts",
"mainEntryPointFilePath": "<projectFolder>/types/entry.d.ts",
"compiler": {
"overrideTsconfig": {
"compilerOptions": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@
import { BoundFunction } from '@testing-library/dom';
import { ComponentChild } from 'preact';
import { ComponentType } from 'preact';
import { ElementTree } from '@lynx-js/test-environment';
import { LynxElement } from '@lynx-js/test-environment';
import { LynxEnv } from '@lynx-js/test-environment';
import { Queries } from '@testing-library/dom';
import { queries } from '@testing-library/dom';

// @public
export function cleanup(): void;

export { ElementTree }

export { LynxEnv }

// @public
export function render<Q extends Queries>(
ui: ComponentChild,
Expand Down
5 changes: 4 additions & 1 deletion packages/react/testing-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"test:ui": "vitest --ui"
},
"devDependencies": {
"@lynx-js/react": "workspace:*"
"@lynx-js/react": "workspace:*",
"@lynx-js/test-environment": "workspace:*",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3"
}
}
11 changes: 11 additions & 0 deletions packages/react/testing-library/rslib.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ export default defineConfig({
],
},
},
{
format: 'esm',
dts: {
bundle: true,
},
source: {
entry: {
'index': './src/entry.ts',
},
},
},
],
tools: {
rspack(config) {
Expand Down
2 changes: 2 additions & 0 deletions packages/react/testing-library/src/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore
export type * from '../../../types/entry.d.ts';
257 changes: 257 additions & 0 deletions packages/react/testing-library/types/entry.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/**
* @packageDocumentation
*
* ReactLynx Testing Library is a simple and complete ReactLynx
* unit testing library that encourages good testing practices.
*
* Inspired by {@link https://testing-library.com/docs/react-testing-library/intro | React Testing Library} and {@link https://github.com/jsdom/jsdom | jsdom}.
*/

import { queries, Queries, BoundFunction } from '@testing-library/dom';
import { LynxElement, type ElementTree, type LynxEnv } from '@lynx-js/test-environment';
import { ComponentChild, ComponentType } from 'preact';
export * from '@testing-library/dom';
export { ElementTree, LynxEnv };

/**
* The options for {@link render}.
*
* @public
*/
export interface RenderOptions<Q extends Queries = typeof queries> {
/**
* Queries to bind. Overrides the default set from DOM Testing Library unless merged.
*
* @example
*
* ```ts
* // Example, a function to traverse table contents
* import * as tableQueries from 'my-table-query-library'
* import { queries } from '@lynx-js/react/testing-library'
*
* const { getByRowColumn, getByText } = render(<MyTable />, {
* queries: {...queries, ...tableQueries},
* })
*
* ```
*/
queries?: Q;
/**
* Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating
* reusable custom render functions for common data providers. See setup for examples.
*
* @example
*
* ```ts
* import { render } from '@lynx-js/react/testing-library'
* import { ThemeProvider } from 'my-ui-lib'
* import { TranslationProvider } from 'my-i18n-lib'
* import defaultStrings from 'i18n/en-x-default'
*
* const AllTheProviders = ({children}) => {
* return (
* <ThemeProvider theme="light">
* <TranslationProvider messages={defaultStrings}>
* {children}
* </TranslationProvider>
* </ThemeProvider>
* )
* }
*
* const customRender = (ui, options) =>
* render(ui, { wrapper: AllTheProviders, ...options })
*
* // re-export everything
* export * from '@lynx-js/react/testing-library'
*
* // override render method
* export { customRender as render }
* ```
*/
wrapper?: ComponentChild;
/**
* Render your component in the main thread or not.
*
* It is recommended to use this option only when you need to test the {@link https://lynxjs.org/zh/guide/interaction/ifr.html | IFR} behavior.
*
* @defaultValue false
*/
enableMainThread?: boolean;
/**
* Render your component in the background thread or not.
*
* Note that all user code in the top level will be executed in the background thread by default. (eg. `__BACKGROUND__` is `true` in the top level)
*
* @defaultValue true
*/
enableBackgroundThread?: boolean;
}

/**
* The result of {@link render}
*
* @public
*/
export type RenderResult<Q extends Queries = typeof queries> = {
container: LynxElement;
rerender: (ui: ComponentChild) => void;
unmount: () => boolean;
} & { [P in keyof Q]: BoundFunction<Q[P]> };

/**
* Render into the page. It should be used with cleanup.
*
* @example
*
* ```ts
* import { render} from '@lynx-js/react/testing-library'
*
* const WrapperComponent = ({ children }) => (
* <view data-testid='wrapper'>{children}</view>
* );
* const Comp = () => {
* return <view data-testid='inner' style="background-color: yellow;" />;
* };
* const { container, getByTestId } = render(<Comp />, {
* wrapper: WrapperComponent,
* });
* expect(getByTestId('wrapper')).toBeInTheDocument();
* expect(container.firstChild).toMatchInlineSnapshot(`
* <view
* data-testid="wrapper"
* >
* <view
* data-testid="inner"
* style="background-color: yellow;"
* />
* </view>
* `);
* ```
*
* @public
*/
export function render<Q extends Queries>(
ui: ComponentChild,
options?: RenderOptions<Q>,
): RenderResult<Q>;
/**
* Cleanup elements rendered to the page and Preact trees that were mounted with render.
*
* @public
*/
export function cleanup(): void;

/**
* The result of {@link renderHook}
*
* @public
*/

export interface RenderHookResult<Result, Props> {
/**
* Triggers a re-render. The props will be passed to your renderHook callback.
*/
rerender: (props?: Props) => void;
/**
* This is a stable reference to the latest value returned by your renderHook
* callback
*/
result: {
/**
* The value returned by your renderHook callback
*/
current: Result;
};
/**
* Unmounts the test component. This is useful for when you need to test
* any cleanup your useEffects have.
*/
unmount: () => void;
}

/**
* The options for {@link renderHook}
*
* @public
*/
export interface RenderHookOptions<Props> {
/**
* The argument passed to the renderHook callback. Can be useful if you plan
* to use the rerender utility to change the values passed to your hook.
*/
initialProps?: Props;
/**
* Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating
* reusable custom render functions for common data providers. See setup for examples.
*
* @example
*
* ```ts
* import { renderHook } from '@lynx-js/react/testing-library'
* import { ThemeProvider } from 'my-ui-lib'
* import { TranslationProvider } from 'my-i18n-lib'
* import defaultStrings from 'i18n/en-x-default'
*
* const AllTheProviders = ({children}) => {
* return (
* <ThemeProvider theme="light">
* <TranslationProvider messages={defaultStrings}>
* {children}
* </TranslationProvider>
* </ThemeProvider>
* )
* }
*
* const customRenderHook = (ui, options) =>
* renderHook(ui, { wrapper: AllTheProviders, ...options })
*
* // re-export everything
* export * from '@lynx-js/react/testing-library'
*
* // override renderHook method
* export { customRender as renderHook }
* ```
*/
wrapper?: ComponentType<{ children: LynxElement }>;
}

/**
* Allows you to render a hook within a test React component without having to
* create that component yourself.
*
* @example
*
* ```ts
* import { renderHook } from '@lynx-js/react/testing-library'
*
* const Context = createContext('default');
* function Wrapper({ children }) {
* return <Context.Provider value='provided'>{children}</Context.Provider>;
* }
* const { result } = renderHook(
* () => {
* return useContext(Context);
* },
* {
* wrapper: Wrapper,
* },
* );
*
* expect(result.current).toEqual('provided');
* ```
*
* @public
*/
export function renderHook<Result, Props>(
render: (initialProps: Props) => Result,
options?: RenderHookOptions<Props>,
): RenderHookResult<Result, Props>;

/**
* Wait for the next event loop.
*
* It will be useful when you want to wait for the next event loop to finish.
*
* @public
*/
export function waitSchedule(): Promise<void>;
Loading
Loading