Home > Software engineering >  Cannot read property of undefined in react native flat list when using react testing library
Cannot read property of undefined in react native flat list when using react testing library

Time:01-05

I'm trying to create a simple snapshot test in react native using react-testing-library, but I can't figure out why I am getting "cannot read property 'lines' of undefined". The flatlist is rendering the data fine with no issues, but the test wont pass.

I've also tried destructuring out the summary.lines, but that didn't work either.

 ● Single Collection Screen Renders

    TypeError: Cannot read property 'lines' of undefined

      47 |         <FlatList
    > 48 |           data={summary.lines}
         |                     ^
      49 |           renderItem={renderCollectionOrderLines}
      50 |           keyExtractor={(_item, i) => i.toString()}
      51 |         />

Mock data.js:

export const useSingleOrdersMock = [
  {
    order_number: 'ABC/1234',
    date: '25/06/20',
    order_status: 'Processing',
    order_total: '£1000.25',
    delivery_address: {
      name: 'John Doe',
      short_name: 'Example Address',
      line_1: 'Example Street',
      line_2: 'United Kingdom',
      line_3: null,
      line_4: null,
      line_5: null,
      postcode: 'ABC 123',
    },
    invoice_address: {
      name: 'Steve Smith',
      short_name: 'Example Address',
      line_1: 'Example Street',
      line_2: 'United Kingdom',
      line_3: null,
      line_4: null,
      line_5: null,
      postcode: 'ABC 123',
    },
    summary: {
      subtotal: '£1100.25',
      delivery: 'Free',
      vat: '£100',
      lines: [
        {
          product_id: 123456,
          part_code: 'ABC1234',
          stock_code: '01234-5678',
          description: 'Combi Oven',
          quantity: 1,
          price_including_vat: '10.20',
          price_excluding_vat: '8.50',
          vat: '1.70',
        },
        {
          product_id: 678910,
          part_code: 'ABC1234',
          stock_code: '01234-5678',
          description: 'Combi Oven',
          quantity: 1,
          price_including_vat: '5.10',
          price_excluding_vat: '4.25',
          vat: '0.85',
        },
      ],
    },
  },
];

export const SingleCollectionScreenAccountContext = {
  selectedCollectionOrder: useSingleOrdersMock,
  setSelectedCollectionOrder: jest.fn(),
};

Test.js:

test('Single Collection Screen Renders', () => {
  let tree;
  act(() => {
    tree = renderer.create(
      <ScreenRenderer
        additionalAccountContext={SingleCollectionScreenAccountContext}>
        <SingleCollectionScreen />
      </ScreenRenderer>,
    );
  });
  expect(tree.toJSON()).toMatchSnapshot();
});

Component.js

import React from 'react';
import { ScrollView, FlatList } from 'react-native';
import Row from '../../components/Account/Row';
import { useAccountContext } from '../../providers/AccountProvider';

const SingleCollectionScreen = () => {
  const { selectedCollectionOrder } = useAccountContext();

  const {
    order_number,
    order_total,
    summary,
  } = selectedCollectionOrder;

  // const { lines } = summary
  
  const renderCollectionOrderLines = ({ item }) => {
    const {
      description,
      part_code,
      price_excluding_vat,
      quantity,
      stock_code,
    } = item;
    return (
      <SummaryLine
        itemName={description}
        catalogue={part_code}
        priceExVat={price_excluding_vat}
        quantity={quantity}
        stockCode={stock_code}
      />
    );
  };

  return (
    <ScrollView>
      <ScreenContainer>
        <FlatList
          data={summary.lines}   <-- error occurring here
          renderItem={renderCollectionOrderLines}
          keyExtractor={(_item, i) => i.toString()}
        />
        <Row title="Subtotal" value={summary.subtotal} />
        <Row title="Delivery" value={summary.delivery} />
        <Row title="VAT" value={summary.vat} />
        <Row title="Total" value={orderTotal} highlight />
      </ScreenContainer>
    </ScrollView>
  );
};

export default SingleCollectionScreen;

CodePudding user response:

It's because in the initial rendering summary.lines is getting undefined.

To get rid of this issue add a ? it will take that as an optional and only execute when summary?.lines is not undefined

data={summary?.lines} 

CodePudding user response:

Looks like the summary data you are getting, is from an asynchronous call, thus at the initial point, its undefined.

In such scenario adding a null check helps in resolving such issues. Instead of summary.lines, try summary?.lines.

  •  Tags:  
  • Related