Merge pull request #387 from jdalrymple/385-pagination-tests

Extending pagination tests to ensure proper functionality
This commit is contained in:
Justin Dalrymple 2019-07-15 10:15:18 -04:00 committed by GitHub
commit f59d51d15d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 158 additions and 119 deletions

View File

@ -69,7 +69,7 @@ methods.forEach(m => {
e.description = output.error || output.message;
}
throw e;
}

View File

@ -21,15 +21,16 @@ export async function get(
query: query || {},
sudo,
});
const { headers } = response;
let { body } = response;
let pagination = {
total: headers['x-total'],
total: parseInt(headers['x-total'], 10),
next: parseInt(headers['x-next-page'], 10) || null,
current: parseInt(headers['x-page'], 10) || 1,
previous: headers['x-prev-page'] || null,
perPage: headers['x-per-page'],
totalPages: headers['x-total-pages'],
previous: parseInt(headers['x-prev-page'], 10) || null,
perPage: parseInt(headers['x-per-page'], 10),
totalPages: parseInt(headers['x-total-pages'], 10),
};
const underLimit = maxPages ? pagination.current < maxPages : true;

View File

@ -14,10 +14,10 @@ class Labels extends BaseService {
return RequestHelper.get(this, `projects/${pId}/labels`, options);
}
create(projectId: ProjectId, options?: BaseRequestOptions) {
create(projectId: ProjectId, labelName: string, color: string, options?: BaseRequestOptions) {
const pId = encodeURIComponent(projectId);
return RequestHelper.post(this, `projects/${pId}/labels`, options);
return RequestHelper.post(this, `projects/${pId}/labels`, { name: labelName, color, ...options });
}
edit(projectId: ProjectId, labelName: string, options?: BaseRequestOptions) {

View File

@ -49,20 +49,20 @@ describe('Issues.all', () => {
const issues = await service.all();
expect(issues).toBeInstanceOf(Array);
expect(issues.length).toEqual(2);
expect(issues).toHaveLength(2);
});
it('should return a list filtered to a specfic page', async () => {
const issues1 = await service.all({projectId: project.id, perPage: 1, page: 1 });
expect(issues1).toBeInstanceOf(Array);
expect(issues1.length).toEqual(1);
expect(issues1).toHaveLength(1);
expect(issues1[0].title).toBe('Issue Integration test2');
const issues2 = await service.all({ projectId: project.id, perPage: 1, page: 2 });
expect(issues2).toBeInstanceOf(Array);
expect(issues2.length).toEqual(1);
expect(issues2).toHaveLength(1);
expect(issues2[0].title).toBe('Issue Integration test1');
});
});

View File

@ -0,0 +1,78 @@
import { Labels, Projects } from '../../../dist';
const config = {
host: process.env.GITLAB_URL,
token: process.env.PERSONAL_ACCESS_TOKEN,
};
let project;
let service: Labels;
beforeAll(async () => {
// Crease project service
const projectService = new Projects(config);
// Create issue service
service = new Labels(config);
// Create a template project
project = await projectService.create({ name: 'Labels Integration test' });
});
describe('Labels.create', () => {
it('should create a valid label on a project', async () => {
const label = await service.create(project.id, 'Test Label1', '#FFAABB');
expect(label).toBeInstanceOf(Object);
expect(label.name).toBe('Test Label1');
});
});
describe('Labels.remove', () => {
it('should remove/delete a valid label on a project', async () => {
const label = await service.create(project.id, 'Test Label3', '#FFAABB');
expect(service.remove(project.id, label.name)).resolves.toEqual("");
});
});
describe('Labels.all', () => {
beforeAll(async () => {
const labels: object[] = [];
for (let i = 0; i < 50; i++) {
labels.push(service.create(project.id, `All Labels ${i}`, '#FFAABB'));
}
return Promise.all(labels);
});
it('should return a list of labels on a project', async () => {
const labels = await service.all(project.id, { perPage: 3 });
const filtered = labels.filter(l => l.name.includes('All Labels'));
expect(labels).toBeInstanceOf(Array);
expect(filtered).toHaveLength(50);
});
it('should return a list of labels on a project restricted to page 5', async () => {
const labels = await service.all(project.id, { perPage: 5, page: 5});
expect(labels).toBeInstanceOf(Array);
expect(labels).toHaveLength(5);
});
it('should return a list of labels on a project restricted to page 5 and show the pagination object', async () => {
const { data, pagination } = await service.all(project.id, { perPage: 5, page: 5, showPagination: true});
expect(data).toBeInstanceOf(Array);
expect(data).toHaveLength(5);
expect(pagination).toMatchObject({
total: 51, // TODO: change this to not depend on previous data
previous: 4,
current: 5,
next: 6,
perPage: 5,
totalPages: 11,
});
});
});

View File

@ -11,112 +11,59 @@ const mockedGetBasic = () => ({
},
});
const mockedGetExtended = (url, { query }) => {
const pages = [
{
body: [
{
prop1: 1,
prop2: 'test property1',
},
{
prop1: 2,
prop2: 'test property2',
},
],
headers: {
link: `<https://www.test.com/api/v4/test?page=2&per_page=2>; rel="next",
<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="first",
<https://www.test.com/api/v4/test?page=4&per_page=2>; rel="last"`,
'x-next-page': 2,
'x-page': 1,
'x-per-page': 2,
'x-prev-page': '',
'x-total': 8,
'x-total-pages': 4,
},
},
{
body: [
{
prop1: 3,
prop2: 'test property3',
},
{
prop1: 4,
prop2: 'test property4',
},
],
headers: {
link: `<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="prev",
<https://www.test.com/api/v4/test?page=3&per_page=2>; rel="next",
<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="first",
<https://www.test.com/api/v4/test?page=4&per_page=2>; rel="last"`,
'x-next-page': 3,
'x-page': 2,
'x-per-page': 2,
'x-prev-page': 1,
'x-total': 8,
'x-total-pages': 4,
},
},
{
body: [
{
prop1: 5,
prop2: 'test property5',
},
{
prop1: 6,
prop2: 'test property6',
},
],
headers: {
link: `<https://www.test.com/api/v4/test?page=2&per_page=2>; rel="prev",
<https://www.test.com/api/v4/test?page=4&per_page=2>; rel="next",
<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="first",
<https://www.test.com/api/v4/test?page=4&per_page=2>; rel="last"`,
'x-next-page': 4,
'x-page': 3,
'x-per-page': 2,
'x-prev-page': 2,
'x-total': 8,
'x-total-pages': 4,
},
},
{
body: [
{
prop1: 7,
prop2: 'test property7',
},
{
prop1: 8,
prop2: 'test property8',
},
],
headers: {
link: `<https://www.test.com/api/v4/test?page=3&per_page=2>; rel="prev",
<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="first",
<https://www.test.com/api/v4/test?page=4&per_page=2>; rel="last"`,
'x-next-page': '',
'x-page': 4,
'x-per-page': 2,
'x-prev-page': 3,
'x-total': 8,
'x-total-pages': 4,
},
},
];
const mockedGetExtended = (url, { query }, limit=30) => {
const pages: object[] = [];
const q = url.match(/page=([0-9]+)/);
let page = 1;
if (q != null) page = q[1];
else if (query.page) page = query.page;
// Only load pages needed for the test
// TODO: modify this to only generate the required response, without the loop
for (let i = 1, a = 1, b = 2; i <= limit && i <= page; i++, a+=2, b+=2) {
let next = '';
let prev = '';
let nextPage;
let prevPage;
if ((i+1) <= limit ) {
next = `<https://www.test.com/api/v4/test?page=${i+1}&per_page=2>; rel="next",`;
nextPage = i+1
}
if ((i-1) >= 1) {
prev = `<https://www.test.com/api/v4/test?page=${i-1}&per_page=2>; rel="prev",`;
prevPage = i-1
}
pages.push({
body: [
{
prop1: a,
prop2: `test property ${a}`,
},
{
prop1: b,
prop2: `test property ${b}`,
},
],
headers: {
link: next + prev + `
<https://www.test.com/api/v4/test?page=1&per_page=2>; rel="first",
<https://www.test.com/api/v4/test?page=${limit}&per_page=2>; rel="last"`,
'x-next-page': nextPage,
'x-page': i,
'x-per-page': 2,
'x-prev-page': prevPage,
'x-total': limit * 2,
'x-total-pages': limit,
},
});
}
return pages[page - 1];
};
}
const service = new BaseService({
host: 'https://testing.com',
@ -151,10 +98,23 @@ describe('RequestHelper.get()', () => {
response.forEach((l, index) => {
expect(l.prop1).toBe(1 + index);
expect(l.prop2).toBe(`test property${1 + index}`);
expect(l.prop2).toBe(`test property ${1 + index}`);
});
expect(response).toHaveLength(8);
expect(response).toHaveLength(60);
});
it('Should handle large paginated (50 pages) results when links are present', async () => {
KyRequester.get = jest.fn(({}, url, options) => mockedGetExtended(url, options, 70));
const response = await RequestHelper.get(service, 'test');
response.forEach((l, index) => {
expect(l.prop1).toBe(1 + index);
expect(l.prop2).toBe(`test property ${1 + index}`);
});
expect(response).toHaveLength(140);
});
it('Should be paginated but limited by the maxPages option', async () => {
@ -166,7 +126,7 @@ describe('RequestHelper.get()', () => {
response.forEach((l, index) => {
expect(l.prop1).toBe(1 + index);
expect(l.prop2).toBe(`test property${1 + index}`);
expect(l.prop2).toBe(`test property ${1 + index}`);
});
});
@ -179,7 +139,7 @@ describe('RequestHelper.get()', () => {
response.forEach((l, index) => {
expect(l.prop1).toBe(3 + index);
expect(l.prop2).toBe(`test property${3 + index}`);
expect(l.prop2).toBe(`test property ${3 + index}`);
});
});
@ -192,16 +152,16 @@ describe('RequestHelper.get()', () => {
response.data.forEach((l, index) => {
expect(l.prop1).toBe(3 + index);
expect(l.prop2).toBe(`test property${3 + index}`);
expect(l.prop2).toBe(`test property ${3 + index}`);
});
expect(response.pagination).toMatchObject({
total: 8,
total: 60,
previous: 1,
current: 2,
next: 3,
perPage: 2,
totalPages: 4,
totalPages: 30,
});
});
@ -217,16 +177,16 @@ describe('RequestHelper.get()', () => {
response.data.forEach((l, index) => {
expect(l.prop1).toBe(1 + index);
expect(l.prop2).toBe(`test property${1 + index}`);
expect(l.prop2).toBe(`test property ${1 + index}`);
});
expect(response.pagination).toMatchObject({
total: 8,
total: 60,
previous: 2,
current: 3,
next: 4,
perPage: 2,
totalPages: 4,
totalPages: 30,
});
});
});