learning_ai_notes/mobile/__mocks__/@testing-library/react-native.tsx
saravanakumardb1 5a0175fa66 feat(mobile): add Block H — Vitest RN mock aliases + component smoke tests
- Create __mocks__/ with react-native, expo-router, expo-constants, expo-status-bar, react-native-mmkv, @testing-library/react-native
- Update vitest.config.ts with resolve aliases for all native modules
- Add AuthScreen smoke test (3 tests)
- Add HomeScreen smoke test (2 tests)
- Add @types/react-test-renderer dev dependency
- Total: 32 passing tests (27 store + 5 component)
2026-03-31 00:42:49 -07:00

79 lines
2.5 KiB
TypeScript

/**
* Lightweight @testing-library/react-native mock for Vitest.
* Uses react-test-renderer under the hood with simple query helpers.
*/
import React from 'react';
import renderer, { type ReactTestRendererJSON } from 'react-test-renderer';
function collectTexts(node: ReactTestRendererJSON | ReactTestRendererJSON[] | string | null): string[] {
if (node === null) return [];
if (typeof node === 'string') return [node];
if (Array.isArray(node)) return node.flatMap(collectTexts);
const texts: string[] = [];
if (node.children) {
for (const child of node.children) {
texts.push(...collectTexts(child));
}
}
return texts;
}
function collectNodes(node: ReactTestRendererJSON | ReactTestRendererJSON[] | null): ReactTestRendererJSON[] {
if (node === null) return [];
if (Array.isArray(node)) return node.flatMap(collectNodes);
const nodes: ReactTestRendererJSON[] = [node];
if (node.children) {
for (const child of node.children) {
if (typeof child !== 'string') {
nodes.push(...collectNodes(child));
}
}
}
return nodes;
}
let currentTree: ReturnType<typeof renderer.create> | null = null;
export function render(element: React.ReactElement) {
currentTree = renderer.create(element);
return { unmount: () => currentTree?.unmount() };
}
export const screen = {
getByText(text: string) {
const json = currentTree?.toJSON();
const allTexts = collectTexts(json ?? null);
const found = allTexts.find((t) => t.includes(text));
if (!found) throw new Error(`Unable to find text: "${text}"`);
return { type: 'Text', children: [found] };
},
getByPlaceholderText(placeholder: string) {
const json = currentTree?.toJSON();
const allNodes = collectNodes(json ?? null);
const found = allNodes.find(
(n) => n.props?.placeholder === placeholder || n.props?.placeholderTextColor != null && n.props?.placeholder === placeholder,
);
if (!found) throw new Error(`Unable to find placeholder: "${placeholder}"`);
return found;
},
queryByText(text: string) {
try {
return screen.getByText(text);
} catch {
return null;
}
},
};
export function fireEvent(element: ReactTestRendererJSON, event: string, ...args: unknown[]) {
const handler = element.props?.[`on${event.charAt(0).toUpperCase()}${event.slice(1)}`];
if (typeof handler === 'function') handler(...args);
}
fireEvent.press = (element: ReactTestRendererJSON) => fireEvent(element, 'press');
fireEvent.changeText = (element: ReactTestRendererJSON, text: string) => fireEvent(element, 'changeText', text);