Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: get application endpoint filters and pagination backoffice #1014

Merged
merged 5 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,34 @@ const APPLICATIONS_NI_FILTER_COLUMNS = [
{ Stage: 5, Region: 'South East', Proposal: 'EN01 - Generating Stations' }
];

const APPLICATIONS_BO_FILTER_COLUMNS = [
{
stage: 'pre_application',
regions: 'south_east',
sector: 'BC - Business and Commercial'
},
{
stage: 'recommendation',
regions: 'north_west',
sector: 'EN - Energy'
},
{
stage: 'post_decision',
regions: 'south_west',
sector: 'EN - Energy'
},
{
stage: 'pre_application',
regions: 'eastern',
sector: 'EN - Energy'
},
{
stage: 'post_decision',
regions: 'south_east',
sector: 'EN - Energy'
}
];

const APPLICATIONS_FO_FILTERS = [
{ name: 'stage', label: 'Pre-application', value: 'pre_application', count: 2 },
{ name: 'stage', label: 'Recommendation', value: 'recommendation', count: 1 },
Expand All @@ -579,6 +607,7 @@ module.exports = {
APPLICATION_FO,
APPLICATIONS_NI_DB,
APPLICATIONS_NI_FILTER_COLUMNS,
APPLICATIONS_BO_FILTER_COLUMNS,
APPLICATIONS_FO,
APPLICATIONS_FO_FILTERS,
APPLICATION_API_V1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ const {
APPLICATIONS_FO,
APPLICATIONS_FO_FILTERS,
APPLICATION_API_V1,
APPLICATION_FO
APPLICATION_FO,
APPLICATIONS_BO_FILTER_COLUMNS
} = require('../__data__/application');
const { request } = require('../__data__/supertest');
const { Op } = require('sequelize');

const mockFindUnique = jest.fn();
const mockCount = jest.fn();
const mockProjectFindMany = jest.fn();
jest.mock('../../src/lib/prisma', () => ({
prismaClient: {
project: {
findUnique: (query) => mockFindUnique(query),
findMany: (query) => mockProjectFindMany(query)
findMany: (query) => mockProjectFindMany(query),
count: (query) => mockCount(query)
}
}
}));
Expand Down Expand Up @@ -234,7 +237,13 @@ describe('/api/v1/applications', () => {
describe('when backOfficeIntegration.applications.getAllApplications is true', () => {
beforeEach(() => {
config.backOfficeIntegration.applications.getAllApplications = true;
mockProjectFindMany.mockResolvedValueOnce([APPLICATION_DB]);
mockProjectFindMany
// applications
.mockResolvedValueOnce([APPLICATION_DB])
// filters
.mockResolvedValueOnce(APPLICATIONS_BO_FILTER_COLUMNS)
.mockClear();
mockCount.mockResolvedValue(1);
});
it('happy path', async () => {
const response = await request.get('/api/v1/applications');
Expand All @@ -244,19 +253,135 @@ describe('/api/v1/applications', () => {
applications: [
{
...APPLICATION_API_V1,
DateOfDCOAcceptance_NonAcceptance: null,
sourceSystem: 'ODT'
sourceSystem: 'ODT',
DateOfDCOAcceptance_NonAcceptance: null
}
],
currentPage: 1,
itemsPerPage: 25,
totalItems: 1,
totalPages: 1,
totalItemsWithoutFilters: 0,
filters: []
totalItemsWithoutFilters: 1,
filters: APPLICATIONS_FO_FILTERS
});
});
it('with filters applied', async () => {
const queryString = [
'stage=acceptance',
'stage=recommendation',
'region=eastern',
'region=north_west',
'sector=energy',
'sector=transport'
].join('&');

const response = await request.get(`/api/v1/applications?${queryString}`);

expect(mockProjectFindMany).toHaveBeenNthCalledWith(1, {
include: { applicant: true },
orderBy: { projectName: 'asc' },
skip: 0,
take: 25,
where: {
AND: [
{
OR: [{ regions: { contains: 'eastern' } }, { regions: { contains: 'north_west' } }]
},
{
OR: [{ stage: 'acceptance' }, { stage: 'recommendation' }]
},
{
OR: [{ sector: { contains: 'energy' } }, { sector: { contains: 'transport' } }]
}
]
}
});
expect(response.status).toEqual(200);
});

it('with search term applied', async () => {
const response = await request.get('/api/v1/applications?searchTerm=London%20Resort');

expect(mockProjectFindMany).toBeCalledWith({
include: { applicant: true },
orderBy: { projectName: 'asc' },
skip: 0,
take: 25,
where: {
AND: [
{
OR: [
{ projectName: { contains: 'London Resort' } },
{
OR: [
{ applicant: { organisationName: { contains: 'London' } } },
{ applicant: { firstName: { contains: 'London' } } },
{ applicant: { lastName: { contains: 'London' } } }
]
},
{
OR: [
{ applicant: { organisationName: { contains: 'Resort' } } },
{ applicant: { firstName: { contains: 'Resort' } } },
{ applicant: { lastName: { contains: 'Resort' } } }
]
}
]
}
]
}
});

expect(response.status).toEqual(200);
});

it('with search term and filters applied', async () => {
const queryString = [
'stage=acceptance',
'stage=recommendation',
'region=eastern',
'region=north_west',
'sector=energy',
'sector=transport',
'searchTerm=Nuclear'
].join('&');

const response = await request.get(`/api/v1/applications?${queryString}`);

expect(mockProjectFindMany).toBeCalledWith({
include: { applicant: true },
orderBy: { projectName: 'asc' },
skip: 0,
take: 25,
where: {
AND: [
{
OR: [
{ projectName: { contains: 'Nuclear' } },
{
OR: [
{ applicant: { organisationName: { contains: 'Nuclear' } } },
{ applicant: { firstName: { contains: 'Nuclear' } } },
{ applicant: { lastName: { contains: 'Nuclear' } } }
]
}
]
},
{
OR: [{ regions: { contains: 'eastern' } }, { regions: { contains: 'north_west' } }]
},
{
OR: [{ stage: 'acceptance' }, { stage: 'recommendation' }]
},
{
OR: [{ sector: { contains: 'energy' } }, { sector: { contains: 'transport' } }]
}
]
}
});

expect(response.status).toEqual(200);
});
// TODO: ASB-2190 - pagination, filter, and sorting tests
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ const {
getByCaseReference,
getAllApplications
} = require('../../../src/repositories/project.backoffice.repository');

const { APPLICATION_DB } = require('../../__data__/application');
const mockFindUnique = jest.fn();
const mockFindMany = jest.fn();
const mockCount = jest.fn();

jest.mock('../../../src/lib/prisma', () => ({
prismaClient: {
project: {
findUnique: (query) => mockFindUnique(query),
findMany: (query) => mockFindMany(query)
findMany: (query) => mockFindMany(query),
count: (query) => mockCount(query)
}
}
}));
Expand All @@ -28,17 +31,133 @@ describe('project repository', () => {
});
});
describe('getAllApplications', () => {
it('calls findMany', async () => {
it('calls findMany with no options', async () => {
await getAllApplications();

expect(mockFindMany).toBeCalledWith({
include: { applicant: true }
include: { applicant: true },
where: {}
});
});
it('calls findMany with given pagination options', async () => {
const options = {
orderBy: { projectName: 'asc' },
offset: 0,
size: 10
};
await getAllApplications(options);

expect(mockFindMany).toBeCalledWith({
include: { applicant: true },
where: {},
orderBy: { projectName: 'asc' },
skip: 0,
take: 10
});
});
it('calls findMany with search term', async () => {
const searchTerm = 'test search';
await getAllApplications({ searchTerm });
expect(mockFindMany).toBeCalledWith({
include: { applicant: true },
where: {
AND: [
{
OR: [
{ projectName: { contains: searchTerm } },
{
OR: [
{ applicant: { organisationName: { contains: 'test' } } },
{ applicant: { firstName: { contains: 'test' } } },
{ applicant: { lastName: { contains: 'test' } } }
]
},
{
OR: [
{ applicant: { organisationName: { contains: 'search' } } },
{ applicant: { firstName: { contains: 'search' } } },
{ applicant: { lastName: { contains: 'search' } } }
]
}
]
}
]
}
});
});

it('calls findMany with filters', async () => {
const filters = {
region: ['eastern', 'north_west'],
stage: ['acceptance', 'recommendation'],
sector: ['energy', 'transport']
};
await getAllApplications({ filters });
expect(mockFindMany).toBeCalledWith({
include: { applicant: true },
where: {
AND: [
{
OR: [{ regions: { contains: 'eastern' } }, { regions: { contains: 'north_west' } }]
},
{
OR: [{ stage: 'acceptance' }, { stage: 'recommendation' }]
},
{
OR: [{ sector: { contains: 'energy' } }, { sector: { contains: 'transport' } }]
}
]
}
});
});

it('calls findMany with filters and search term', async () => {
const searchTerm = 'test';
const filters = {
region: ['eastern', 'north_west'],
stage: ['acceptance', 'recommendation'],
sector: ['energy', 'transport']
};
await getAllApplications({ filters, searchTerm });
expect(mockFindMany).toBeCalledWith({
include: { applicant: true },
where: {
AND: [
{
OR: [
{ projectName: { contains: searchTerm } },
{
OR: [
{ applicant: { organisationName: { contains: searchTerm } } },
{ applicant: { firstName: { contains: searchTerm } } },
{ applicant: { lastName: { contains: searchTerm } } }
]
}
]
},
{
OR: [{ regions: { contains: 'eastern' } }, { regions: { contains: 'north_west' } }]
},
{
OR: [{ stage: 'acceptance' }, { stage: 'recommendation' }]
},
{
OR: [{ sector: { contains: 'energy' } }, { sector: { contains: 'transport' } }]
}
]
}
});
});

it('calls count', async () => {
await getAllApplications();
expect(mockCount).toBeCalledWith({ where: {} });
});
it('returns all applications', async () => {
mockFindMany.mockResolvedValueOnce([]);
mockFindMany.mockResolvedValueOnce([APPLICATION_DB]);
mockCount.mockResolvedValueOnce(1);
const applications = await getAllApplications();
expect(applications).toEqual([]);
expect(applications).toEqual({ applications: [APPLICATION_DB], count: 1 });
});
});
});
Loading
Loading