diff --git a/README.md b/README.md index 802e84d..75f454a 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,13 @@ * interceptor.waitForRequestAfterAction() waits for specific or any first request and returns all its data. * interceptor.waitForResponseAfterAction() waits for specific or any first response and returns all its data. +### Request Mocking ### + +* We are using teremock - Easy to use test request mocker for puppeteer / mocha / karma +* The documentation is located at: https://github.com/Diokuz/teremock +* The Helper (RequestMocker) that is implemented has simplified behavior where it will record all xhr and fetch responses from backend and when replay on the subsequent runs. +Default behavior can be overridden with custom options passed. The options allow to target specific requests and allow to specify response body, headers, status and delay. + ### Parallel execution ### * By default Jest runs tests in parallel with a worker pool of child processes * The console commands responsible for parallelization settings ([Official Jest documentation](https://jestjs.io/docs/en/cli.html)): diff --git a/example/tests/requestMocking.test.js b/example/tests/requestMocking.test.js new file mode 100644 index 0000000..f0276f0 --- /dev/null +++ b/example/tests/requestMocking.test.js @@ -0,0 +1,80 @@ +import { RequestMocker, Element, Helpers } from "test-juggler"; +const fs = require("fs"); + +describe("Request mocking by recording and replaying specific requests", () => { + + let mocker = new RequestMocker(); + let helpers = new Helpers(); + + it("Recording all requests and replaying it on the second test run google", async () => { + //Arrange + await mocker.start(); + + //Act + await helpers.goToUrlAndLoad("https://downforeveryoneorjustme.com/google"); + await mocker.stop(); + + //Assert + expect(fs.existsSync("mockData\\Request mocking by recording and replaying and indercetipt specific requests\\Recording all requests and replaying it on the second test run google\\interceptors\\get.json")).toBe(true); + }); + + it("Interceptor response 404 to all requests", async () => { + //Arrange + const errorTextElement = new Element("div.humane.humane-jackedup-error.humane-animate"); + const notFoundInterceptor = { + response: { status: 404 } + }; + + //Act + await mocker.start(notFoundInterceptor); + await helpers.goToUrlAndLoad("https://www.cheapshark.com/"); + await mocker.stop(); + const actualText = await errorTextElement.text(); + + //Assert + expect(actualText).toMatch("Error - 404 Not Found"); + }); + + it("Interceptor changing response body", async () => { + //Arrange + const errorTextElement = new Element("#json > span:nth-child(42)"); + const responseBodyChanged = { + url: "https://api.ratesapi.io/api/latest", + response: { + status: 200, + body: { "base": "EUR", "rates": { "This": 0.89448, "Response": 8.7809, "is": 15882.4, "mocked": 3.9172, "!": 7.4564 }, "date": "2020-06-05" } + } + }; + + //Act + await mocker.start(responseBodyChanged); + await helpers.goToUrlAndLoad("https://ratesapi.io/"); + await mocker.stop(); + const actualText = await errorTextElement.text(); + + //Assert + expect(actualText).toMatch("\"mocked\""); + }); + + it("Interceptor delaying response by 3s (ttfb)", async () => { + //Arrange + const timeStamp = Date.now(); + const responseBodyChanged = { + url: "https://api.ratesapi.io/api/latest", + response: { + status: 200, + body: { "base": "EUR", "rates": { "This": 0.89448, "Response": 8.7809, "is": 15882.4, "mocked": 3.9172, "!": 7.4564 }, "date": "2020-06-05" }, + ttfb: 3000 + } + }; + + //Act + await mocker.start(responseBodyChanged); + await helpers.goToUrlAndLoad("https://ratesapi.io/"); + const pageLoadTimeinMs = Date.now() - timeStamp; + await mocker.stop(); + + //Assert + expect(pageLoadTimeinMs).toBeGreaterThan(3000); + }); +}); \ No newline at end of file diff --git a/framework/requestMocker.js b/framework/requestMocker.js new file mode 100644 index 0000000..c7f2123 --- /dev/null +++ b/framework/requestMocker.js @@ -0,0 +1,19 @@ +/*global page*/ +import teremock from "teremock"; + +const DEFAULT_INTERCEPTOR_CAPTURE = { + resourceTypes: "xhr,fetch" +}; + +export default class RequestMocker { + + async stop() { + await teremock.stop(); + } + + async start(interceptors = DEFAULT_INTERCEPTOR_CAPTURE) { + + const targetDir = `./mockData/${jasmine["currentSuite"].fullName}/${jasmine["currentTest"].description}`; + await teremock.start({ page, wd: targetDir, interceptors: { interceptors } }); + } +} \ No newline at end of file diff --git a/index.js b/index.js index bc77592..a06be7c 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ export { default as Element } from "./framework/Element"; export { default as Helpers } from "./framework/helpers"; +export { default as RequestMocker } from "./framework/requestMocker"; export { default as Interceptor } from "./framework/interceptor"; \ No newline at end of file diff --git a/package.json b/package.json index d559402..022e2bc 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "jest-image-snapshot": "^3.0.0", "jest-junit": "^10.0.0", "jest-puppeteer": "^4.0.0", - "puppeteer": "^3.0.0" + "puppeteer": "^3.0.0", + "teremock": "^1.0.5" }, "devDependencies": { "eslint": "^6.8.0",