From 508b65b4ff84ac0a8d7b0af9ba9868a42a973518 Mon Sep 17 00:00:00 2001 From: Davide Briani Date: Mon, 18 Jun 2018 20:16:00 +0200 Subject: [PATCH] fix(tests): Fix tests and code to get full coverage --- __mocks__/react-native.js | 14 ++++ src/__mocks__/utils.js | 20 ++++++ src/index.js | 4 +- src/index.test.js | 131 +++++++++++++++++++++++++++++++++++++- src/utils.js | 3 +- 5 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 __mocks__/react-native.js create mode 100644 src/__mocks__/utils.js diff --git a/__mocks__/react-native.js b/__mocks__/react-native.js new file mode 100644 index 0000000..235e100 --- /dev/null +++ b/__mocks__/react-native.js @@ -0,0 +1,14 @@ +"use strict"; + +const ReactNative = jest.genMockFromModule("react-native"); + +let connectionInfo = { type: "wifi" }; + +export const NetInfo = { + __setConnectionInfo: info => { + connectionInfo = info; + }, + getConnectionInfo: () => connectionInfo +}; + +export default ReactNative; diff --git a/src/__mocks__/utils.js b/src/__mocks__/utils.js new file mode 100644 index 0000000..c1558e8 --- /dev/null +++ b/src/__mocks__/utils.js @@ -0,0 +1,20 @@ +"use strict"; + +const utils = jest.genMockFromModule("./utils"); + +let environment = "WEB"; + +function __setEnvironment(env) { + environment = env; +} + +utils.__setEnvironment = __setEnvironment; +utils.isString = (s: any) => typeof s === "string" || s instanceof String; + +Object.defineProperty(utils, "environment", { + get: function() { + return environment; + } +}); + +module.exports = utils; diff --git a/src/index.js b/src/index.js index a7c3757..cdc522b 100644 --- a/src/index.js +++ b/src/index.js @@ -4,8 +4,6 @@ import { NetInfo } from "react-native"; import fetch from "cross-fetch"; import utils from "./utils"; -const isString = s => typeof s === "string" || s instanceof String; - type Options = { urls: Array, timeout: number @@ -34,7 +32,7 @@ const isOnline = async (options?: Options = defaultOptions) => { } let { urls, timeout } = options; - if (!Array.isArray(urls) || !urls.every(isString)) { + if (!Array.isArray(urls) || !urls.every(utils.isString)) { urls = defaultOptions.urls; } if (!timeout || typeof timeout !== "number") { diff --git a/src/index.test.js b/src/index.test.js index d015c9e..969dc46 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,5 +1,132 @@ +import { NetInfo } from "react-native"; +import fetch from "cross-fetch"; import isOnline from "./index"; +import utils from "./utils"; -it("should be all good", () => { - expect(1 + 2).toBe(3); +jest.mock("react-native"); +jest.mock("cross-fetch"); +jest.mock("./utils"); + +const defaultOptions = { + urls: ["//1.1.1.1"], + timeout: 3000 +}; + +describe("WEB", () => { + beforeEach(() => { + jest.clearAllMocks(); + utils.__setEnvironment("WEB"); + }); + + test("calls cross-fetch once by default", async done => { + try { + fetch.mockResolvedValue(true); + const online = await isOnline(); + expect(fetch.mock.calls.length).toBe(1); + expect(fetch.mock.calls[0][0]).toBe(defaultOptions.urls[0]); + expect(online).toBe(true); + done(); + } catch (e) { + done.fail(e); + } + }); + + test("calls cross-fetch three times for three urls", async done => { + try { + fetch.mockResolvedValue(true); + await isOnline({ + urls: ["//1.1.1.1", "https://www.apple.com", "BAD URI"] + }); + expect(fetch.mock.calls.length).toBe(3); + done(); + } catch (e) { + done.fail(e); + } + }); + + test("uses default options when supplied malformed ones", async done => { + try { + fetch.mockResolvedValue(true); + await isOnline({ + urls: ["//1.1.1.1", "https://www.apple.com", 1234567890], + timeout: "3000" + }); + expect(fetch.mock.calls.length).toBe(1); + expect(fetch.mock.calls[0][0]).toBe(defaultOptions.urls[0]); + await isOnline({ + urls: "//1.1.1.1", + timeout: 3000 + }); + expect(fetch.mock.calls.length).toBe(2); + expect(fetch.mock.calls[1][0]).toBe(defaultOptions.urls[0]); + done(); + } catch (e) { + done.fail(e); + } + }); + + test("returns offline when every url is rejected", async done => { + try { + fetch.mockResolvedValue(Promise.reject()); + const online = await isOnline({ + urls: ["//1.1.1.1", "https://www.apple.com", "1234567890"], + timeout: 3000 + }); + expect(fetch.mock.calls.length).toBe(3); + expect(online).toBe(false); + done(); + } catch (e) { + done.fail(e); + } + }); +}); + +const getConnectionInfoSpy = jest.spyOn(NetInfo, "getConnectionInfo"); +describe("REACT-NATIVE", () => { + beforeEach(() => { + jest.clearAllMocks(); + utils.__setEnvironment("REACT-NATIVE"); + }); + + test("calls NetInfo once", async done => { + try { + NetInfo.__setConnectionInfo({ type: "wifi" }); + const online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(1); + expect(online).toBe(true); + done(); + } catch (e) { + done.fail(e); + } + }); + + test("returns correct connection status", async done => { + try { + let online = false; + const getConnectionInfoSpy = jest.spyOn(NetInfo, "getConnectionInfo"); + NetInfo.__setConnectionInfo({ type: "none" }); + online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(1); + expect(online).toBe(false); + NetInfo.__setConnectionInfo({ type: "wifi" }); + online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(2); + expect(online).toBe(true); + NetInfo.__setConnectionInfo({ type: "cellular" }); + online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(3); + expect(online).toBe(true); + NetInfo.__setConnectionInfo({ type: "unknown" }); + online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(4); + expect(online).toBe(false); + NetInfo.__setConnectionInfo({ type: "rubbish" }); + online = await isOnline(); + expect(getConnectionInfoSpy.mock.calls.length).toBe(5); + expect(online).toBe(false); + done(); + } catch (e) { + done.fail(e); + } + }); }); diff --git a/src/utils.js b/src/utils.js index 1329f27..37377cf 100644 --- a/src/utils.js +++ b/src/utils.js @@ -11,5 +11,6 @@ export default { } else { return "NODE"; } - } + }, + isString: (s: any) => typeof s === "string" || s instanceof String };