Geoffrey Huntoon
Geoffrey Huntoon

Reputation: 25

Jest test passes locally, but why does it fail when running npm test in GitHub actions?

I'm having an issue with certain Jest tests in the GitHub CI. My project is in TypeScript so I'm using ts-jest. Here is the function I'm testing, it sets the "text" fields of date and time elements:

const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

export const setDateAndTime = (dateDisplay: TextElement, clockDisplay: TextElement): void => {
  let now: Date = new Date(Date.now());
  dateDisplay.text = `${days[now.getDay()]}, ${months[now.getMonth()]} ${now.getDate()}, ${now.getFullYear()}`;

  let hours: number = preferences.clockDisplay === "12h" ? now.getHours() % 12 || 12 : now.getHours();
  let minutes: number = now.getMinutes();
  clockDisplay.text = minutes < 10 ? `${hours}:0${minutes}` : `${hours}:${minutes}`;
};

Here is a test for that function:

import { TestElement } from "../mocks/test-element";

let dateDisplay = new TestElement() as TextElement;
let clockDisplay = new TestElement() as TextElement;

test("Sets date and time display correctly", () => {
  jest.spyOn(Date, "now").mockImplementation(() => 1607913488);
  setDateAndTime(dateDisplay, clockDisplay);
  expect(dateDisplay.text).toBe("Mon, Jan 19, 1970");
  expect(clockDisplay.text).toBe("9:38");
});

TestElement is just a dummy element with a "text" field:

export class TestElement {
  text = "";
}

Locally, both of the expect() statements pass. But, in GitHub, I get the following error, for the second statement only:

TypeError: (0 , _jestDiff.diffStringsRaw) is not a function

      18 |   setDateAndTime(dateDisplay, clockDisplay);
      19 |   expect(dateDisplay.text).toBe("Mon, Jan 19, 1970");
    > 20 |   expect(clockDisplay.text).toBe("9:38");
         |                             ^
      21 | });

Since the issue is happening only in GitHub, I'll post my node.js.yml configuration as well:

name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: windows-latest

    strategy:
      matrix:
        node-version: [14.x]

    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npx fitbit-build
      - run: npm test

For the life of me, I can't figure out why only the second string comparison fails - it's the exact same function performed on the exact same class of element. After doing some research, the only thing I can find is that diffStringsRaw is used internally by Jest through the jest-diff package, but I haven't gotten much farther than that. Any help would be much appreciated!

Upvotes: 0

Views: 6360

Answers (2)

aadulan
aadulan

Reputation: 11

Another way to fix this, if you didn't want to use the GitHub Action, is to replace your test command with TZ=Europe/London npm test, where Europe/London is your desired time zone.

See this link for discussion

Upvotes: 1

Geoffrey Huntoon
Geoffrey Huntoon

Reputation: 25

The answer to this wasn't in Jest at all - rather it was that the GitHub test runner runs in GMT, not the local time zone, which was why the first expect() passed for comparing the date, and the second one failed for comparing the time.

For anyone interested, the possible solutions are:

  1. Refactor your function or your test to account for the system time zone; or
  2. Add a GitHub action to your configuration that explicitly sets the time zone.

I chose option 2 and went with Setup Timezone (shoutout to zcong1993 for the easy to use action!)

Upvotes: 0

Related Questions