diff --git a/package-lock.json b/package-lock.json index d536c3b8..ca0417c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2383,6 +2383,15 @@ "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==" }, + "@types/axios-mock-adapter": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@types/axios-mock-adapter/-/axios-mock-adapter-1.10.0.tgz", + "integrity": "sha512-Govyvy3cr8hsR6DcCoBjVMQhYyzkHdfU/hMgBw6ONOFuTrZTDxdE/rBR7Sz3qsGtVZABSK8/2rDekp5UwZ/V8A==", + "dev": true, + "requires": { + "axios-mock-adapter": "*" + } + }, "@types/babel__core": { "version": "7.1.12", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", @@ -2586,6 +2595,15 @@ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, + "@types/nock": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", + "integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", + "dev": true, + "requires": { + "nock": "*" + } + }, "@types/node": { "version": "12.19.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.0.tgz", @@ -3773,6 +3791,16 @@ "is-buffer": "^2.0.2" } }, + "axios-mock-adapter": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.19.0.tgz", + "integrity": "sha512-D+0U4LNPr7WroiBDvWilzTMYPYTuZlbo6BI8YHZtj7wYQS8NkARlP9KBt8IWWHTQJ0q/8oZ0ClPBtKCCkx8cQg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "is-buffer": "^2.0.3" + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -13167,6 +13195,12 @@ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "dev": true + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -13920,6 +13954,35 @@ "tslib": "^1.10.0" } }, + "nock": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.0.4.tgz", + "integrity": "sha512-alqTV8Qt7TUbc74x1pKRLSENzfjp4nywovcJgi/1aXDiUxXdt7TkruSTF5MDWPP7UoPVgea4F9ghVdmX0xxnSA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash.set": "^4.3.2", + "propagate": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -16097,6 +16160,12 @@ "reflect.ownkeys": "^0.2.0" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", diff --git a/package.json b/package.json index ae644607..01bda95e 100644 --- a/package.json +++ b/package.json @@ -79,8 +79,8 @@ "release-web": "npm run build && npm run webpack:prod", "release-ci": "bash ./scripts/build.sh", "release": "npm run build && npm run webpack:prod && electron-builder", - "pretest": "npx eslint 'src/**/*.ts*'", - "lintfix": "npx eslint 'src/**/*.ts*' --fix", + "pretest": "npx eslint \"src/**/*.ts*\"", + "lintfix": "npx eslint \"src/**/*.ts*\" --fix", "test": "react-scripts test --env=jsdom --silent", "test:ci": "cross-env CI=true npm run test", "test:coverage": "npm run test -- --coverage", @@ -105,10 +105,12 @@ }, "devDependencies": { "@fortawesome/fontawesome-free": "^5.5.0", + "@types/axios-mock-adapter": "^1.10.0", "@types/dotenv": "^6.1.0", "@types/enzyme": "^3.1.15", "@types/jest": "23.3.9", "@types/json2csv": "^4.4.0", + "@types/nock": "^11.1.0", "@types/node": "12.19.0", "@types/react": "16.7.6", "@types/react-dom": "16.0.9", @@ -119,6 +121,7 @@ "@types/redux-logger": "^3.0.6", "@types/redux-mock-store": "^1.0.0", "@types/snapsvg": "^0.4.35", + "axios-mock-adapter": "^1.19.0", "cross-env": "^5.2.0", "electron": "^10.1.5", "electron-builder": "^22.9.1", @@ -127,6 +130,7 @@ "foreman": "^3.0.1", "jest-enzyme": "^7.0.1", "jquery": "^3.3.1", + "nock": "^13.0.4", "node-sass": "^4.14.1", "popper.js": "^1.14.6", "redux-immutable-state-invariant": "^2.1.0", diff --git a/src/common/htmlFileReader.test.ts b/src/common/htmlFileReader.test.ts index be8c189d..82c7c3a1 100644 --- a/src/common/htmlFileReader.test.ts +++ b/src/common/htmlFileReader.test.ts @@ -1,9 +1,10 @@ -import axios, { AxiosResponse } from "axios"; +import axios from "axios"; import HtmlFileReader from "./htmlFileReader"; import { AssetService } from "../services/assetService"; import { TFRecordsBuilder, FeatureType } from "../providers/export/tensorFlowRecords/tensorFlowBuilder"; import MockFactory from "./mockFactory"; import { AssetState, IAsset } from "../models/applicationState"; +import nock from 'nock'; describe("Html File Reader", () => { const assetTestCache = new Map(); @@ -57,62 +58,41 @@ describe("Html File Reader", () => { describe("Download asset binaries", () => { it("Downloads a blob from the asset path", async () => { const asset = AssetService.createAssetFromFilePath("https://server.com/image.jpg"); - axios.get = jest.fn((url, config) => { - return Promise.resolve({ - config, - headers: null, - status: 200, - statusText: "OK", - data: new Blob(["Some binary data"]), - }); - }); + nock("https://server.com") + .get("/image.jpg") + .reply(200, new Blob(["Some binary data"])); const result = await HtmlFileReader.getAssetBlob(asset); expect(result).not.toBeNull(); expect(result).toBeInstanceOf(Blob); - expect(axios.get).toBeCalledWith(asset.path, { responseType: "blob" }); }); it("Rejects the promise when request receives non 200 result", async () => { const asset = AssetService.createAssetFromFilePath("https://server.com/image.jpg"); - axios.get = jest.fn((url, config) => { - return Promise.resolve({ - config, - headers: null, - status: 404, - statusText: "Not Found", - data: null, - }); - }); + nock("https://server.com").get("/image.jpg").reply(404, null); await expect(HtmlFileReader.getAssetBlob(asset)).rejects.not.toBeNull(); - expect(axios.get).toBeCalledWith(asset.path, { responseType: "blob" }); }); }); describe("Download asset binaries array", () => { - beforeEach(() => { - axios.get = jest.fn((url, config) => { - return Promise.resolve({ - config, - headers: null, - status: 200, - statusText: "OK", - data: [1, 2, 3], - }); - }); - }); - it("Downloads a byte array from the asset path", async () => { - const asset = AssetService.createAssetFromFilePath("https://server.com/image.jpg"); + const imagePath = "https://server.com/image.jpg"; + nock("https://server.com") + .get("/image.jpg") + .reply(200, [1, 2, 3]); + + const asset = AssetService.createAssetFromFilePath(imagePath); const result = await HtmlFileReader.getAssetArray(asset); expect(result).not.toBeNull(); expect(result).toBeInstanceOf(ArrayBuffer); - expect(axios.get).toBeCalledWith(asset.path, { responseType: "blob" }); }); it("Test non valid asset type", async () => { - const imageAsset = AssetService.createAssetFromFilePath("https://server.com/image.notsupported"); + const imagePath = "https://server.com/image.notsupported"; + axiosMock.onGet(imagePath).reply(200, [1, 2, 3]); + + const imageAsset = AssetService.createAssetFromFilePath(imagePath); try { const result = await HtmlFileReader.readAssetAttributes(imageAsset); } catch (error) { @@ -128,23 +108,16 @@ describe("Html File Reader", () => { height: 1080, }; - axios.get = jest.fn((url, config) => { - const builder = new TFRecordsBuilder(); - builder.addFeature("image/height", FeatureType.Int64, expected.height); - builder.addFeature("image/width", FeatureType.Int64, expected.width); - const buffer = builder.build(); - const tfrecords = TFRecordsBuilder.buildTFRecords([buffer]); + const builder = new TFRecordsBuilder(); + builder.addFeature("image/height", FeatureType.Int64, expected.height); + builder.addFeature("image/width", FeatureType.Int64, expected.width); + const buffer = builder.build(); + const tfrecords = TFRecordsBuilder.buildTFRecords([buffer]); - return Promise.resolve({ - config, - headers: null, - status: 200, - statusText: "OK", - data: tfrecords, - }); - }); + const assetPath = "https://server.com/image.tfrecord" + axiosMock.onGet(assetPath).reply(200, tfrecords); - const imageAsset = AssetService.createAssetFromFilePath("https://server.com/image.tfrecord"); + const imageAsset = AssetService.createAssetFromFilePath(assetPath); const result = await HtmlFileReader.readAssetAttributes(imageAsset); expect(result.width).toEqual(expected.width); @@ -159,23 +132,16 @@ describe("Html File Reader", () => { height: 1080, }; - axios.get = jest.fn((url, config) => { - const builder = new TFRecordsBuilder(); - builder.addFeature("image/height", FeatureType.Int64, expected.height); - builder.addFeature("image/width", FeatureType.Int64, expected.width); - const buffer = builder.build(); - const tfrecords = TFRecordsBuilder.buildTFRecords([buffer]); + const builder = new TFRecordsBuilder(); + builder.addFeature("image/height", FeatureType.Int64, expected.height); + builder.addFeature("image/width", FeatureType.Int64, expected.width); + const buffer = builder.build(); + const tfrecords = TFRecordsBuilder.buildTFRecords([buffer]); - return Promise.resolve({ - config, - headers: null, - status: 200, - statusText: "OK", - data: tfrecords, - }); - }); + const assetPath = "https://server.com/image.tfrecord" + axiosMock.onGet(assetPath).reply(200, tfrecords); - const imageAsset = AssetService.createAssetFromFilePath("https://server.com/image.tfrecord"); + const imageAsset = AssetService.createAssetFromFilePath(assetPath); const result = await HtmlFileReader.readAssetAttributes(imageAsset); expect(result.width).toEqual(expected.width); diff --git a/src/providers/storage/bingImageSearch.test.ts b/src/providers/storage/bingImageSearch.test.ts index 65d7daaa..e90a748f 100644 --- a/src/providers/storage/bingImageSearch.test.ts +++ b/src/providers/storage/bingImageSearch.test.ts @@ -2,6 +2,7 @@ import axios from "axios"; import { BingImageSearch, IBingImageSearchOptions, BingImageSearchAspectRatio } from "./bingImageSearch"; import { IAsset, AssetType, AssetState } from "../../models/applicationState"; import MD5 from "md5.js"; +import MockAdapter from "axios-mock-adapter"; describe("Bing Image Search", () => { const options: IBingImageSearchOptions = { @@ -18,26 +19,21 @@ describe("Bing Image Search", () => { { contentUrl: "http://images.com/image4.jpg" }, ]; - axios.get = jest.fn(() => { - return Promise.resolve({ - data: { - value: assets, - }, - }); - }); + const axiosMock = new MockAdapter(axios); it("calls the Bing image search API", async () => { // tslint:disable-next-line:max-line-length const expectedUrl = `https://api.cognitive.microsoft.com/bing/v7.0/images/search?q=${options.query}&aspect=${options.aspectRatio}`; + axiosMock.onGet(expectedUrl).reply(200, { value: assets, }); + const expectedHeaders = { - headers: { - "Ocp-Apim-Subscription-Key": options.apiKey, - "Accept": "application/json", - }, + "Ocp-Apim-Subscription-Key": options.apiKey, + "Accept": "application/json", }; await provider.getAssets(); - expect(axios.get).toBeCalledWith(expectedUrl, expectedHeaders); + expect(axiosMock.history.get[0].url).toEqual(expectedUrl); + expect(axiosMock.history.get[0].headers).toEqual(expectedHeaders); }); it("returns parsed image assets", async () => {