mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-02-01 12:58:52 +08:00
135 lines
5.3 KiB
CoffeeScript
135 lines
5.3 KiB
CoffeeScript
|
ModelQuery = require '../../src/flux/models/query'
|
||
|
{Matcher} = require '../../src/flux/attributes'
|
||
|
Thread = require '../../src/flux/models/thread'
|
||
|
Namespace = require '../../src/flux/models/namespace'
|
||
|
|
||
|
describe "ModelQuery", ->
|
||
|
beforeEach ->
|
||
|
@db = {}
|
||
|
|
||
|
describe "where", ->
|
||
|
beforeEach ->
|
||
|
@q = new ModelQuery(Thread, @db)
|
||
|
@m1 = Thread.attributes.id.equal(4)
|
||
|
@m2 = Thread.attributes.tags.contains('inbox')
|
||
|
|
||
|
it "should accept an array of Matcher objects", ->
|
||
|
@q.where([@m1,@m2])
|
||
|
expect(@q._matchers.length).toBe(2)
|
||
|
expect(@q._matchers[0]).toBe(@m1)
|
||
|
expect(@q._matchers[1]).toBe(@m2)
|
||
|
|
||
|
it "should accept a single Matcher object", ->
|
||
|
@q.where(@m1)
|
||
|
expect(@q._matchers.length).toBe(1)
|
||
|
expect(@q._matchers[0]).toBe(@m1)
|
||
|
|
||
|
it "should append to any existing where clauses", ->
|
||
|
@q.where(@m1)
|
||
|
@q.where(@m2)
|
||
|
expect(@q._matchers.length).toBe(2)
|
||
|
expect(@q._matchers[0]).toBe(@m1)
|
||
|
expect(@q._matchers[1]).toBe(@m2)
|
||
|
|
||
|
it "should accept a shorthand format", ->
|
||
|
@q.where({id: 4, lastMessageTimestamp: 1234})
|
||
|
expect(@q._matchers.length).toBe(2)
|
||
|
expect(@q._matchers[0].attr.modelKey).toBe('id')
|
||
|
expect(@q._matchers[0].comparator).toBe('=')
|
||
|
expect(@q._matchers[0].val).toBe(4)
|
||
|
|
||
|
it "should return the query so it can be chained", ->
|
||
|
expect(@q.where({id: 4})).toBe(@q)
|
||
|
|
||
|
it "should immediately raise an exception if an un-queryable attribute is specified", ->
|
||
|
expect(-> @q.where({snippet: 'My Snippet'})).toThrow()
|
||
|
|
||
|
it "should immediately raise an exception if a non-existent attribute is specified", ->
|
||
|
expect(-> @q.where({looksLikeADuck: 'of course'})).toThrow()
|
||
|
|
||
|
describe "order", ->
|
||
|
beforeEach ->
|
||
|
@q = new ModelQuery(Thread, @db)
|
||
|
@o1 = Thread.attributes.lastMessageTimestamp.descending()
|
||
|
@o2 = Thread.attributes.subject.descending()
|
||
|
|
||
|
it "should accept an array of SortOrders", ->
|
||
|
@q.order([@o1,@o2])
|
||
|
expect(@q._orders.length).toBe(2)
|
||
|
|
||
|
it "should accept a single SortOrder object", ->
|
||
|
@q.order(@o2)
|
||
|
expect(@q._orders.length).toBe(1)
|
||
|
|
||
|
it "should extend any existing ordering", ->
|
||
|
@q.order(@o1)
|
||
|
@q.order(@o2)
|
||
|
expect(@q._orders.length).toBe(2)
|
||
|
expect(@q._orders[0]).toBe(@o1)
|
||
|
expect(@q._orders[1]).toBe(@o2)
|
||
|
|
||
|
it "should return the query so it can be chained", ->
|
||
|
expect(@q.order(@o2)).toBe(@q)
|
||
|
|
||
|
describe "sql", ->
|
||
|
beforeEach ->
|
||
|
@runScenario = (klass, scenario) ->
|
||
|
q = new ModelQuery(klass, @db)
|
||
|
Matcher.muid = 1
|
||
|
scenario.builder(q)
|
||
|
expect(q.sql().trim()).toBe(scenario.sql.trim())
|
||
|
|
||
|
it "should correctly generate queries with multiple where clauses", ->
|
||
|
@runScenario Namespace,
|
||
|
builder: (q) -> q.where({emailAddress: 'ben@inboxapp.com'}).where({id: 2})
|
||
|
sql: "SELECT `Namespace`.`data` FROM `Namespace` \
|
||
|
WHERE `email_address` = 'ben@inboxapp.com' AND `id` = 2"
|
||
|
|
||
|
it "should correctly generate COUNT queries", ->
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where({namespaceId: 'abcd'}).count()
|
||
|
sql: "SELECT COUNT(*) as count FROM `Thread` \
|
||
|
WHERE `namespace_id` = 'abcd' "
|
||
|
|
||
|
it "should correctly generate LIMIT 1 queries for single items", ->
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where({namespaceId: 'abcd'}).one()
|
||
|
sql: "SELECT `Thread`.`data` FROM `Thread` \
|
||
|
WHERE `namespace_id` = 'abcd' \
|
||
|
ORDER BY `Thread`.`last_message_timestamp` DESC LIMIT 1"
|
||
|
|
||
|
it "should correctly generate `contains` queries using JOINS", ->
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where(Thread.attributes.tags.contains('inbox')).where({id: '1234'})
|
||
|
sql: "SELECT `Thread`.`data` FROM `Thread` \
|
||
|
INNER JOIN `Thread-Tag` AS `M1` ON `M1`.`id` = `Thread`.`id` \
|
||
|
WHERE `M1`.`value` = 'inbox' AND `id` = '1234' \
|
||
|
ORDER BY `Thread`.`last_message_timestamp` DESC"
|
||
|
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where([Thread.attributes.tags.contains('inbox'), Thread.attributes.tags.contains('unread')])
|
||
|
sql: "SELECT `Thread`.`data` FROM `Thread` \
|
||
|
INNER JOIN `Thread-Tag` AS `M1` ON `M1`.`id` = `Thread`.`id` \
|
||
|
INNER JOIN `Thread-Tag` AS `M2` ON `M2`.`id` = `Thread`.`id` \
|
||
|
WHERE `M1`.`value` = 'inbox' AND `M2`.`value` = 'unread' \
|
||
|
ORDER BY `Thread`.`last_message_timestamp` DESC"
|
||
|
|
||
|
it "should correctly generate queries with the class's naturalSortOrder when one is available and no other orders are provided", ->
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where({namespaceId: 'abcd'})
|
||
|
sql: "SELECT `Thread`.`data` FROM `Thread` \
|
||
|
WHERE `namespace_id` = 'abcd' \
|
||
|
ORDER BY `Thread`.`last_message_timestamp` DESC"
|
||
|
|
||
|
@runScenario Thread,
|
||
|
builder: (q) -> q.where({namespaceId: 'abcd'}).order(Thread.attributes.lastMessageTimestamp.ascending())
|
||
|
sql: "SELECT `Thread`.`data` FROM `Thread` \
|
||
|
WHERE `namespace_id` = 'abcd' \
|
||
|
ORDER BY `Thread`.`last_message_timestamp` ASC"
|
||
|
|
||
|
@runScenario Namespace,
|
||
|
builder: (q) -> q.where({id: 'abcd'})
|
||
|
sql: "SELECT `Namespace`.`data` FROM `Namespace` \
|
||
|
WHERE `id` = 'abcd' "
|
||
|
|