Jest: making flow aware of certain jest assertions

Created on 8 Jun 2017  路  7Comments  路  Source: facebook/jest

What is the current behavior?

I have the following code:

test("flow problem", () => {
  class Foo {
    foo: string;
    constructor(foo: string) {
      this.foo = foo;
    }
  }
  function somecall(): { a: ?Foo, b: ?string } {
    return { a: new Foo("FOO"), b: "B" };
  }
  const { a, b } = somecall();
  expect(a.foo).toEqual("FOO");
});

Flow correctly marks the last line with "property foo Property cannot be accessed on possibly null value null`".

Now I want to modify this test so it passes flow. I was hoping I could do this with an additional Jest assertion before the last one, such as this one:

expect(a).not.toBe(null);

If flow understood that, the test would pass without flow error.

But I cannot do that. I can instead modify it to look like this:

test("flow problem", () => {
  ...
  const { a, b } = somecall();
  if (a == null) {
    return;
  }
  expect(a.foo).toEqual("FOO");
});

Now flow stops complaining, but there's a new problem: the test will never reach the expect statement if a is null, and will pass without complaint. So to get a complaint from jest when this branch is reached I have to add:

test("flow problem", () => {
  ...
  const { a, b } = somecall();
  if (a == null) {
    expect(false).toBe(true); // no programmatic way to induce fails
    return;
  }
  expect(a.foo).toEqual("FOO");
});

or, probably better but still awkward:

test("flow problem", () => {
  ...
  const { a, b } = somecall();
  expect(a).not.toBe(null);
  if (a == null) {
    return;
  }
  expect(a.foo).toEqual("FOO");
});

What is the expected behavior?

I'd like flow to understand the Jest assertion so that it stops complaining. If flow understood these like it understands comparisons with null, it could deduce the test is valid without me adding additional code.

Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.

jest 20.0.4
flow-bin 0.47.0
yarn 0.23.3

node 6.8.0
Fedora Linux 24.

Documentation

Most helpful comment

Any movement we can make here?

All 7 comments

Install typings with flow-typed install [email protected]

Where in docs do you think is good to tell people about flow-typed?

ExpectAPI.md, or GlobalAPI.md, or both?

In GettingStarted and both of the above.

From @thymikee's response I thought this would solve my reported problem, as I had mistakenly still installed an older version of flow-typed jest 19.x.x. But upgrading to 20.0.4 makes no difference - I still have flow complain the same way even though I added the line expect(a).not.toBe(null);

To be clear, I would like this test to have no flow complaints because once I've asserted a cannot be null, it should know it's therefore an instance of Foo:

test("flow problem", () => {
  class Foo {
    foo: string;
    constructor(foo: string) {
      this.foo = foo;
    }
  }
  function somecall(): { a: ?Foo, b: ?string } {
    return { a: new Foo("FOO"), b: "B" };
  }
  const { a, b } = somecall();
  expect(a).not.toBe(null);
  expect(a.foo).toEqual("FOO");
});

But instead I get a complaint on this line:

  expect(a.foo).toEqual("FOO");

property foo Property cannot be accessed on possibly null value null

@faassen Just remembered a solution on page 156 of React Up & Running by Stoyan Stefanov. It is not documented anywhere in flow.org Web site that I can find.

import invariant from 'invariant';

test("flow problem", () => {
  class Foo {
    foo: string;
    constructor(foo: string) {
      this.foo = foo;
    }
  }
  function somecall(): { a: ?Foo, b: ?string } {
    return { a: new Foo("FOO"), b: "B" };
  }
  const { a, b } = somecall();
  invariant(a, 'a is not optional in this test');
  expect(a.foo).toEqual("FOO");
});

To make sure that my prerequisite knowledge is correct:

you likely want to use some third-party libraries that were not written with Flow

Because Jest is written with Flow, the reason to need a libdef is because of implicit globals in test files as discussed in https://github.com/flowtype/flow-typed/issues/251 instead of explicit import test from 'ava' for example?

Looks like any link will go to flow-typed repo instead of flow.org because relevant info at the site is still limited to the blog article :(

Any movement we can make here?

Was this page helpful?
0 / 5 - 0 ratings