From a316f9ab43932b0611ebf62bb61f05e200220789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Garapich?= Date: Tue, 20 Feb 2024 10:42:25 +0100 Subject: [PATCH] fix(etf2l): replace axios with native fetch --- src/etf2l/services/etf2l-api.service.spec.ts | 105 ++++--------------- src/etf2l/services/etf2l-api.service.ts | 43 ++------ 2 files changed, 29 insertions(+), 119 deletions(-) diff --git a/src/etf2l/services/etf2l-api.service.spec.ts b/src/etf2l/services/etf2l-api.service.spec.ts index b24687f0e..ffc2eb50f 100644 --- a/src/etf2l/services/etf2l-api.service.spec.ts +++ b/src/etf2l/services/etf2l-api.service.spec.ts @@ -1,25 +1,20 @@ -import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { Etf2lApiService } from './etf2l-api.service'; import { Etf2lProfile } from '../types/etf2l-profile'; -import { of, throwError } from 'rxjs'; -import { AxiosError, AxiosResponse, AxiosRequestHeaders } from 'axios'; import { Etf2lApiError } from '../errors/etf2l-api.error'; import { NoEtf2lAccountError } from '../errors/no-etf2l-account.error'; -jest.mock('@nestjs/axios'); +global.fetch = jest.fn(); describe('Etf2lApiService', () => { let service: Etf2lApiService; - let httpService: jest.Mocked; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [Etf2lApiService, HttpService], + providers: [Etf2lApiService], }).compile(); service = module.get(Etf2lApiService); - httpService = module.get(HttpService); }); it('should be defined', () => { @@ -50,59 +45,27 @@ describe('Etf2lApiService', () => { }; beforeEach(() => { - httpService.get.mockReturnValue( - of({ - status: 200, - data: { player: mockEtf2lProfile }, - } as AxiosResponse), - ); + (fetch as jest.MockedFunction).mockResolvedValue({ + ok: true, + json: () => Promise.resolve({ player: mockEtf2lProfile }), + } as Response); }); it('should query the etf2l.org endpoint', async () => { const profile = await service.fetchPlayerProfile('FAKE_STEAM_ID'); - expect(httpService.get).toHaveBeenCalledWith( + expect(fetch).toHaveBeenCalledWith( 'http://api-v2.etf2l.org/player/FAKE_STEAM_ID', ); expect(profile).toEqual(mockEtf2lProfile); }); - describe('when the profile does not exist - response with code 404', () => { - beforeEach(() => { - httpService.get.mockReturnValue( - of({ - status: 404, - } as AxiosResponse), - ); - }); - - it('should throw NoEtf2lAccountError', async () => { - await expect( - service.fetchPlayerProfile('FAKE_OTHER_STEAM_ID'), - ).rejects.toThrow(NoEtf2lAccountError); - }); - }); - - describe('when the profile does not exist - AxiosError', () => { + describe('when the profile does not exist', () => { beforeEach(() => { - const headers = {} as AxiosRequestHeaders; - httpService.get.mockReturnValue( - throwError( - () => - new AxiosError( - 'Request failed with status code 404', - '404', - undefined, - undefined, - { - status: 404, - statusText: 'NOT FOUND', - data: null, - config: { headers }, - headers, - }, - ), - ), - ); + (fetch as jest.MockedFunction).mockResolvedValue({ + ok: false, + status: 404, + statusText: 'Not Found', + } as Response); }); it('should throw NoEtf2lAccountError', async () => { @@ -112,43 +75,13 @@ describe('Etf2lApiService', () => { }); }); - describe('when the API fails - response with code 500', () => { - beforeEach(() => { - httpService.get.mockReturnValue( - of({ - status: 500, - } as AxiosResponse), - ); - }); - - it('should throw Etf2lApiError', async () => { - await expect( - service.fetchPlayerProfile('FAKE_OTHER_STEAM_ID'), - ).rejects.toThrow(Etf2lApiError); - }); - }); - - describe('when the API fails - AxiosError', () => { + describe('when the API fails', () => { beforeEach(() => { - const headers = {} as AxiosRequestHeaders; - httpService.get.mockReturnValue( - throwError( - () => - new AxiosError( - 'Request failed with status code 500', - '500', - undefined, - undefined, - { - status: 500, - statusText: 'INTERNAL SERVER ERROR', - data: null, - config: { headers }, - headers, - }, - ), - ), - ); + (fetch as jest.MockedFunction).mockResolvedValue({ + ok: false, + status: 500, + statusText: 'Internal Server Error', + } as Response); }); it('should throw Etf2lApiError', async () => { diff --git a/src/etf2l/services/etf2l-api.service.ts b/src/etf2l/services/etf2l-api.service.ts index b312cebc9..adc2fbb6f 100644 --- a/src/etf2l/services/etf2l-api.service.ts +++ b/src/etf2l/services/etf2l-api.service.ts @@ -1,11 +1,8 @@ import { etf2lApiEndpoint } from '@configs/urls'; -import { HttpService } from '@nestjs/axios'; import { Injectable } from '@nestjs/common'; -import { catchError, firstValueFrom, of, switchMap, throwError } from 'rxjs'; import { Etf2lApiError } from '../errors/etf2l-api.error'; import { NoEtf2lAccountError } from '../errors/no-etf2l-account.error'; import { Etf2lProfile } from '../types/etf2l-profile'; -import { AxiosError } from 'axios'; interface Etf2lPlayerResponse { player: Etf2lProfile; @@ -17,39 +14,19 @@ interface Etf2lPlayerResponse { @Injectable() export class Etf2lApiService { - constructor(private readonly httpService: HttpService) {} - async fetchPlayerProfile(steamIdOrEtf2lId: string): Promise { const url = `${etf2lApiEndpoint}/player/${steamIdOrEtf2lId}`; - return await firstValueFrom( - this.httpService.get(url).pipe( - catchError((err: AxiosError) => { - if (err.response?.status === 404) { - throw new NoEtf2lAccountError(steamIdOrEtf2lId); - } - throw new Etf2lApiError(url, `${err.code} ${err.message}`); - }), - switchMap((response) => { - switch (response.status) { - case 200: - return of(response.data.player); - case 404: - return throwError( - () => new NoEtf2lAccountError(steamIdOrEtf2lId), - ); + const response = await fetch(url); + if (response.ok) { + const data = (await response.json()) as Etf2lPlayerResponse; + return data.player; + } + + if (response.status === 404) { + throw new NoEtf2lAccountError(steamIdOrEtf2lId); + } - default: - return throwError( - () => - new Etf2lApiError( - url, - `${response.status} ${response.statusText}`, - ), - ); - } - }), - ), - ); + throw new Etf2lApiError(url, `${response.status} ${response.statusText}`); } }