Skip to content

Commit

Permalink
Order By with args (#339)
Browse files Browse the repository at this point in the history
* orderBy now accepts args

* test for orderby case

* signature for orderBy func

* no reversing of nulls

* [ci skip] rename test

* docs and test simplification

* test desc change
  • Loading branch information
sushantdhiman authored and mickhansen committed Oct 10, 2016
1 parent 6f30aee commit e3ac7de
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 15 deletions.
3 changes: 2 additions & 1 deletion docs/relay.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ const userTaskConnection = sequelizeConnection({
name: 'UserTaskOrderBy',
values: {
AGE: {value: ['createdAt', 'DESC']}, // The first ENUM value will be the default order. The direction will be used for `first`, will automatically be inversed for `last` lookups.
TITLE: {value: ['title', 'ASC']}
TITLE: {value: ['title', 'ASC']},
CUSTOM: {value: [function (source, args, context, info) {}, 'ASC']} // build and return custom order for sequelize orderBy option
}
}),
where: function (key, value) {
Expand Down
32 changes: 22 additions & 10 deletions src/relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,17 @@ export function sequelizeConnection({
}
};

let orderByAttribute = function (orderBy) {
return orderBy[0][0];
let orderByAttribute = function (orderAttr, {source, args, context, info}) {
return typeof orderAttr === 'function' ? orderAttr(source, args, context, info) : orderAttr;
};

let orderByDirection = function (orderDirection, args) {
if (args.last) {
return orderDirection.indexOf('ASC') >= 0
? orderDirection.replace('ASC', 'DESC')
: orderDirection.replace('DESC', 'ASC');
}
return orderDirection;
};

/**
Expand Down Expand Up @@ -211,22 +220,25 @@ export function sequelizeConnection({
}

let orderBy = args.orderBy;
let orderAttribute = orderByAttribute(orderBy);
let orderDirection = args.orderBy[0][1];

if (args.last) {
orderDirection = orderDirection === 'ASC' ? 'DESC' : 'ASC';
}
let orderAttribute = orderByAttribute(orderBy[0][0], {
source: info.source,
args,
context,
info
});
let orderDirection = orderByDirection(orderBy[0][1], args);

options.order = [
[orderAttribute, orderDirection]
];

if (orderAttribute !== model.primaryKeyAttribute) {
options.order.push([model.primaryKeyAttribute, 'ASC']);
options.order.push([model.primaryKeyAttribute, orderByDirection('ASC', args)]);
}

options.attributes.push(orderAttribute);
if (typeof orderAttribute === 'string') {
options.attributes.push(orderAttribute);
}

if (options.limit && !options.attributes.some(attribute => attribute.length === 2 && attribute[1] === 'full_count')) {
if (model.sequelize.dialect.name === 'postgres') {
Expand Down
65 changes: 61 additions & 4 deletions test/integration/relay/connection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe('relay', function () {
}
});

this.projectOrderSpy = sinon.spy(() => 'name');
this.projectTaskConnectionFieldSpy = sinon.spy();
this.projectTaskConnection = sequelizeConnection({
name: 'projectTask',
Expand All @@ -74,7 +75,9 @@ describe('relay', function () {
values: {
ID: {value: [this.Task.primaryKeyAttribute, 'ASC']},
LATEST: {value: ['createdAt', 'DESC']},
NAME: {value: ['name', 'ASC']}
NAME: {value: ['name', 'ASC']},
NAME_FUNC: {value: [this.projectOrderSpy, 'ASC']},
NAME_NULLS_LAST: {value: ['name', 'ASC NULLS LAST']}
}
}),
connectionFields: () => ({
Expand Down Expand Up @@ -479,6 +482,60 @@ describe('relay', function () {

});

it('should handle orderBy function case', async function () {
await graphql(this.schema, `
{
user(id: ${this.userA.id}) {
projects(first: 1) {
edges {
node {
tasks(orderBy: NAME_FUNC, first: 5) {
edges {
cursor
node {
id
name
}
}
}
}
}
}
}
}
`, null, {});

expect(this.projectOrderSpy).to.have.been.calledOnce;
expect(this.projectOrderSpy.alwaysCalledWithMatch({}, { first: 5 })).to.be.ok;
});

it('should properly reverse orderBy with NULLS and last', async function () {
let sqlSpy = sinon.spy();
await graphql(this.schema, `
{
user(id: ${this.userA.id}) {
projects(first: 1) {
edges {
node {
tasks(orderBy: NAME_NULLS_LAST, last: 10) {
edges {
cursor
node {
id
name
}
}
}
}
}
}
}
}
`, null, { logging: sqlSpy });

expect(sqlSpy.lastCall.args[0].match('DESC NULLS LAST')).to.be.ok;
});

it('should support in-query slicing and pagination with first and orderBy', async function () {
let firstThree = this.userA.tasks.slice(this.userA.tasks.length - 3, this.userA.tasks.length);
let nextThree = this.userA.tasks.slice(this.userA.tasks.length - 6, this.userA.tasks.length - 3);
Expand Down Expand Up @@ -641,7 +698,7 @@ describe('relay', function () {
});

it('should support pagination with where', async function () {
const completedTasks = this.userA.tasks.filter(task => task.completed)
const completedTasks = this.userA.tasks.filter(task => task.completed);

expect(completedTasks.length).to.equal(4);

Expand Down Expand Up @@ -934,8 +991,8 @@ describe('relay', function () {

const nodeNames = result.data.user.projects.edges.map(edge => {
return edge.node.tasks.edges.map(edge => {
return edge.node.name
}).sort()
return edge.node.name;
}).sort();
});
expect(nodeNames).to.deep.equal([
[
Expand Down

0 comments on commit e3ac7de

Please sign in to comment.