Jest jsdom Protocol "http:" not supported
I am trying to run some integration tests for react using jest. When running the test, I get the following error UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_PROTOCOL]: Protocol "http:" not supported. Expected "https:"
. Initially I though was related to msw mocking my api calls, but even after disabling the msw server I am still getting this erros.
I am using axios in my app to make http requests, and all URLs are set to use HTTPS. I also told jest both in a setup file and jest.config
to use https when mocking origin, but it's still not working. Any ideas what else I can try?
See also questions close to this topic
-
Radio Group not rendering in react (material ui)
I have a state in react called options that looks like:
{ "0": ["Peru", "Brazil", "Colombia", "Ecuador"], "1": ["False", "True"], "2": ["Kurdish", "Arab", "Egyptian", "Syrian"], "3": ["True", "False"], "4": ["Just Cause 2", "Grand Theft Auto 5", "The Elder Scrolls 4: Oblivion", "The Witcher 3: Wild Hunt"] }
I want the array values to render in a radio group, In this example RadioGroup 1 should contain radio buttons of object key "0", RadioGroup 2 of object key "1" and so on...
For a more visual example:
//Radio Group 1
O Peru
O Brazil
O Columbia
O Ecuador//Radio Group 2
O False
O TrueI am trying to do like this but the Radio isn't rendering in Object.values, I have tested it does render outside of Object.values if I put some constant value (for testing purpose)
const renderAnswers = (index) => { // don't worry about what index is, just remember that I'm calling this function in main render return ( <RadioGroup aria-label="quiz" name="quiz" onChange={handleRadioChange(index)}> { // Works but not inside Object.values // <FormControlLabel value="F" control={<Radio color="primary" />} label="F"} /> Object.values(options).map((val, key) => { //options is the state that I was talking about in the beginning val.map((v, k) => { return ( // Doesn't work I don't know why? <FormControlLabel value={decodeEntities(v)} control={<Radio color="primary" />} label={decodeEntities(v)} /> ); }) }) } </RadioGroup> ); }
SideNote: because my array can contain special characters decodeEntities is a function that decodes special characters and codes and returns the string
-
How to handle String mechanism in react js
I have written a small piece of code inside the return. for example
const Demo = (props) => { return ( <div> props.map((val, index) => ( <h2>{val.fileName}</h2> )) </div> ) }
The output is coming like this:
F:\test\form\student.html
But inside I don't want this type of output. I want to modify the output like:F:\test\form\form.pdf
The last student.html will remove and the form must become 2 times will repeat and lastly, the extension is pdf
original output: F:\test\form\student.html desired output: F:\test\form\form.pdf
can you help how to solve this problem?
-
Ctrl stops animated scroll midway while using react-scroll and disable-scroll
I am currently working on a website that is going to be having scrolling disabled while using a subset of properties on disableScroll(npm package)
disableScroll.on( {}, { authorizedInInputs: [32, 37, 38, 39, 40], disableKeys: true, disableScroll: false, disableWheel: true, keyboardKeys: [32, 33, 34, 35, 36, 37, 38, 39, 40], } );
I have disableScroll as false since I want to animate scrolling via using react-scroll Links(another npm package)
Everything works fine but now I noticed that if while the scrolling is ongoing(I have a duration of a second) if I press the ctrl key it stops the scrolling. I haven't been able to figure out why this is happening. Is there a way to disable this feature or is this a bug?
I do want to keep my animated scroll feature(react-scroll smooth scrolling no)
Not sure if it helps but I have set the scrollbar width to zero in order to prevent the user from scrolling altogether.
PS: I don't think any of my code snippets are required but if so let me know and I'll update them here
-
More than one test fails due to import after jest is torn down - Supertest Typescript and Express API
I am running into an issue where I am running multiple tests using
supertest
andjest
. When there is only one test running then it works just fine but the second one throws the following error:ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
I tested this with two very simple tests:
describe("Default API", () => { describe("Default:", () => { it("should create a user in the DB", (done) => { request(app).get("/").expect(200, done); }); it("should create a user in the DB", (done) => { request(app).get("/").expect(200, done); }); }); });
They are the same but the second one throws the error. If I run only the first one there is no issue. This must be a setup issue Does anyone have advice. In my index.ts where I have the main express code I export app as follows:
export default app;
This is at the bottom of the index.ts file.
-
TypeError: Cannot read property 'getContext' of null
I have created a game using canvas API and now I am testing using Jest. But when running a test for a simple function it throws me this error. my script tag is at the end of the HTML and I also added this event listener to wait for the DOM document.addEventListener("DOMContentLoaded", init,false);
jest
PASS tests/sum.test.js FAIL tests/mod.test.js ● Test suite failed to run
TypeError: Cannot read property 'getContext' of null 20 | const empty = 0; 21 | const nextPieceCanvas = document.querySelector("canvas#nextPiece") as HTMLCanvasElement; > 22 | const NPctx = nextPieceCanvas.getContext("2d")! as CanvasRenderingContext2D; | ^ 23 | 24 | //Gameboard Canvas 25 | const canvas = document.querySelector("canvas#tetris") as HTMLCanvasElement; at Object.<anonymous> (src/ts/app.ts:22:31) at Object.<anonymous> (tests/mod.test.js:2:1)
Test Suites: 1 failed, 1 passed, 2 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.424 s Ran all test suites. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! tetris_ts@1.0.0 test:
jest
npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the tetris_ts@1.0.0 test script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in: npm ERR! /home/alex/.npm/_logs/2021-02-26T22_46_02_771Z-debug.log
enter code here
-
nestjs unit test createTestingModule Dependency Injection
I hope you can help me out. I am using Nx with latest angular/nestjs (date: February, 26)
... "@nestjs/common": "^7.0.0", "@nestjs/config": "^0.6.3", "@nestjs/core": "^7.0.0", "@nestjs/platform-express": "^7.0.0", "@nestjs/platform-socket.io": "^7.6.7", "@nestjs/websockets": "^7.6.7", "jest": "26.2.2", "@nrwl/jest": "11.4.0", ...
I cannot get my unit test running using NestJS with Jest I want to test following service:
@Injectable() export class CoreApiService { logger = new Logger('CoreApiService'); apiEndpoint; constructor(private httpService: HttpService, configService: ConfigService) { this.apiEndpoint = configService.get('API_SERVICE_ENDPOINT'); } }
and I get following error:
TypeError: Cannot read property 'get' of undefined
so it seems that the ConfigService (and also httpService) is always undefined.
when logging httpService and ConfigService, it will always be undefined. Even when I try to instantiate new Instances like
new CoreApiService(new HttpService(), new ConfigService())
I've even tried things likenew CoreApiService({} as any, {get: (...params} => {return 'foo'})
in the test itselfit will always be the same error mentioned above.
The test file:
import { Test, TestingModule } from '@nestjs/testing'; import { CoreApiService } from './core-api.service'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { HttpModule } from '@nestjs/common'; class ConfigServiceMock { get(key: string): string { switch (key) { case 'API_SERVICE_ENDPOINT': return ''; } } } describe('CoreApiService', () => { let module: TestingModule; let service: CoreApiService; beforeEach(async () => { module = await Test.createTestingModule({ imports: [HttpModule, ConfigModule], providers: [ CoreApiService, { provide: ConfigService, useClass: ConfigServiceMock }, ], }).compile(); service = module.get<CoreApiService>(CoreApiService); }); it('should be defined', () => { expect(service).toBeDefined(); }); });
I've even tried:
.overrideProvider(ConfigService).useClass(ConfigServiceMock)
Thank you in advance!
-
How do I use jsdom with Gatsby (aka use webpack target node)?
I want to use jsdom within a Gatsby project, in order to be able to load and render a separate webpage within a React component.
However, when I try to build with Gatsby, I get a series of Webpack errors which look like this:
undefined failed
Can't resolve 'child_process' in '/Users/john/WebstormProjects/analytics/web/node_modules/jsdom/lib/jsdom/living/xhr'
I think this may be because Webpack is using the 'web' target mode and not 'node'. I've tried putting a
webpack.config.js
file in the root directory:module.exports = { target: 'node', }
However, this didn't do anything. I also tried to use
onCreateWebpackConfig
, but I'm not sure if this is correct, as I couldn't get this to work either://gatsby-node.ts export { onCreateWebpackConfig } from "./src/gatsby/on-create-webpack-config"; // ./src/gatsby/on-create-webpack-config export const onCreateWebpackConfig = ({ actions } : any) => { actions.setWebpackConfig({ target: 'node', }); }
I have 2 questions:
Is it possible to use
jsdom
in a Gatsby project and if so, what do I need to do? If it's just to use thetarget
mode, then:How do I set the
target
mode in Gatsby to benode
and notweb
?
-
JSDOM - not able to get the manipulated file
I tried several approaches but it didn't work. I need some help. I want to manipulate a simple html code. It is plain code without a body or head. The id_1 in the following code example has the start value 40.
const jsdom = require("jsdom"); const dom = new jsdom.JSDOM(html_file); dom.window.document.getElementById("id_1").value = 80; console.log(dom.window.document.getElementById("id_1").value); // return 80 -> correct
To get the manipulated code I try:
html_file = dom.window.document.documentElement.innerHTML;
It doesn´t work. I always get the original code back (id_1 value 40) and not the manipulated with the value 80. What is my error? Happy for some help...
-
D3.CSV ReferenceError: fetch is not defined
Hello i wan't to export only the SVG of the "Radial Stacked Barchart" using jsdom.env is not a function exporting svg to image for the "Radial Stacked Barchart" i use the following article: https://bl.ocks.org/KoGor/9f3932d3c7154f8ab3ea2078b2aca113
I created two scripts
ExportToSVG.js script
const d3 = require("d3"); const fs = require("fs"); const {JSDOM} = require("jsdom"); // init d3 - https://gist.github.com/tomgp/c99a699587b5c5465228 const minHtml = '<html><head></head><body><svg width="960" height="800" font-family="sans-serif" font-size="10"></body></html>' const dom = new JSDOM(`${minHtml}`, { pretendToBeVisual: true }); const window = dom.window; window.d3 = d3.select(window.document); // D3JS CODE * * * * * * WORKS * * * * * * * * * * * var svg = window.d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"), innerRadius = 180, outerRadius = Math.min(width, height) / 2.5, g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var xScaleOffset = Math.PI * 75/180; var x = d3.scaleBand() .range([xScaleOffset, 2 * Math.PI + xScaleOffset]) .align(0); var y = d3.scaleLinear() .range([innerRadius, outerRadius]); var z = d3.scaleOrdinal() .range(["#a1d76a", "#91bfdb"]); var zClasses = ['внутренняя сторона', 'внешняя сторона']; // END (D3JS) * * * * * * * * * * * * * * * * * * * * * * * * // D3JS CODE * * * * * * EXPIRIMENT * * * * * * * * * * * d3.csv("simple_stat.csv", function(d, i, columns) { d.left_lane = (+d.left_lane); d.right_lane = (+d.right_lane); return d; }, function(error, data) { if (error) throw error; var keys = data.columns.slice(1); var meanAccidents = d3.mean(data, function(d) { return d3.sum(keys, function(key) { return d[key]; }); }) x.domain(data.map(function(d) { return d.km; })); y.domain([0, d3.max(data, function(d) { return (d.left_lane + d.right_lane); })]); z.domain(data.columns.slice(1)); // Accidents g.append('g') .selectAll("g") .data(d3.stack().keys(data.columns.slice(1))(data)) .enter().append("g") .attr("fill", function(d) { return z(d.key); }) .selectAll("path") .data(function(d) { return d; }) .enter().append("path") .attr("d", d3.arc() .innerRadius(function(d) { return y(d[0]); }) .outerRadius(function(d) { return y(d[1]); }) .startAngle(function(d) { return x(d.data.km); }) .endAngle(function(d) { return x(d.data.km) + x.bandwidth(); }) .padAngle(0.01) .padRadius(innerRadius)); //yAxis and Mean var yAxis = g.append("g") .attr("text-anchor", "middle"); var yTicksValues = d3.ticks(0, 40, 4); console.log('Среднее: ', meanAccidents); // Mean value line var yMeanTick = yAxis .append("g") .datum([meanAccidents]); yMeanTick.append("circle") .attr("fill", "none") .attr("stroke", "#C0625E") .attr("stroke-dasharray", "5 3") .attr("r", y); var yTick = yAxis .selectAll("g") .data(yTicksValues) .enter().append("g"); yTick.append("circle") .attr("fill", "none") .attr("stroke", "#ccdcea") .attr("r", y); yTick.append("text") .attr("y", function(d) { return -y(d); }) .attr("dy", "0.35em") .attr("fill", "none") .attr("stroke", "#fff") .attr("stroke-width", 5) .text(y.tickFormat(5, "s")); yTick.append("text") .attr("y", function(d) { return -y(d); }) .attr("dy", "0.35em") .text(y.tickFormat(5, "s")); yAxis.append("text") .attr("y", function(d) { return -y(yTicksValues.pop()); }) .attr("dy", "-2em") .text("МКАД, аварийность"); // Labels for xAxis var label = g.append("g") .selectAll("g") .data(data) .enter().append("g") .attr("text-anchor", "middle") .attr("transform", function(d) { return "rotate(" + ((x(d.km) + x.bandwidth() / 2) * 180 / Math.PI - 90) + ")translate(" + innerRadius + ",0)"; }); label.append("line") .attr("x2", function(d) { return (((d.km % 5) == 0) | (d.km == '1')) ? -7 : -4 }) .attr("stroke", "#000"); label.append("text") .attr("transform", function(d) { return (x(d.km) + x.bandwidth() / 2 + Math.PI / 2) % (2 * Math.PI) < Math.PI ? "rotate(90)translate(0,16)" : "rotate(-90)translate(0,-9)"; }) .text(function(d) { var xlabel = (((d.km % 5) == 0) | (d.km == '1')) ? d.km : ''; return xlabel; }); // Legend var legend = g.append("g") .selectAll("g") .data(zClasses) .enter().append("g") .attr("transform", function(d, i) { return "translate(-50," + (i - (zClasses.length - 1) / 2) * 25+ ")"; }); legend.append("circle") .attr("r", 8) .attr("fill", z); legend.append("text") .attr("x", 15) .attr("y", 0) .attr("dy", "0.35em") .text(function(d) { return d; }); }); console.log( window.d3.select("body").html() );
for the data i use the same data as what is described in the example in the above url. When i execute the following statement
node ExportToSVG > out.svg
i get the following error:
C:\Users\username\Documents\git\svgcreator.node.js\node_modules\d3-fetch\dist\d3-fetch.js:32 return fetch(input, init).then(responseText); ReferenceError: fetch is not defined at text (C:\Users\username\Documents\git\svgcreator.node.js\node_modules\?[4md3-fetch?[24m\dist\d3-fetch.js:32:3) at Object.<anonymous> (C:\Users\username\Documents\git\svgcreator.node.js\node_modules\?[4md3-fetch?[24m\dist\d3-fetch.js:38:12) at Object.<anonymous> (C:\Users\username\Documents\git\svgcreator.node.js\ExportToSVG.js:36:4) ?[90m at Module._compile (internal/modules/cjs/loader.js:1063:30)?[39m ?[90m at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)?[39m ?[90m at Module.load (internal/modules/cjs/loader.js:928:32)?[39m ?[90m at Function.Module._load (internal/modules/cjs/loader.js:769:14)?[39m ?[90m at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)?[39m ?[90m at internal/main/run_main_module.js:17:47?[39m
Can you please help me
Manny thanks Erik
-
What jest tests am I missing for lines 27-33 in this Angular component?
I am writing unit tests for the first time and a bit confused on what tests I'm actually missing for lines 27-33. This is a simple angular component with ngOnit and two functions. I thought I covered all lines because I wrote tests for each function that was called, but something is obviously missing. None of these functions have an expected return value. They are just expected to be called. Please help! Any resources to help me understand unit tests with jest would be helpful. We are not using TestBed since we have other automated tests for the DOM. So we are only focused on the
component.ts
files. Also, if you see a test that isn't actually necessary please let me know that too. Here is where I'm at:I'm currently at 78.57%
video-inventory.component.ts
import { Component, OnInit } from '@angular/core'; import { BaseComponent } from '@enterprise/shared/client'; import { AnalyticsService } from '@enterprise/senet/shared/src/lib/analytics/analytics.service'; import { VideoInventoryFacade } from '../shared/video-inventory.facade'; @Component({ selector: 'senet-video-inventory', templateUrl: './video-inventory.component.html', styleUrls: ['./video-inventory.component.scss'], }) export class VideoInventoryComponent extends BaseComponent implements OnInit { vm$ = this._videoInventoryFacade.vm$; constructor( private _videoInventoryFacade: VideoInventoryFacade, private _analyticsService: AnalyticsService ) { super(); } ngOnInit() { this._videoInventoryFacade.loadNetworks(); } onPageChange(page: number) { 27. this._videoInventoryFacade.pageChange(page); 28. } 29. 30. onSearchChange(searchCriteria: string) { 31. this._videoInventoryFacade.searchChange(searchCriteria); 32. 33. this._analyticsService.searchEvent( { searchPhrase: searchCriteria, }, { siteSection: 'Video', siteSubSection: 'Video Inventory', } ); } }
video-inventory.component.spec.ts
import { Injectable } from '@angular/core'; import { VideoInventoryComponent } from './video-inventory.component'; @Injectable() class MockService {} describe('VideoInventoryComponent', () => { let component: any; beforeEach(async () => { component = new VideoInventoryComponent( new MockService() as any, new MockService() as any ); }); it('should run #constructor()', async () => { expect(component).toBeTruthy(); }); it('should run #ngOnInit()', async () => { component._videoInventoryFacade.loadNetworks = jest.fn(); component.ngOnInit(); expect(component._videoInventoryFacade.loadNetworks).toHaveBeenCalled(); }); it('should run onPageChange()', async () => { const pageChangeEvent = { toPage: 3, }; component.onPageChange = jest.fn(); component.onPageChange(pageChangeEvent.toPage); expect(component.onPageChange).toHaveBeenCalledWith(pageChangeEvent.toPage); }); //** I thought this would cover lines 27-29 **// it('should run _videoInventoryFacade.pageChange()', async () => { const pageChangeEvent = { toPage: 3, }; component._videoInventoryFacade.pageChange = jest.fn(); component._videoInventoryFacade.pageChange(pageChangeEvent.toPage); expect(component._videoInventoryFacade.pageChange).toHaveBeenCalledWith( pageChangeEvent.toPage ); }); //** I thought this was covering lines 30-33 **// it('should run onSearchChange()', async () => { component.onSearchChange = jest.fn(); component.onSearchChange(); expect(component.onSearchChange).toBeCalled(); }); //** I thought this would cover lines 30-33 **// it('should run _videoInventoryFacade.searchChange()', async () => { component._videoInventoryFacade.searchChange = jest.fn(); component._videoInventoryFacade.searchChange(); expect(component._videoInventoryFacade.searchChange).toBeCalled(); }); //** I thought this would cover lines 30-33 **// it('should run _analyticsService.searchEvent()', async () => { component._analyticsService.searchEvent = jest.fn(); component._analyticsService.searchEvent( { searchPhrase: '*', }, { siteSection: 'Video', siteSubSection: 'Video Inventory', } ); expect(component._analyticsService.searchEvent).toHaveBeenCalledWith( { searchPhrase: '*', }, { siteSection: 'Video', siteSubSection: 'Video Inventory', } ); });
-
Jest jest.fn it's being called but the expect fails
I am new to testing with jest, and I wrote the below test. I mocked with jest a function and passed it as a parameter. however when run the test, in the logs I can see the function onSuccess was called. but the expect fails with the error below the code.
how am I supposed to assert the onSuccess = jest.fn() was called?
Test
it('should create product correctly', async () => { const store = mockStore() const onSuccess = jest.fn(() => console.log("I was called")) const onError = jest.fn() const CreateProductApiMock = CreateProductApi as jest.Mock const productRequest = {id: 1} as Product CreateProductApiMock.mockResolvedValue(Promise.resolve({ data: "any" } as AxiosResponse<string>)) await store.dispatch(createProduct(productRequest, onSuccess, onError, "jwt")) await expect(CreateProductApiMock).toHaveBeenCalledWith({"id": 1}, "jwt") await expect(onSuccess).toHaveBeenCalledTimes(1) })
Logs:
console.log src/__tests__/components/product/product-slice.test.ts:133 I've was called Error: expect(jest.fn()).toHaveBeenCalledTimes(expected) Expected number of calls: 1 Received number of calls: 0
-
How do you unit test JavaScript written in Asynchronous Module Definition pattern?
I tried to add a unit test framework (JEST) to legacy JavaScript codebase written in AMD. NodeJs kicks out an error when require to add the module.
Here is the JavaScript AMD:
define('LegacyModule', function () { 'use strict'; var exports = { CreateTag: function (name) { return 'tag:' + name; }, }; return exports; });
Here is the Test file:
require('amd-loader'); var myTest = require('./LegacyModule'); test('Create where tag does not throw exception', () => { var request = myTest.CreateTag('test'); expect(request.toBe('tag:test')); });
Here are the errors:
Test suite failed to run
Can not assign module to a different id than the current file ● Test suite failed to runCan not assign module to a different id than the current file 1 | define('LegacyModule', > 2 | function () { | ^ 3 | 'use strict'; 4 | var exports = { 5 | at Object.<anonymous>.global.define (node_modules/amd-loader/amd-loader.js:39:15)
-
How to match a buffer request body with Mock Service Worker
I am currently using Nock and would like to replace it with Mock Service Worker.
With Nock I am able to match the stringified request body with the provided buffer:const request = nock(hostname) .post('/api/instance', Buffer.from(arrayBuffer)) .reply(201, json);
I have not figured out how to get the same result with mws because the request body and the buffer are not equal. Can someone help me?
Thanks. -
setupServer is not working when use react-testing-library
I want to unit test using react-testing-library when I first render component, fetch some info from API.
So I'm m using setupServer to mock API and send dummy data using REST but there is only loader in component and setupServer is not working
How do I solve this problem?
detail.tsx
import React, { FC, useEffect, useState } from 'react'; import { RouteComponentProps, useHistory, withRouter } from 'react-router-dom'; import { actorInfo, detailMovie, movieInfo, popularResponseType, } from '../../types'; import { fetcher, } from '../../utils/request'; import * as S from './styles'; import * as C from '../../utils/constants'; import Loader from '../Loader'; interface movieID { id: string; } const Detail: FC<RouteComponentProps<movieID>> = ({ match }) => { const [detail, setDetail] = useState<detailMovie>(); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(false); useEffect(() => { const getData = async () => { setIsLoading(true); const movieDetail: detailMovie = await fetcher(`https://api.themoviedb.org/3/movie/343611{API_KEY}&language=kr-KR`); setDetail(movieDetail); setIsLoading(false); }; getData(); }, []); if (error) { return <p>something went wrong</p>; } return ( isLoading ? ( <Loader /> ) <S.Container> <S.IntroduceContainer> {detail ? ( <S.Poster src={`${C.IMAGE_URL_W500}/${detail?.poster_path}`} /> ) : ( <S.Poster /> )} <S.InfoContainer> <S.Title>{detail?.title}</S.Title> <S.RunningTime>{`${detail?.runtime}분`}</S.RunningTime> <S.Description>{detail?.overview}</S.Description> </S.InfoContainer> </S.IntroduceContainer> </S.Container> ); }; export default withRouter(Detail);
detail.test.js
import React from 'react'; import { render, waitFor, screen } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import Detail from '../index'; import movieDetailDummy from '../../../dummy/movieDummy'; import { Route, MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; import { API_KEY, API_URL_MOVIE } from '../../../utils/constants'; const server = setupServer( rest.get(`https://api.themoviedb.org/3/movie/343611{API_KEY}&language=kr-KR`, (req, res, ctx) => { return res(ctx.status(200), ctx.json(movieDetailDummy)); }) ); beforeAll(() => server.listen()); afterAll(() => server.close()); afterEach(() => server.resetHandlers()); const renderComponenet = ({ movieID }) => render( <MemoryRouter initialEntries={[`/detail/${movieID}`]}> <Route path="/detail/:id"> <Detail /> </Route> </MemoryRouter> ); describe('<Detail />', () => { it('get movieDetail from tmdb', async () => { act(() => { renderComponent({ movieID: 343611 }); }); await waitFor(() => screen.getByText('잭 리처: 네버 고 백')); }); });
fetcher
export const fetcher = async (url: string) => { const response = await fetch(url); if (!response.ok) { const error = new Error('Error while fetching the data'); error.message = await response.json(); throw error; } const result = await response.json(); return result; };
-
Fetch does not return an object while using msw
I try to mock an api call using msw in a react app; handlers.ts:
import {rest} from 'msw'; export const handlers = [ rest.get('/functions', (req, res, ctx) => { return res( ctx.status(200), ctx.set('Content-Type', 'application/json'), ctx.delay(300), ctx.json([{id: 1, name: 'function1'}, {id: 2, name: 'function2'}]), ); }), ];
server.ts:
import {setupServer} from 'msw/node'; import {rest} from 'msw'; import {handlers} from './handlers'; const server = setupServer(...handlers); export {server, rest};
client.ts:
type Headers = Record<string, string>; interface Config { method: string; headers: Headers; body?: BodyInit | null; } interface ClientObject { method?: string; customConfig?: { headers?: Headers; }; body?: unknown; } export const client = async <T>( url: string, clientObj: ClientObject, ): Promise<T> => { const headers: Headers = { 'Content-Type': 'application/json', }; const config: Config = { method: clientObj.body ? 'POST' : 'GET', ...clientObj.customConfig, headers: { ...headers, ...(clientObj.customConfig ? clientObj.customConfig.headers : {}), }, }; if (clientObj.body) { config.body = JSON.stringify(clientObj.body); } let data; try { const response = await window.fetch(url, config); data = await response.json(); if (response.ok) { return data; } throw new Error(response.statusText); } catch (err) { return Promise.reject(err.message ? err.message : data); } }; client.get = <T>(url: string, clientObj: ClientObject = {}) => { return client<T>(url, clientObj); };
function.ts:
const getFunctions = async({code: string; version: number}) => { const data = await client.get(`/functions?code=${code}&version=${version}`); return data; });
FunctionComponent.tsx:
import React from 'react'; const FunctionList = ({code, version}: {code: string; version: number}) => { const [list, setList] = useState<{id: number, name: string}[]>([]); const [loading, setLoading] = useState('idle'); useEffect(() => { setLoading('pending'); getFunctions(code, version) .then((data) => { setList(data) setLoading('resolved') }) .catch((error) => setLoading('rejected')) }, [code, version]); let content; if (loading === 'pending') { content = <h1>Loading</h1> } else if(loading === 'rejected') { content = <h1>Internal error</h1> } else { content = ( <ul> {list && list.length ? list.map(f => <li>{f.name}</li>) : null} </ul> ) return content; }
FunctionList.test.tsx:
import React from 'react'; import '@testing-library/jest-dom/extend-expect'; import {render, screen} from 'test/CustomRender'; import FunctionList from './FunctionList'; describe('FunctionList', () => { test('Should render successfully the component', () => { render(<ReadFunctionList code="1" version="1" />); const titleLabel = screen.getByTitle('ap-functions-title'); expect(titleLabel).toBeInTheDocument(); }); });
The test failed because it needs to launch the getFunctions and return the result from the server. The msw handler is called but not returned by the fetch inside client.ts. How can I fix that,