Skip to content

Commit

Permalink
feat: expands knex query coverage on models (#691)
Browse files Browse the repository at this point in the history
  • Loading branch information
willviles authored and zacharygolba committed May 2, 2017
1 parent dd200af commit df96fd6
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 2 deletions.
10 changes: 10 additions & 0 deletions src/packages/database/model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,16 @@ class Model {
return new Query(this).where(conditions);
}

static whereBetween(conditions: Object): Query<Array<this>> {
return new Query(this).whereBetween(conditions);
}

static whereRaw(
query: string,
bindings: Array<any> = []): Query<Array<this>> {
return new Query(this).whereRaw(query, bindings);
}

static not(conditions: Object): Query<Array<this>> {
return new Query(this).not(conditions);
}
Expand Down
42 changes: 41 additions & 1 deletion src/packages/database/query/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,21 @@ class Query<+T: any> extends Promise {

if (Array.isArray(value)) {
if (value.length > 1) {
this.snapshots.push([not ? 'whereNotIn' : 'whereIn', [key, value]]);
this.snapshots.push([
not ? 'whereNotIn' : 'whereIn',
[key, value]
]);
} else {
return {
...obj,
[key]: value[0]
};
}
} else if (value === null) {
this.snapshots.push([
not ? 'whereNotNull' : 'whereNull',
[key]
]);
} else {
return {
...obj,
Expand All @@ -221,6 +229,38 @@ class Query<+T: any> extends Promise {
return this;
}

whereBetween(conditions: Object, not: boolean = false): this {
const {
model: {
tableName
}
} = this;

entries(conditions).forEach((condition) => {
let [key] = condition;
const [, value] = condition;
const columnName = this.model.columnNameFor(key);

if (columnName) {
key = `${tableName}.${columnName}`;

if (Array.isArray(value)) {
this.snapshots.push([
`where${not ? 'NotBetween' : 'Between'}`,
[key, value]
]);
}
}
});

return this;
}

whereRaw(query: string, bindings: Array<any> = []): this {
this.snapshots.push(['whereRaw', [query, bindings]]);
return this;
}

first(): this {
if (!this.shouldCount) {
const willSort = this.snapshots.some(
Expand Down
41 changes: 41 additions & 0 deletions src/packages/database/test/model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,47 @@ describe('module "database/model"', () => {
});
});

describe('.whereBetween()', () => {
class Subject extends Model {
static tableName = 'posts';
}

before(async () => {
await Subject.initialize(store, () => {
return store.connection(Subject.tableName);
});
});

it('returns an instance of `Query`', () => {
const result = Subject.whereBetween({
userId: [1, 10]
});

expect(result).to.be.an.instanceof(Query);
});
});

describe('.whereRaw()', () => {
class Subject extends Model {
static tableName = 'posts';
}

before(async () => {
await Subject.initialize(store, () => {
return store.connection(Subject.tableName);
});
});

it('returns an instance of `Query`', () => {
const result = Subject.whereRaw(
`"title" LIKE ?`,
[`%Test%`]
);

expect(result).to.be.an.instanceof(Query);
});
});

describe('.not()', () => {
class Subject extends Model {
static tableName = 'posts';
Expand Down
97 changes: 97 additions & 0 deletions src/packages/database/test/query.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,16 @@ describe('module "database/query"', () => {
]);
});

it('properly handles null conditions', () => {
const result = subject.where({
isPublic: null
});

expect(result.snapshots).to.deep.equal([
['whereNull', ['posts.is_public']]
]);
});

it('resolves with the correct array of `Model` instances', async () => {
const result = await subject.where({
isPublic: true
Expand All @@ -423,6 +433,93 @@ describe('module "database/query"', () => {
});
});

describe('#whereBetween()', () => {
let subject;

beforeEach(() => {
subject = new Query(TestModel);
});

it('returns `this`', () => {
const result = subject.whereBetween({
userId: [1, 10]
});

expect(result).to.equal(subject);
});

it('properly modifies #snapshots', () => {
const result = subject.whereBetween({
userId: [1, 10]
});

expect(result.snapshots).to.deep.equal([
['whereBetween', ['posts.user_id', [1, 10]]]
]);
});

it('resolves with the correct array of `Model` instances', async () => {
const result = await subject.whereBetween({
userId: [1, 10]
});

expect(result).to.be.an('array');

if (Array.isArray(result)) {
result.forEach(item => {
assertItem(item);
expect(item.userId).to.be.above(0).and.below(11);

});
}
});
});

describe('#whereRaw()', () => {
let subject;

beforeEach(() => {
subject = new Query(TestModel);
});

it('returns `this`', () => {
const result = subject.whereRaw(
`"title" LIKE ?`,
[`%Test%`]
);

expect(result).to.equal(subject);
});

it('properly modifies #snapshots', () => {
const result = subject.whereRaw(
`"title" LIKE ?`,
[`%Test%`]
);

expect(result.snapshots).to.deep.equal([
['whereRaw', [`"title" LIKE ?`, [`%Test%`]]]
]);
});

it('resolves with the correct array of `Model` instances', async () => {
const result = await subject.whereRaw(
`"title" LIKE ?`,
[`%Test%`]
);

expect(result).to.be.an('array');

if (Array.isArray(result)) {
result.forEach(item => {
assertItem(item);
expect(item.title).to.match(/Test/);

});
}
});
});

describe('#first()', () => {
let subject;

Expand Down
2 changes: 1 addition & 1 deletion test/test-app/db/seed.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default async function seed(trx) {
Array.from(range(1, 100)).map(() => (
Post.transacting(trx).create({
body: lorem.paragraphs(),
title: lorem.sentence(),
title: `${arguments[1] === 0 ? 'Test ' : ''} ${lorem.sentence()}`,
userId: randomize([...range(1, 100)]),
isPublic: random.boolean()
})
Expand Down

0 comments on commit df96fd6

Please sign in to comment.