12
static async getInitialProps({ query }) {
  let content;
  let alert;

  try {
    const first = query.first ? query.first : '';
    content = await getContent(first);
  } catch (error) {
    alert = 'There was an error loading data, please try again.';
    content = [];
  }

  return {
    content,
    alert,
  };
}

I'm trying to write tests for this logic but because it is server side code I'm struggling to understand how I write a test for it as it isn't available to me in instance().

Google hasn't shown me the way on this one so I'm wondering how others have tackled writing tests for getInitial props.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Max Lynn
  • 431
  • 2
  • 7
  • 16

1 Answers1

11

First, take a look at what's a static method and what does the static keyword do.

Since getInitialProps is just a static function on a component, you can test it manually like any other function.

import MyComponent from "./path/to/MyComponent";

// Mock the getContent function which I don't know where it comes from.
jest.mock("../someModule.js", () => ({
  getContent: () => Promise.reject()
}));

describe("MyComponent", () => {
  it('populates the "alert" prop on getContent failure.', async () => {
    // Inject anything you want to test
    const props = await MyComponent.getInitialProps({
      query: { first: "whatever" }
    });

    // And make sure it results in what you want.
    expect(props).toEqual({
      content: [],
      alert: "There was an error loading data, please try again."
    });
  });
});

Most of the time, getInitialProps is called like that anyway.

export default class MyApp extends App {
  static async getInitialProps ({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

The documentation describes getInitialProps goal and we can confirm that it's ok to call it directly and test its return value as an Object.

Notice that to load data when the page loads, we use getInitialProps which is an async static method. It can asynchronously fetch anything that resolves to a JavaScript plain Object, which populates props.

Data returned from getInitialProps is serialized when server rendering, similar to a JSON.stringify. Make sure the returned object from getInitialProps is a plain Object and not using Date, Map or Set.

For the initial page load, getInitialProps will execute on the server only. getInitialProps will only be executed on the client when navigating to a different route via the Link component or using the routing APIs.

Jason R Stevens CFA
  • 2,232
  • 1
  • 22
  • 28
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • Thanks this is a great explanation. I was trying to get it from instance before didn't realised I could do it directly from the component – Max Lynn Oct 22 '19 at 08:41
  • 1
    Thanks for linking to documentation -- I'm submitting some link updates herein. I like to also check for the props having their appropriate properties, too. This allows me to catch dynamic CMS typos quickly, e.g. ` expect(testProps).toHaveProperty('props.footerProps');`. – Jason R Stevens CFA Nov 18 '20 at 15:32