duongdev / phosphor-react-native

phosphor-icons for react-native. A flexible icon family for React Native
https://www.npmjs.com/package/phosphor-react-native
MIT License
174 stars 21 forks source link

Error jest unit testing need help #46

Closed rodrigodiasf1984 closed 5 months ago

rodrigodiasf1984 commented 5 months ago

all my tests where i'm using the icons from phosphor-react-native I'm getting this the error: image

this is my component:

import { useState } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';

type AccordionItemProps = {
  children: React.ReactNode;
  title: string;
  testID?: string;
};

function AccordionItem({ children, title, testID }: AccordionItemProps) {
  const [expanded, setExpanded] = useState(false);

  function toggleItem() {
    setExpanded(!expanded);
  }

  const body = (
    <View
      testID="body"
      className="w-[88%] py-2 self-center border-r-[0.5px] border-r-shape_gray border-l-[0.5px] border-l-shape_gray border-b-[0.5px] border-b-shape_gray rounded-b-lg"
    >
      {children}
    </View>
  );

  return (
    <View className="pb-2" testID={testID}>
      <TouchableOpacity
        testID="accordion-item-button"
        activeOpacity={0.7}
        className="p-4 bg-white flex-row justify-between border-[0.5px] border-shape_gray rounded-lg w-[90%] self-center"
        onPress={() => toggleItem()}
      >
        <Text className="text-base font-rubik_medium text-shape_gray">
          {title}
        </Text>
        {expanded ? (
          <View testID="icon_up">
            <CaretUp size={20} />
          </View>
        ) : (
          <View testID="icon_down">
            <CaretDown size={20} />
          </View>
        )}
      </TouchableOpacity>
      {expanded && body}
    </View>
  );
}

export default AccordionItem;

these are my tests:

import { fireEvent, render } from '@testing-library/react-native';
import { View } from 'react-native';
import AccordionItem from '..';

describe('AccordionItem', () => {
  it('renders without crashing', () => {
    const { getByTestId } = render(
      <AccordionItem title="Test Title" testID="accordion-item">
        <View />
      </AccordionItem>,
    );
    const accordionItem = getByTestId('accordion-item');
    expect(accordionItem).toBeTruthy();
  });

  it('toggles item when the button is pressed', () => {
    const { getByTestId } = render(
      <AccordionItem title="Test Title" testID="accordion-item">
        <View />
      </AccordionItem>,
    );

    const button = getByTestId('accordion-item-button');
    fireEvent.press(button);

    const body = getByTestId('body');
    expect(body).toBeTruthy();
  });

  it('renders the up icon when expanded is true', () => {
    const { getByTestId } = render(
      <AccordionItem title="Test Title" testID="accordion-item">
        <View />
      </AccordionItem>,
    );

    const button = getByTestId('accordion-item-button');
    fireEvent.press(button);
    const upIcon = getByTestId('icon_up');
    expect(upIcon).toBeTruthy();
  });

  it('renders the down icon when expanded is false', () => {
    const { getByTestId } = render(
      <AccordionItem title="Test Title" testID="accordion-item">
        <View />
      </AccordionItem>,
    );

    const downIcon = getByTestId('icon_down');

    expect(downIcon).toBeTruthy();
  });
});

how can I fix it ? Thanks

rodrigodiasf1984 commented 5 months ago

@duongdev any update on this? Thanks!

ConnorHome commented 5 months ago

@rodrigodiasf1984 You can mock the icon to get around this.

jest.mock('phosphor-react-native', () => ({
  CaretDown () => <div />,
}))
rodrigodiasf1984 commented 5 months ago

@rodrigodiasf1984 You can mock the icon to get around this.

jest.mock('phosphor-react-native', () => ({
  CaretDown () => <div />,
}))

Hi @ConnorHome, thanks for your answer I'll give it a try, it isn't enjoyable to make this for all the icons I have been using in the app.

rodrigodiasf1984 commented 5 months ago

@ConnorHome now I'm getting this error:


function CaretDown() {
  return <View />;
}

jest.mock('phosphor-react-native', () => ({
  CaretDown,
}));

'
 FAIL  src/components/AccordionItem/__tests__/AccordionItem.test.tsx
  ● Test suite failed to run

    ReferenceError: /Users/rodrigodiasdefigueiredo/Desktop/TheBasement/zerel-parksharing-mobile/src/components/AccordionItem/__tests__/AccordionItem.test.tsx: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: CaretDown
    Allowed objects: AbortController, AbortSignal, AggregateError, Array, ArrayBuffer, Atomics, BigInt, BigInt64Array, BigUint64Array, Blob, Boolean, BroadcastChannel, Buffer, ByteLengthQueuingStrategy, CompressionStream, CountQueuingStrategy, DOMException, DataView, Date, DecompressionStream, Error, EvalError, Event, EventTarget, FinalizationRegistry, Float32Array, Float64Array, FormData, Function, Generator, GeneratorFunction, Headers, Infinity, Int16Array, Int32Array, Int8Array, InternalError, Intl, JSON, Map, Math, MessageChannel, MessageEvent, MessagePort, NaN, Number, Object, Performance, Promise, Proxy, RangeError, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, ReferenceError, Reflect, RegExp, Request, Response, Set, SharedArrayBuffer, String, Symbol, SyntaxError, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStream, TransformStreamDefaultController, TypeError, URIError, URL, URLSearchParams, Uint16Array, Uint32Array, Uint8Array, Uint8ClampedArray, WeakMap, WeakRef, WeakSet, WebAssembly, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter, __dirname, __filename, arguments, atob, btoa, clearImmediate, clearInterval, clearTimeout, console, decodeURI, decodeURIComponent, encodeURI, encodeURIComponent, escape, eval, expect, exports, fetch, global, globalThis, isFinite, isNaN, jest, module, parseFloat, parseInt, performance, process, queueMicrotask, require, setImmediate, setInterval, setTimeout, structuredClone, undefined, unescape.
    Note: This is a precaution to guard against uninitialized mock variables. If it is ensured that the mock is required lazily, variable names prefixed with `mock` (case insensitive) are permitted.

       9 |
      10 | jest.mock('phosphor-react-native', () => ({
    > 11 |   CaretDown,
         |   ^^^^^^^^^
      12 | }));
      13 | describe('AccordionItem', () => {
      14 |   it('renders without crashing', () => {

      at File.buildCodeFrameError (node_modules/@babel/core/src/transformation/file/file.ts:279:12)
      at NodePath.buildError [as buildCodeFrameError] (node_modules/@babel/traverse/src/path/index.ts:136:21)
      at call (node_modules/@babel/traverse/src/visitors.ts:293:14)
      at NodePath.call [as _call] (node_modules/@babel/traverse/src/path/context.ts:35:20)
      at NodePath._call [as call] (node_modules/@babel/traverse/src/path/context.ts:20:17)
      at NodePath.call [as visit] (node_modules/@babel/traverse/src/path/context.ts:94:31)
      at TraversalContext.visit [as visitQueue] (node_modules/@babel/traverse/src/context.ts:144:16)
      at TraversalContext.visitQueue [as visitMultiple] (node_modules/@babel/traverse/src/context.ts:98:17)
      at TraversalContext.visitMultiple [as visit] (node_modules/@babel/traverse/src/context.ts:174:19)
      at visit (node_modules/@babel/traverse/src/traverse-node.ts:40:17)
      at NodePath.visit (node_modules/@babel/traverse/src/path/context.ts:101:33)
      at TraversalContext.visit [as visitQueue] (node_modules/@babel/traverse/src/context.ts:144:16)
      at TraversalContext.visitQueue [as visitSingle] (node_modules/@babel/traverse/src/context.ts:108:19)
      at TraversalContext.visitSingle [as visit] (node_modules/@babel/traverse/src/context.ts:176:19)
      at visit (node_modules/@babel/traverse/src/traverse-node.ts:40:17)
      at traverse (node_modules/@babel/traverse/src/index.ts:82:15)
      at transformFile (node_modules/@babel/core/src/transformation/index.ts:124:15)
          at transformFile.next (<anonymous>)
      at transformFile (node_modules/@babel/core/src/transformation/index.ts:48:12)
          at run.next (<anonymous>)
      at transform (node_modules/@babel/core/src/transform.ts:29:20)
          at transform.next (<anonymous>)
      at evaluateSync (node_modules/gensync/index.js:251:28)
      at sync (node_modules/gensync/index.js:89:14)
      at fn (node_modules/@babel/core/src/errors/rewrite-stack-trace.ts:99:14)
      at transformSync (node_modules/@babel/core/src/transform.ts:66:52)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:545:31)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:674:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:726:19)
rodrigodiasf1984 commented 5 months ago

Just solve it, it must be mocked like this:


function MockCaretDown() {
  return <View />;
}

function MockCaretUp() {
  return <View />;
}

jest.mock('phosphor-react-native', () => ({
  CaretDown: () => <MockCaretDown />,
  CaretUp: () => <MockCaretUp />,
}));
asdolo commented 3 months ago

For anyone wanting to mock all icons at once, without having to repeat code, just use a Proxy object to force returning the Mock function for anything exported by phosphor-react-native:

const MockPhosphorIcon = () => <View />;

jest.mock('phosphor-react-native', () => new Proxy({}, { get: () => MockPhosphorIcon }));

cc @rodrigodiasf1984

thenriquedb commented 1 month ago

For anyone wanting to mock all icons at once, without having to repeat code, just use a Proxy object to force returning the Mock function for anything exported by phosphor-react-native:

const MockPhosphorIcon = () => <View />;

jest.mock('phosphor-react-native', () => new Proxy({}, { get: () => MockPhosphorIcon }));

cc @rodrigodiasf1984

I tried and it didn't work, I still get the same error

rodrigodiasf1984 commented 1 month ago

hey guys, i've add this into my jest.setup

jest.mock('phosphor-react-native', () => ({ CheckCircle: () => <MockIcon />, AlertCircle: () => <MockIcon />, Info: () => <MockIcon />, WarningCircle: () => <MockIcon />, CaretDown: () => <MockIcon />, Clock: () => <MockIcon />, MagnifyingGlass: () => <MockIcon />, WarningCircle: () => <MockIcon />, CaretDown: () => <MockIcon />, CaretUp: () => <MockIcon />, Check: () => <MockIcon />, Trash: () => <MockIcon />, X: () => <MockIcon />, MapPin: () => <MockIcon />, Star: () => <MockIcon />, HouseLine: () => <MockIcon />, Briefcase: () => <MockIcon />, Eye: () => <MockIcon />, CaretLeft: () => <MockIcon />, UserCirclePlus: () => <MockIcon />, Crosshair: () => <MockIcon />, XCircle: () => <MockIcon />, WifiSlash: () => <MockIcon />, Heart: () => <MockIcon />, Camera: () => <MockIcon />, ImageSquare: () => <MockIcon />, CurrencyEur: () => <MockIcon />, PencilLine: () => <MockIcon />, LockOpen: () => <MockIcon />, Bell: () => <MockIcon />, Broadcast: () => <MockIcon />, Car: () => <MockIcon />, DeviceMobileCamera: () => <MockIcon />, HandPalm: () => <MockIcon />, NotePencil: () => <MockIcon />, Receipt: () => <MockIcon />, SignOut: () => <MockIcon />, User: () => <MockIcon />, Warning: () => <MockIcon />, BellSlash: () => <MockIcon />, TrafficSign: () => <MockIcon />, Garage: () => <MockIcon />, DotsNine: () => <MockIcon />, Buildings: () => <MockIcon />, ShareFat: () => <MockIcon />, PlusCircle: () => <MockIcon />, MinusCircle: () => <MockIcon />, PaperPlaneRight: () => <MockIcon />, ThumbsUp: () => <MockIcon />, Van: () => <MockIcon />, Motorcycle: () => <MockIcon />, List: () => <MockIcon />, CarProfile: () => <MockIcon />, IdentificationCard: () => <MockIcon />, Wallet: () => <MockIcon />, PhoneCall: () => <MockIcon />, Factory: () => <MockIcon />, })); and when i added a new icon to my code i must to update this code. Hope this helps.