fix(connectionPlugin): allow first and last to be zero (#436)

Co-authored-by: Jason Kuhrt <jason.kuhrt@dialogue.co>
This commit is contained in:
Leonardo Dino 2020-07-01 19:49:09 +01:00 committed by GitHub
parent bf0df64ebd
commit 5b900b156a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 7 deletions

View File

@ -839,12 +839,12 @@ function defaultPageInfoFromNodes(nodes: any[], args: PaginationArgs) {
function defaultHasNextPage(nodes: any[], args: PaginationArgs) {
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
if (args.first) {
if (typeof args.first === "number") {
return nodes.length >= args.first;
}
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
// that we have a previous page
if (args.last) {
if (typeof args.last === "number") {
if (args.before && args.before !== "0") {
return true;
}
@ -860,7 +860,7 @@ function defaultHasNextPage(nodes: any[], args: PaginationArgs) {
function defaultHasPreviousPage(nodes: any[], args: PaginationArgs) {
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
if (args.first) {
if (typeof args.first === "number") {
if (args.after && args.after !== "0") {
return true;
}
@ -868,7 +868,7 @@ function defaultHasPreviousPage(nodes: any[], args: PaginationArgs) {
}
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
// that we have a previous page
if (args.last) {
if (typeof args.last === "number") {
return nodes.length >= args.last;
}
/* istanbul ignore next */
@ -888,7 +888,7 @@ function defaultCursorFromNode(
let cursorIndex = index;
// If we're paginating forward, assume we're incrementing from the offset provided via "after",
// e.g. [0...20] (first: 5, after: "cursor:5") -> [cursor:6, cursor:7, cursor:8, cursor:9, cursor: 10]
if (args.first) {
if (typeof args.first === "number") {
if (args.after) {
const offset = parseInt(args.after, 10);
cursorIndex = offset + index + 1;
@ -897,7 +897,7 @@ function defaultCursorFromNode(
// If we're paginating backward, assume we're working backward from the assumed length
// e.g. [0...20] (last: 5, before: "cursor:20") -> [cursor:15, cursor:16, cursor:17, cursor:18, cursor:19]
if (args.last) {
if (typeof args.last === "number") {
if (args.before) {
const offset = parseInt(args.before, 10);
cursorIndex = offset - args.last + index;
@ -1010,7 +1010,7 @@ function defaultValidateArgs(
args: Record<string, any> = {},
info: GraphQLResolveInfo
) {
if (!args.first && !args.last) {
if (!(args.first || args.first === 0) && !(args.last || args.last === 0)) {
throw new Error(
`The ${info.parentType}.${info.fieldName} connection field requires a "first" or "last" argument`
);

View File

@ -347,6 +347,50 @@ describe("connectionPlugin", () => {
});
});
it("default arg validation: allows first to be zero", async () => {
const schema = testConnectionSchema({});
const result = await execute({
schema,
document: UsersFieldFirst,
variableValues: { first: 0 },
});
expect(result).toEqual({
data: {
users: {
edges: [],
pageInfo: {
endCursor: null,
hasNextPage: true,
hasPreviousPage: false,
startCursor: null,
},
},
},
});
});
it("default arg validation: allows last to be zero", async () => {
const schema = testConnectionSchema({});
const result = await execute({
schema,
document: UsersFieldLast,
variableValues: { last: 0 },
});
expect(result).toEqual({
data: {
users: {
edges: [],
pageInfo: {
endCursor: null,
hasNextPage: false,
hasPreviousPage: true,
startCursor: null,
},
},
},
});
});
it("default arg validation: throws if both first & last are provided", async () => {
const schema = testConnectionSchema({});
const result = await execute({