|
|
@@ -36,20 +36,27 @@ vi.mock('./get-toppage-viewers-count', () => ({
|
|
|
}));
|
|
|
|
|
|
describe('listPages', () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ vi.clearAllMocks();
|
|
|
+ });
|
|
|
+
|
|
|
it("returns 400 HTTP response when the query 'pagePath' is undefined", async () => {
|
|
|
// setup
|
|
|
const reqMock = mock<IListPagesRequest>();
|
|
|
+ reqMock.query = { pagePath: '' };
|
|
|
+
|
|
|
const resMock = mock<Response>();
|
|
|
const resStatusMock = mock<Response>();
|
|
|
- resMock.status.calledWith(400).mockReturnValue(resStatusMock);
|
|
|
+ resMock.status.mockReturnValue(resStatusMock);
|
|
|
+
|
|
|
+ mocks.generateBaseQueryMock.mockRejectedValue(
|
|
|
+ createError(400, 'pagePath is required'),
|
|
|
+ );
|
|
|
|
|
|
- // when
|
|
|
- await listPages(reqMock, resMock);
|
|
|
+ const handler = listPages({ excludedPaths: [] });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
|
|
|
- // then
|
|
|
- expect(resMock.status).toHaveBeenCalledOnce();
|
|
|
- expect(resStatusMock.send).toHaveBeenCalledOnce();
|
|
|
- expect(mocks.generateBaseQueryMock).not.toHaveBeenCalled();
|
|
|
+ expect(resMock.status).toHaveBeenCalledWith(400);
|
|
|
});
|
|
|
|
|
|
describe('with num option', () => {
|
|
|
@@ -58,12 +65,16 @@ describe('listPages', () => {
|
|
|
|
|
|
const builderMock = mock<PageQueryBuilder>();
|
|
|
|
|
|
- mocks.generateBaseQueryMock.mockResolvedValue(builderMock);
|
|
|
- mocks.getToppageViewersCountMock.mockImplementation(() => 99);
|
|
|
-
|
|
|
const queryMock = mock<PageQuery>();
|
|
|
builderMock.query = queryMock;
|
|
|
|
|
|
+ beforeEach(() => {
|
|
|
+ mocks.generateBaseQueryMock.mockResolvedValue(builderMock);
|
|
|
+ mocks.getToppageViewersCountMock.mockImplementation(() => 99);
|
|
|
+
|
|
|
+ queryMock.and.mockReturnValue(queryMock);
|
|
|
+ });
|
|
|
+
|
|
|
it('returns 200 HTTP response', async () => {
|
|
|
// setup query.clone().count()
|
|
|
const queryClonedMock = mock<PageQuery>();
|
|
|
@@ -85,7 +96,8 @@ describe('listPages', () => {
|
|
|
resMock.status.calledWith(200).mockReturnValue(resStatusMock);
|
|
|
|
|
|
// when
|
|
|
- await listPages(reqMock, resMock);
|
|
|
+ const handler = listPages({ excludedPaths: [] });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
|
|
|
// then
|
|
|
expect(mocks.generateBaseQueryMock).toHaveBeenCalledOnce();
|
|
|
@@ -118,7 +130,8 @@ describe('listPages', () => {
|
|
|
resMock.status.calledWith(500).mockReturnValue(resStatusMock);
|
|
|
|
|
|
// when
|
|
|
- await listPages(reqMock, resMock);
|
|
|
+ const handler = listPages({ excludedPaths: [] });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
|
|
|
// then
|
|
|
expect(mocks.generateBaseQueryMock).toHaveBeenCalledOnce();
|
|
|
@@ -147,7 +160,8 @@ describe('listPages', () => {
|
|
|
resMock.status.calledWith(400).mockReturnValue(resStatusMock);
|
|
|
|
|
|
// when
|
|
|
- await listPages(reqMock, resMock);
|
|
|
+ const handler = listPages({ excludedPaths: [] });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
|
|
|
// then
|
|
|
expect(mocks.generateBaseQueryMock).toHaveBeenCalledOnce();
|
|
|
@@ -243,3 +257,67 @@ describe('listPages', () => {
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
+
|
|
|
+describe('when excludedPaths is handled', () => {
|
|
|
+ const pagePath = '/Sandbox';
|
|
|
+ const builderMock = mock<PageQueryBuilder>();
|
|
|
+ const queryMock = mock<PageQuery>();
|
|
|
+ builderMock.query = queryMock;
|
|
|
+
|
|
|
+ beforeEach(() => {
|
|
|
+ mocks.generateBaseQueryMock.mockResolvedValue(builderMock);
|
|
|
+ queryMock.and.mockReturnValue(queryMock);
|
|
|
+
|
|
|
+ // Setup successful flow for count and exec
|
|
|
+ const queryClonedMock = mock<PageQuery>();
|
|
|
+ queryMock.clone.mockReturnValue(queryClonedMock);
|
|
|
+ queryClonedMock.count.mockResolvedValue(0);
|
|
|
+ queryMock.exec.mockResolvedValue([]);
|
|
|
+
|
|
|
+ mocks.addNumConditionMock.mockReturnValue(queryMock);
|
|
|
+ mocks.addSortConditionMock.mockReturnValue(queryMock);
|
|
|
+ mocks.getToppageViewersCountMock.mockResolvedValue(0);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('does not add path exclusion conditions when excludedPaths is empty', async () => {
|
|
|
+ // setup
|
|
|
+ const reqMock = mock<IListPagesRequest>();
|
|
|
+ reqMock.query = { pagePath };
|
|
|
+ const resMock = mock<Response>();
|
|
|
+ resMock.status.mockReturnValue(mock<Response>());
|
|
|
+
|
|
|
+ // excludedPaths is empty
|
|
|
+ const handler = listPages({ excludedPaths: [] });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
+
|
|
|
+ // query.and should NOT be called with a $not regex for paths
|
|
|
+ expect(queryMock.and).not.toHaveBeenCalledWith(
|
|
|
+ expect.arrayContaining([
|
|
|
+ expect.objectContaining({
|
|
|
+ path: expect.objectContaining({ $not: expect.any(RegExp) }),
|
|
|
+ }),
|
|
|
+ ]),
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it('adds a regex exclusion condition when excludedPaths is specified', async () => {
|
|
|
+ // setup
|
|
|
+ const reqMock = mock<IListPagesRequest>();
|
|
|
+ reqMock.query = { pagePath };
|
|
|
+ const resMock = mock<Response>();
|
|
|
+ resMock.status.mockReturnValue(mock<Response>());
|
|
|
+
|
|
|
+ // excludedPaths provided
|
|
|
+ const excludedPaths = ['/user', '/tmp'];
|
|
|
+ const handler = listPages({ excludedPaths });
|
|
|
+ await handler(reqMock, resMock);
|
|
|
+
|
|
|
+ // check if the logic generates the correct regex: ^\/(user|tmp)(\/|$)
|
|
|
+ const expectedRegex = /^\/(user|tmp)(\/|$)/;
|
|
|
+ expect(queryMock.and).toHaveBeenCalledWith([
|
|
|
+ {
|
|
|
+ path: { $not: expectedRegex },
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+});
|