Test coverage for pagination and search service.

This commit is contained in:
danny-mhlv 2022-08-18 19:52:50 +03:00
parent 5eb20c4727
commit 26cd205738
5 changed files with 379 additions and 228 deletions

View File

@ -1,8 +1,7 @@
import { HttpService } from "@nestjs/axios"; import { HttpService } from "@nestjs/axios";
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common"; import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
import { Observable, map, take } from "rxjs"; import { Observable, map, take } from "rxjs";
import { EsResponseDto, PageDto } from "../domain/dtos"; import { PageDto } from "../domain/dtos";
import { EsHitDto } from "../domain/dtos/es-hit.dto";
import { EsQueryDto } from "../domain/dtos/es-query.dto"; import { EsQueryDto } from "../domain/dtos/es-query.dto";
import { RequestDto } from "../domain/dtos/request.dto"; import { RequestDto } from "../domain/dtos/request.dto";
import { SearchQueryDto } from "../domain/dtos/search-q.dto"; import { SearchQueryDto } from "../domain/dtos/search-q.dto";
@ -10,12 +9,11 @@ import { EsTime } from "../domain/enums/es-time.enum";
import { Order } from "../domain/enums/page-order.enum"; import { Order } from "../domain/enums/page-order.enum";
import { PageMeta } from "../domain/interfaces"; import { PageMeta } from "../domain/interfaces";
import { EsPit } from "../domain/interfaces/es-pit.interface"; import { EsPit } from "../domain/interfaces/es-pit.interface";
import { SearchInfo } from "../domain/interfaces/search-info.interface";
/** /**
* Previous search data storage * Previous search data storage
*/ */
class PrevSearch implements SearchInfo { class PrevSearch {
/** /**
* Constructs an uninitialized object * Constructs an uninitialized object
*/ */
@ -28,17 +26,35 @@ class PrevSearch implements SearchInfo {
/** /**
* PIT object of the previous search * PIT object of the previous search
*/ */
pit: EsPit; private pit: EsPit;
set _pit(pit: EsPit) {
this.pit = pit;
}
get _pit(): EsPit {
return this.pit;
}
/** /**
* Tiebreaker and sort parameters * Tiebreaker and sort parameters
*/ */
tiebreaker: unknown[]; private tiebreaker: unknown[];
set _tiebreaker(tiebreaker: unknown[]) {
this.tiebreaker = tiebreaker;
}
get _tiebreaker(): unknown[] {
return this.tiebreaker;
}
/** /**
* Number of the previous page * Number of the previous page
*/ */
prevPage: number; private prevPage: number;
set _prevPage(page: number) {
this.prevPage = page;
}
get _prevPage(): number {
return this.prevPage;
}
/** /**
* Checks if there was the search before current one * Checks if there was the search before current one
@ -89,23 +105,23 @@ export class PageInterceptor implements NestInterceptor {
]; ];
if (this.prevSearch.isSet()) { if (this.prevSearch.isSet()) {
request.es_query.pit = this.prevSearch.pit; request.es_query.pit = this.prevSearch._pit;
request.es_query.search_after = this.prevSearch.tiebreaker; request.es_query.search_after = this.prevSearch._tiebreaker;
let limit = !query?.limit ? 10 : query.limit; let limit = !query?.limit ? 10 : query.limit;
request.es_query.size = limit * Math.abs(query.page - this.prevSearch.prevPage); request.es_query.size = limit * Math.abs(query.page - this.prevSearch._prevPage);
if (query.page < this.prevSearch.prevPage) { if (query.page < this.prevSearch._prevPage) {
request.es_query.sort = [{ _score: { order: 'asc' } }]; request.es_query.sort = [{ _score: { order: 'asc' } }];
request.es_query.size += limit - 1; request.es_query.size += limit - 1;
reverse = true; reverse = true;
} else if (query.page == this.prevSearch.prevPage) { } else if (query.page == this.prevSearch._prevPage) {
// Caching should be HERE // Caching should be HERE
request.es_query.sort = [{ _score: { order: 'asc' } }]; request.es_query.sort = [{ _score: { order: 'asc' } }];
reverse = true; reverse = true;
} }
} else { } else {
this.prevSearch.pit = request.es_query.pit = await this.getPIT(1); this.prevSearch._pit = request.es_query.pit = await this.getPIT(1);
let limit = !query?.limit ? 10 : query.limit; let limit = !query?.limit ? 10 : query.limit;
request.es_query.size = limit * query.page; request.es_query.size = limit * query.page;
@ -116,24 +132,24 @@ export class PageInterceptor implements NestInterceptor {
// Setting the page meta-data // Setting the page meta-data
let meta: PageMeta = { let meta: PageMeta = {
total: res.hits.total.value, total: res.hits.total.value,
pagenum: !query?.page ? 1 : query.page, pagenum: !query?.page ? 1 : +query.page,
order: query?.order?.toUpperCase() === Order.ASC ? Order.ASC : Order.DESC, order: query?.order?.toUpperCase() === Order.ASC ? Order.ASC : Order.DESC,
pagesize: !query?.limit ? 10 : query.limit,
hasNext: undefined, hasNext: undefined,
hasPrev: undefined, hasPrev: undefined,
pagesize: !query?.limit ? 10 : query.limit,
}; };
meta.hasNext = meta.pagenum * meta.pagesize < meta.total ? true : false; meta.hasNext = meta.pagenum * meta.pagesize < meta.total ? true : false;
meta.hasPrev = meta.pagenum != 1 ? true : false; meta.hasPrev = meta.pagenum != 1 ? true : false;
// Saving the search info // Saving the search info
this.prevSearch.pit.id = res.pit_id; this.prevSearch._pit.id = res.pit_id;
this.prevSearch.tiebreaker = res.hits.hits[res.hits.hits.length - 1]?.sort; this.prevSearch._tiebreaker = res.hits.hits[res.hits.hits.length - 1]?.sort;
this.prevSearch.prevPage = query.page; this.prevSearch._prevPage = query.page;
// Check if the performed search is a backward search // Check if the performed search is a backwards search
let data = res.hits.hits.slice(-meta.pagesize); let data = res.hits.hits.slice(-meta.pagesize);
if (reverse) { if (reverse) {
this.prevSearch.tiebreaker = data[0]?.sort; this.prevSearch._tiebreaker = data[0]?.sort;
data.reverse(); data.reverse();
reverse = false; reverse = false;
} }
@ -165,12 +181,12 @@ export class PageInterceptor implements NestInterceptor {
public async getPIT(alive: number, unit: EsTime = EsTime.min): Promise<EsPit> { public async getPIT(alive: number, unit: EsTime = EsTime.min): Promise<EsPit> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
(this.httpService.post<EsPit>(`http://localhost:${this.ES_PORT}/papers/_pit?keep_alive=${alive+unit}`) this.httpService.post<EsPit>(`http://localhost:${this.ES_PORT}/papers/_pit?keep_alive=${alive+unit}`)
.pipe(take(1), map(axiosRes => axiosRes.data)) .pipe(take(1), map(axiosRes => axiosRes.data))
.subscribe((res) => { .subscribe((res: EsPit) => {
res.keep_alive = alive + unit; res.keep_alive = alive + unit;
resolve(res); resolve(res);
})); });
} catch (error) { } catch (error) {
reject(error); reject(error);
} }

View File

@ -0,0 +1,82 @@
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import request from 'supertest'
import { AppModule } from "src/infrastructure/modules";
describe('E2E Testing of /papers', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleRef: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleRef.createNestApplication();
await app.init();
});
it('GET /papers/{uuid} | Should return one exact item on page', async () => {
const test = await request(app.getHttpServer())
.get('/papers/eeeb2d01-8315-454e-b33f-3d6caa25db42') // ??? Fetch a random object from DB
.expect(200);
// Checking received data
expect(test.body.data).toBeDefined();
expect(test.body.data.length).toBe(1);
expect(test.body.data[0].id).toBeDefined();
expect(test.body.data[0].title).toBeDefined();
expect(test.body.data[0].authors).toBeDefined();
expect(test.body.data[0].summary).toBeDefined();
expect(test.body.data[0].tags).toBeDefined();
expect(test.body.data[0].content).toBeDefined();
expect(test.body.data[0].id).toBe('eeeb2d01-8315-454e-b33f-3d6caa25db42');
// Checking received meta
expect(test.body.meta).toBeDefined();
expect(test.body.meta.total).toBeDefined();
expect(test.body.meta.pagenum).toBeDefined();
expect(test.body.meta.order).toBeDefined();
expect(test.body.meta.pagesize).toBeDefined();
expect(test.body.meta.hasNext).toBeDefined();
expect(test.body.meta.hasPrev).toBeDefined();
expect(test.body.meta.total).toBe(1);
expect(test.body.meta.pagenum).toBe(1);
});
it('GET /papers/search? | Should return multiple items', async () => {
const test = await request(app.getHttpServer())
.get('/papers/search?query=at&page=1')
.expect(200);
// Checking received data
expect(test.body.data).toBeDefined();
expect(test.body.data.length).toBeGreaterThan(0);
for (const paper of test.body.data) {
expect(paper.id).toBeDefined();
expect(paper.title).toBeDefined();
expect(paper.authors).toBeDefined();
expect(paper.summary).toBeDefined();
expect(paper.tags).toBeDefined();
expect(paper.content).toBeDefined();
}
// Checking received meta
expect(test.body.meta).toBeDefined();
expect(test.body.meta.total).toBeDefined();
expect(test.body.meta.pagenum).toBeDefined();
expect(test.body.meta.order).toBeDefined();
expect(test.body.meta.pagesize).toBeDefined();
expect(test.body.meta.hasNext).toBeDefined();
expect(test.body.meta.hasPrev).toBeDefined();
expect(test.body.meta.total).toBeGreaterThan(0);
expect(test.body.meta.pagenum).toBe(1);
});
afterAll(async () => {
await app.close();
})
});

View File

@ -1,12 +1,12 @@
import { HttpModule } from "@nestjs/axios"; import { HttpService } from "@nestjs/axios";
import { ConfigModule } from "@nestjs/config";
import { ModuleRef } from "@nestjs/core";
import { Test } from "@nestjs/testing"; import { Test } from "@nestjs/testing";
import exp from "constants";
import { Observable, of } from "rxjs"; import { Observable, of } from "rxjs";
import { PapersController } from "src/application"; import { EsTime, Order } from "src/core/domain";
import { Order } from "src/core/domain"; import { PageDto } from "src/core/domain/dtos";
import { PageDto, SearchQueryDto } from "src/core/domain/dtos"; import { HttpResponseException } from "src/core/exceptions";
import { PageInterceptor } from "src/core/interceptors/page.interceptor"; import { PageInterceptor } from "src/core/interceptors/page.interceptor";
import { SearchService } from "src/core/services/common/search.service";
const execCtxMock = { const execCtxMock = {
switchToHttp: jest.fn().mockReturnThis(), switchToHttp: jest.fn().mockReturnThis(),
@ -26,18 +26,31 @@ const callHandlerMock = {
describe('Unit tests for PageInterceptor', () => { describe('Unit tests for PageInterceptor', () => {
let pageInter: PageInterceptor; let pageInter: PageInterceptor;
let moduleRef; let httpService: HttpService;
beforeAll(async () => { beforeAll(async () => {
moduleRef = await Test.createTestingModule({ const moduleRef = await Test.createTestingModule({
imports: [HttpModule], providers: [
controllers: [PapersController], {
providers: [SearchService, PageInterceptor], provide: HttpService,
useValue: {
post: jest.fn(),
delete: jest.fn()
},
},
PageInterceptor,
],
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
expandVariables: true,
})
],
}).compile(); }).compile();
pageInter = moduleRef.get(PageInterceptor); pageInter = moduleRef.get(PageInterceptor);
httpService = moduleRef.get(HttpService);
pageInter.getPIT = jest.fn().mockReturnValue({});
execCtxMock.getRequest.mockReturnValue({ execCtxMock.getRequest.mockReturnValue({
query: { query: {
@ -48,19 +61,32 @@ describe('Unit tests for PageInterceptor', () => {
} }
}); });
callHandlerMock.handle.mockReturnValueOnce( callHandlerMock.handle.mockReturnValue(
of({ of({
hits: {
total: { value: 1 }, total: { value: 1 },
hits: { hits: [{}] } hits: [{}]
}
}) })
); );
}); });
it('Should be defined', () => { it('Should be defined', () => {
expect(pageInter).toBeDefined(); expect(pageInter).toBeDefined();
expect(httpService).toBeDefined();
}); });
describe('intercept()', () => { describe('intercept()', () => {
let tmp;
beforeAll(() => {
tmp = pageInter.getPIT;
pageInter.getPIT = jest.fn().mockReturnValue({});
});
afterAll(() => {
pageInter.getPIT = tmp;
});
it('Should return a Promise', () => { it('Should return a Promise', () => {
expect(pageInter.intercept(execCtxMock, callHandlerMock)).toBeInstanceOf(Promise); expect(pageInter.intercept(execCtxMock, callHandlerMock)).toBeInstanceOf(Promise);
}); });
@ -74,80 +100,233 @@ describe('Unit tests for PageInterceptor', () => {
}); });
}); });
it.todo('Should touch CallHandler.handle() method'); it('Should touch CallHandler.handle() method', () => {
let chHandleSpy = jest.spyOn(callHandlerMock, 'handle');
pageInter.intercept(execCtxMock, callHandlerMock);
// it('Should return an Observable with a page of type PageDto', (done) => { expect(chHandleSpy).toBeCalled();
// executionContext.getRequest.mockReturnValue( { query: new SearchQueryDto('someQuery', 1, 10, 'desc') });
// callHandler.handle.mockReturnValue( of({
// total: { value: 1 },
// hits: [{},],
// }));
// expect(pageInter.intercept(executionContext, callHandler)).toBeInstanceOf(Promise);
// pageInter.intercept(executionContext, callHandler).then(res => res.subscribe((data) => {
// expect(data).toBeInstanceOf(PageDto);
// done();
// }));
// })
// it('Should hold content on the returned page', (done) => {
// executionContext.getRequest.mockReturnValueOnce( { query: new SearchQueryDto('someQuery', 1, 10, 'desc') });
// callHandler.handle.mockReturnValueOnce(of({
// total: { value: 1 },
// hits: [{dummy: 'dum'}],
// }));
// pageInter.intercept(executionContext, callHandler).then(res => res.subscribe((data) => {
// expect(data).toEqual({
// data: expect.anything(),
// meta: expect.anything(),
// });
// done();
// }));
// });
// it('Should have next page', (done) => {
// executionContext.getRequest.mockReturnValue({ query: new SearchQueryDto('someQuery', 1, 5, 'desc') });
// callHandler.handle.mockReturnValue(of({
// total: { value: 10 },
// hits: Array(10).fill({dummy: 'dum'}, 0, 10),
// }));
// pageInter.intercept(executionContext, callHandler).then(res => res.subscribe((data) => {
// expect(data.meta.hasNext).toEqual(true);
// expect(data.meta.hasPrev).toEqual(false);
// done();
// }));
// });
// it('Should have correct meta-data', (done) => {
// executionContext.getRequest.mockReturnValue({ query: new SearchQueryDto('someQuery', 2, 5, 'asc') });
// callHandler.handle.mockReturnValue(of({
// total: { value: 15 },
// hits: Array(15).fill({dummy: 'dum'}, 0, 15),
// }));
// pageInter.intercept(executionContext, callHandler).then(res => res.subscribe((data) => {
// expect(data.meta).toEqual({
// total: 15,
// pagenum: 2,
// order: Order.ASC,
// hasNext: true,
// hasPrev: true,
// pagesize: 5
// });
// done();
// }));
// });
}); });
// describe('getPIT()', () => { it('Should construct a page with proper data on it', () => {
callHandlerMock.handle.mockReturnValueOnce(
of({
hits: {
total: { value: 1 },
hits: [{
_source: {
dummy: 'dum'
}
}]
}
})
);
// }); pageInter.intercept(execCtxMock, callHandlerMock).then((res) => {
res.subscribe((page) => {
expect(page.data.length).toBe(1);
expect(page.data[0]).toEqual({ dummy: 'dum' });
});
});
});
it('Should construct correct meta-data of the page', () => {
execCtxMock.getRequest.mockReturnValueOnce({
query: {
page: 5,
order: 'desc',
limit: 100,
}
});
callHandlerMock.handle.mockReturnValueOnce(
of({
hits: {
total: { value: 921 },
hits: []
}
})
);
pageInter.intercept(execCtxMock, callHandlerMock).then((res) => {
res.subscribe((page) => {
expect(page.meta).toEqual({
total: 921,
pagenum: 5,
order: 'desc',
hasNext: true,
hasPrev: true,
pagesize: 100
});
});
});
});
it('Should reverse the search results', () => {
execCtxMock.getRequest.mockReturnValueOnce({
query: {
page: 1,
order: 'desc',
limit: 3
}
});
pageInter['prevSearch']._prevPage = 3;
pageInter['prevSearch'].isSet = jest.fn().mockImplementationOnce(() => {
return true;
})
callHandlerMock.handle.mockReturnValueOnce(
of({
hits: {
total: { value: 1 },
hits: [
{ sort: ['1', 'less relevant'], _source: '1' },
{ sort: ['2', 'average'], _source: '2' },
{ sort: ['3', 'most relevant'], _source: '3' }
]
}
})
);
pageInter.intercept(execCtxMock, callHandlerMock).then((res) => {
res.subscribe((page) => {
expect(pageInter['prevSearch']._tiebreaker).toEqual(['1', 'less relevant']);
expect(page.data).toEqual(['3', '2', '1']);
});
});
});
});
describe('getPIT()', () => {
it('Should touch HttpService.post() method', () => {
let httpPostMock = jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
pageInter.getPIT(1);
expect(httpPostMock).toHaveBeenCalled();
});
it('Should contain correct port in the URI from .env', () => {
let httpPostMock = jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
pageInter.getPIT(1);
expect(httpPostMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=1m`);
});
it('Should touch HttpService with correct URI when time alive and time-unit are set', () => {
let httpPostMock = jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
let time = 2;
let unit = EsTime.sec;
pageInter.getPIT(time, unit);
expect(httpPostMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=${time+unit}`);
});
it('Should return error exeception when HttpService fails', () => {
jest.spyOn(httpService, 'post').mockImplementationOnce(() => {
throw HttpResponseException;
});
expect(pageInter.getPIT(1)).rejects.toEqual(HttpResponseException);
});
it('Should return a non-empty string when HttpService request succeedes', () => {
jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
data: {id: '2567', keep_alive: '1m'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
expect(pageInter.getPIT(1)).resolves.toEqual({
id: '2567',
keep_alive: '1m',
});
});
});
// describe('deletePIT()', () => { // describe('deletePIT()', () => {
// it('Should touch HttpService.delete() method', () => {
// let httpPostMock = jest.spyOn(httpService, 'delete').mockReturnValueOnce(of({
// data: {id: '2567'},
// status: 0,
// statusText: '',
// headers: {},
// config: {},
// }));
// pageInter.getPIT(1);
// expect(httpPostMock).toHaveBeenCalled();
// });
// it('Should contain correct port in the URI from .env', () => {
// let httpPostMock = jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
// data: {id: '2567'},
// status: 0,
// statusText: '',
// headers: {},
// config: {},
// }));
// pageInter.getPIT(1);
// expect(httpPostMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=1m`);
// });
// it('Should touch HttpService with correct URI when time alive and time-unit are set', () => {
// let httpPostMock = jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
// data: {id: '2567'},
// status: 0,
// statusText: '',
// headers: {},
// config: {},
// }));
// let time = 2;
// let unit = EsTime.sec;
// pageInter.getPIT(time, unit);
// expect(httpPostMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=${time+unit}`);
// });
// it('Should return error exeception when HttpService fails', () => {
// jest.spyOn(httpService, 'post').mockImplementationOnce(() => {
// throw HttpResponseException;
// });
// expect(pageInter.getPIT(1)).rejects.toEqual(HttpResponseException);
// });
// it('Should return a non-empty string when HttpService request succeedes', () => {
// jest.spyOn(httpService, 'post').mockReturnValueOnce(of({
// data: {id: '2567', keep_alive: '1m'},
// status: 0,
// statusText: '',
// headers: {},
// config: {},
// }));
// expect(pageInter.getPIT(1)).resolves.toEqual({
// id: '2567',
// keep_alive: '1m',
// });
// });
// }); // });
}); });

View File

@ -1,47 +0,0 @@
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import request from 'supertest'
import { AppModule } from "src/infrastructure/modules";
describe('E2E Testing of /papers', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleRef: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleRef.createNestApplication();
await app.init();
});
it('Should return one exact item on page', async () => {
return request(app.getHttpServer())
.get('/papers/eeeb2d01-8315-454e-b33f-3d6caa25db42')
.expect(200)
.expect((res) => {
res.body.data.length === 1;
})
.expect((res) => {
res.body.data[0]._source.id === 'eeeb2d01-8315-454e-b33f-3d6caa25db42';
});
});
it('Should return multiple items', async () => {
return request(app.getHttpServer())
.get('/papers/search?query=at&page=1')
.expect(200)
.expect((res) => {
res.body.data.length > 0;
})
.expect((res) => {
for (const value of res.body.data) {
if(Object.keys(value).length === 0) return false;
}
})
});
afterAll(async () => {
await app.close();
})
});

View File

@ -10,7 +10,6 @@ describe('Unit tests for SearchService', () => {
let searchService: SearchService; let searchService: SearchService;
let httpService: HttpService; let httpService: HttpService;
beforeAll(async () => { beforeAll(async () => {
const moduleRef = await Test.createTestingModule({ const moduleRef = await Test.createTestingModule({
providers: [ providers: [
@ -114,7 +113,6 @@ describe('Unit tests for SearchService', () => {
searchService.findByID('').catch((err) => { searchService.findByID('').catch((err) => {
expect(err).toBeInstanceOf(GatewayTimeoutException); expect(err).toBeInstanceOf(GatewayTimeoutException);
console.log(err)
}); });
}); });
@ -211,7 +209,6 @@ describe('Unit tests for SearchService', () => {
searchService.findByContext(null).catch((err) => { searchService.findByContext(null).catch((err) => {
expect(err).toBeInstanceOf(GatewayTimeoutException); expect(err).toBeInstanceOf(GatewayTimeoutException);
console.log(err)
}); });
}); });
@ -228,79 +225,3 @@ describe('Unit tests for SearchService', () => {
}); });
}); });
}); });
/**
* describe('getPIT()', () => {
it('Should touch HttpService.post() method', () => {
let postMock = jest.spyOn(httpService, 'post').mockReturnValue(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
searchService.getPIT(1);
expect(postMock).toHaveBeenCalled();
});
it('Should contain correct port in the URI from .env', () => {
let postMock = jest.spyOn(httpService, 'post').mockReturnValue(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
searchService.getPIT(1);
expect(postMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=1m`);
});
it('Should touch HttpService with correct URI when time alive and time-unit are set', () => {
let postMock = jest.spyOn(httpService, 'post').mockReturnValue(of({
data: {id: '2567'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
let time = 2;
let unit = EsTime.sec;
searchService.getPIT(time, unit);
expect(postMock).toHaveBeenCalledWith(`http://localhost:${process.env.ES_PORT}/papers/_pit?keep_alive=${time+unit}`);
});
it('Should return error exeception when HttpService fails', () => {
jest.spyOn(httpService, 'post').mockImplementation(() => {
throw HttpResponseException;
});
expect(searchService.getPIT(1)).rejects.toEqual(HttpResponseException);
});
it('Should return a non-empty string when HttpService request succeedes', () => {
jest.spyOn(httpService, 'post').mockReturnValue(of({
data: {id: '2567', keep_alive: '1m'},
status: 0,
statusText: '',
headers: {},
config: {},
}));
expect(searchService.getPIT(1)).resolves.toEqual({
id: '2567',
keep_alive: '1m',
});
});
});
describe('deletePIT()', () => {
it.todo('Should fail to delete, because the requested PIT ID is invalid');
it.todo('Should call HttpService.delete() method with correct body');
});
*/