Skip to content

Commit 937a682

Browse files
committed
feat(ConnectionResolver): Add fallback algorithm, which uses limit and skip.
This algorithm does not garantee absence of records overfetching or underfetching. Use connection with sorting by unique indexed fields and provided proper config for composeWithConnection method.
1 parent d1145ff commit 937a682

File tree

5 files changed

+283
-55
lines changed

5 files changed

+283
-55
lines changed

src/__tests__/connectionResolver-test.js

Lines changed: 168 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,36 @@ describe('connectionResolver', () => {
402402
expect(result).deep.property('edges.0.node.id').equals(8);
403403
expect(result).deep.property('edges.1.node.id').equals(9);
404404
expect(result).deep.property('edges.2.node.id').equals(10);
405-
expect(result).deep.property('count').equals(7);
405+
expect(result).deep.property('count').equals(15);
406+
});
407+
408+
it('should correctly prepare cursor for before and after args', async () => {
409+
const result = await connectionResolver.resolve({
410+
args: {
411+
sort: sortOptions.ID_ASC.value,
412+
first: 3,
413+
},
414+
});
415+
expect(result).deep.property('edges').to.have.length(3);
416+
const cursor = result.edges[1].cursor;
417+
const prev = await connectionResolver.resolve({
418+
args: {
419+
sort: sortOptions.ID_ASC.value,
420+
first: 1,
421+
before: cursor,
422+
},
423+
});
424+
expect(prev).deep.property('edges.0.node.id')
425+
.equals(result.edges[0].node.id);
426+
const next = await connectionResolver.resolve({
427+
args: {
428+
sort: sortOptions.ID_ASC.value,
429+
first: 1,
430+
after: cursor,
431+
},
432+
});
433+
expect(next).deep.property('edges.0.node.id')
434+
.equals(result.edges[2].node.id);
406435
});
407436
});
408437
});
@@ -421,10 +450,147 @@ describe('connectionResolver', () => {
421450
});
422451
expect(result).deep.property('edges').to.have.length(8);
423452
expect(result).deep.property('edges.0.node')
424-
.deep.equals({ id: 1, name: 'user1', age: 11, gender: 'm' });
453+
.deep.equals({ id: 1, name: 'user01', age: 11, gender: 'm' });
425454
expect(result).deep.property('edges.7.node')
426455
.deep.equals({ id: 15, name: 'user15', age: 45, gender: 'm' });
427456
expect(result).deep.property('count').equals(8);
428457
});
429458
});
459+
460+
describe('fallback logic (offset in cursor)', () => {
461+
it('if `after` cursor is set, should return next record', async () => {
462+
const result = await connectionResolver.resolve({
463+
args: {
464+
after: dataToCursor(1),
465+
sort: { name: 1 },
466+
first: 1,
467+
},
468+
});
469+
expect(result).deep.property('edges.0.node.id').equals(3);
470+
});
471+
472+
it('if `before` cursor is set, should return previous record', async () => {
473+
const result = await connectionResolver.resolve({
474+
args: {
475+
before: dataToCursor(1),
476+
sort: { name: 1 },
477+
first: 1,
478+
},
479+
});
480+
expect(result).deep.property('edges.0.node.id').equals(1);
481+
});
482+
483+
it('if `before` and `after` cursors are set, should return between records', async () => {
484+
const result = await connectionResolver.resolve({
485+
args: {
486+
after: dataToCursor(1),
487+
before: dataToCursor(5),
488+
sort: { name: 1 },
489+
first: 10,
490+
},
491+
});
492+
expect(result).deep.property('edges').to.have.length(3);
493+
expect(result).deep.property('edges.0.node.id').equals(3);
494+
expect(result).deep.property('edges.1.node.id').equals(4);
495+
expect(result).deep.property('edges.2.node.id').equals(5);
496+
});
497+
498+
it('should throw error if `first` is less than 0', async () => {
499+
const promise = connectionResolver.resolve({
500+
args: {
501+
first: -5,
502+
sort: { name: 1 },
503+
},
504+
});
505+
await expect(promise).be.rejectedWith(Error, 'should be non-negative number');
506+
});
507+
508+
it('should slice edges to be length of `first`, if length is greater', async () => {
509+
const result = await connectionResolver.resolve({
510+
args: {
511+
sort: { name: 1 },
512+
first: 5,
513+
},
514+
});
515+
expect(result).deep.property('edges').to.have.length(5);
516+
});
517+
518+
it('should throw error if `last` is less than 0', async () => {
519+
const promise = connectionResolver.resolve({
520+
args: {
521+
last: -5,
522+
sort: { name: 1 },
523+
},
524+
});
525+
await expect(promise).be.rejectedWith(Error, 'should be non-negative number');
526+
});
527+
528+
it('should slice edges to be length of `last`', async () => {
529+
const result = await connectionResolver.resolve({
530+
args: {
531+
sort: { name: 1 },
532+
last: 3,
533+
},
534+
});
535+
expect(result).deep.property('edges').to.have.length(3);
536+
});
537+
538+
it('should slice edges to be length of `last`, if `first` and `last` present', async () => {
539+
const result = await connectionResolver.resolve({
540+
args: {
541+
sort: { name: 1 },
542+
first: 5,
543+
last: 2,
544+
},
545+
});
546+
expect(result).deep.property('edges').to.have.length(2);
547+
});
548+
549+
it('serve complex fetching with all connection args', async () => {
550+
const result = await connectionResolver.resolve({
551+
args: {
552+
sort: { name: 1 },
553+
after: dataToCursor(4),
554+
before: dataToCursor(12),
555+
first: 5,
556+
last: 3,
557+
},
558+
projection: { count: 1 },
559+
});
560+
expect(result).deep.property('edges').to.have.length(3);
561+
expect(result).deep.property('edges.0.node.id').equals(8);
562+
expect(result).deep.property('edges.1.node.id').equals(9);
563+
expect(result).deep.property('edges.2.node.id').equals(10);
564+
expect(result).deep.property('count').equals(15);
565+
});
566+
567+
it('should correctly prepare cursor for before and after args', async () => {
568+
const result = await connectionResolver.resolve({
569+
args: {
570+
sort: { name: 1 },
571+
first: 3,
572+
},
573+
});
574+
expect(result).deep.property('edges').to.have.length(3);
575+
const cursor = result.edges[1].cursor;
576+
const prev = await connectionResolver.resolve({
577+
args: {
578+
sort: { name: 1 },
579+
first: 1,
580+
before: cursor,
581+
},
582+
});
583+
expect(prev).deep.property('edges.0.node.id')
584+
.equals(result.edges[0].node.id);
585+
const next = await connectionResolver.resolve({
586+
args: {
587+
sort: { name: 1 },
588+
first: 1,
589+
after: cursor,
590+
},
591+
});
592+
expect(next).deep.property('edges.0.node.id')
593+
.equals(result.edges[2].node.id);
594+
});
595+
});
430596
});

0 commit comments

Comments
 (0)