filemaker 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +129 -17
  3. data/filemaker.gemspec +1 -0
  4. data/lib/filemaker.rb +47 -0
  5. data/lib/filemaker/api/query_commands/findquery.rb +20 -3
  6. data/lib/filemaker/configuration.rb +1 -1
  7. data/lib/filemaker/core_ext/hash.rb +19 -15
  8. data/lib/filemaker/error.rb +5 -0
  9. data/lib/filemaker/metadata/field.rb +21 -5
  10. data/lib/filemaker/model.rb +132 -0
  11. data/lib/filemaker/model/builder.rb +52 -0
  12. data/lib/filemaker/model/components.rb +25 -0
  13. data/lib/filemaker/model/criteria.rb +101 -0
  14. data/lib/filemaker/model/field.rb +38 -0
  15. data/lib/filemaker/model/fields.rb +80 -0
  16. data/lib/filemaker/model/findable.rb +35 -0
  17. data/lib/filemaker/model/optional.rb +69 -0
  18. data/lib/filemaker/model/pagination.rb +41 -0
  19. data/lib/filemaker/model/persistable.rb +96 -0
  20. data/lib/filemaker/model/relations.rb +72 -0
  21. data/lib/filemaker/model/relations/belongs_to.rb +30 -0
  22. data/lib/filemaker/model/relations/has_many.rb +79 -0
  23. data/lib/filemaker/model/relations/proxy.rb +35 -0
  24. data/lib/filemaker/model/selectable.rb +146 -0
  25. data/lib/filemaker/railtie.rb +17 -0
  26. data/lib/filemaker/record.rb +25 -0
  27. data/lib/filemaker/resultset.rb +12 -4
  28. data/lib/filemaker/server.rb +7 -5
  29. data/lib/filemaker/version.rb +1 -1
  30. data/spec/filemaker/api/query_commands/compound_find_spec.rb +13 -1
  31. data/spec/filemaker/configuration_spec.rb +23 -0
  32. data/spec/filemaker/layout_spec.rb +0 -1
  33. data/spec/filemaker/model/criteria_spec.rb +304 -0
  34. data/spec/filemaker/model/relations_spec.rb +85 -0
  35. data/spec/filemaker/model_spec.rb +73 -0
  36. data/spec/filemaker/record_spec.rb +12 -1
  37. data/spec/spec_helper.rb +1 -0
  38. data/spec/support/filemaker.yml +13 -0
  39. data/spec/support/models.rb +38 -0
  40. metadata +44 -2
@@ -0,0 +1,17 @@
1
+ require 'rails'
2
+
3
+ module Rails
4
+ module Filemaker
5
+ class Railtie < Rails::Railtie
6
+ initializer 'filemaker-load-config-yml' do
7
+ config_file = Rails.root.join('config', 'filemaker.yml')
8
+
9
+ if config_file.file?
10
+ Filemaker.load!(config_file, Rails.env)
11
+ else
12
+ fail Error::ConfigurationError, 'No config file provided'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -9,10 +9,13 @@ module Filemaker
9
9
  # @return [Hash] additional nested records
10
10
  attr_reader :portals
11
11
 
12
+ attr_reader :dirty
13
+
12
14
  def initialize(record, resultset, portal_table_name = nil)
13
15
  @mod_id = record['mod-id']
14
16
  @record_id = record['record-id']
15
17
  @portals = HashWithIndifferentAndCaseInsensitiveAccess.new
18
+ @dirty = {} # Keep track of field modification
16
19
 
17
20
  record.xpath('field').each do |field|
18
21
  # `field` is Nokogiri::XML::Element
@@ -36,6 +39,21 @@ module Filemaker
36
39
  end
37
40
 
38
41
  build_portals(record.xpath('relatedset'), resultset)
42
+
43
+ @ready = true
44
+ end
45
+
46
+ def [](key)
47
+ fail(Filemaker::Error::InvalidFieldError, "Invalid field: #{key}") \
48
+ unless key?(key)
49
+ super
50
+ end
51
+
52
+ def []=(key, value)
53
+ return super unless @ready
54
+ fail(Filemaker::Error::InvalidFieldError, "Invalid field: #{key}") \
55
+ unless key?(key)
56
+ @dirty[key] = value
39
57
  end
40
58
 
41
59
  private
@@ -60,5 +78,12 @@ module Filemaker
60
78
  return nil if datum.empty?
61
79
  (datum.size == 1) ? datum.first : datum
62
80
  end
81
+
82
+ def method_missing(symbol, *args, &block)
83
+ method = symbol.to_s
84
+ return self[method] if key?(method)
85
+ return @dirty[$`] = args.first if method =~ /(=)$/ && key?($`)
86
+ super
87
+ end
63
88
  end
64
89
  end
@@ -38,9 +38,9 @@ module Filemaker
38
38
  # @return [String] the raw XML for inspection
39
39
  attr_reader :xml
40
40
 
41
- # @param xml [Filemaker::Server] server
42
- # @param xml [String] the XML string from response
43
- # @param xml [Hash] the request params used to construct request
41
+ # @param [Filemaker::Server] server
42
+ # @param [String] xml The XML string from response
43
+ # @param [Hash] params The request params used to construct request
44
44
  def initialize(server, xml, params = nil)
45
45
  @list = []
46
46
  @fields = {}
@@ -76,10 +76,18 @@ module Filemaker
76
76
  list.each(*args, &block)
77
77
  end
78
78
 
79
+ def size
80
+ list.size
81
+ end
82
+ alias_method :length, :size
83
+
79
84
  private
80
85
 
86
+ # For 401 (No records match the request) and 101 (Record is missing), we
87
+ # will return empty array or nil back rather than raise those errors. Is it
88
+ # a good design? We need to find out after production usage.
81
89
  def raise_potential_error!(error_code)
82
- return if error_code.zero?
90
+ return if error_code.zero? || error_code == 401 || error_code == 101
83
91
 
84
92
  Filemaker::Error.raise_error_by_code(error_code)
85
93
  end
@@ -14,13 +14,13 @@ module Filemaker
14
14
  alias_method :database, :databases
15
15
  alias_method :db, :databases
16
16
 
17
- def_delegators :@config, :host, :url, :ssl, :endpoint
17
+ def_delegators :@config, :host, :url, :ssl, :endpoint, :log
18
18
  def_delegators :@config, :account_name, :password
19
19
 
20
20
  def initialize(options = {})
21
21
  @config = Configuration.new
22
22
  yield @config if block_given?
23
- fail ArgumentError if @config.not_configurable?
23
+ fail ArgumentError, 'Missing config block' if @config.not_configurable?
24
24
 
25
25
  @databases = Store::DatabaseStore.new(self)
26
26
  @connection = get_connection(options)
@@ -39,13 +39,13 @@ module Filemaker
39
39
  .merge(expand_options(options))
40
40
  .merge({ action => '' })
41
41
 
42
- # Serialize the params for submission
43
- params = params.stringify_keys
42
+ # Serialize the params for submission??
43
+ params.stringify_keys!
44
44
 
45
45
  log_action(params)
46
46
 
47
47
  # yield params if block_given?
48
- response = @connection.__send__(method, endpoint, params)
48
+ response = @connection.public_send(method, endpoint, params)
49
49
 
50
50
  case response.status
51
51
  when 200 then [response, params]
@@ -86,6 +86,7 @@ module Filemaker
86
86
  when DateTime then args[key] = value.strftime('%m/%d/%Y %H:%M:%S')
87
87
  when Time then args[key] = value.strftime('%H:%M')
88
88
  else
89
+ # Especially for range operator (...), we want to output as String
89
90
  args[key] = value.to_s
90
91
  end
91
92
  end
@@ -161,6 +162,7 @@ module Filemaker
161
162
  expanded
162
163
  end
163
164
 
165
+ # TODO: Should we convert it to string so 'cURL' will work also?
164
166
  def log_action(params)
165
167
  case @config.log
166
168
  when :simple then log_simple(params)
@@ -1,3 +1,3 @@
1
1
  module Filemaker
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -44,7 +44,7 @@ describe Filemaker::Api::QueryCommands::CompoundFind do
44
44
  end
45
45
  end
46
46
 
47
- context 'with array' do
47
+ context 'with array of hash' do
48
48
  it '[{a: 1}, {b: 2}] to (q0);(q1)' do
49
49
  expect(Filemaker::Api::QueryCommands::CompoundFind.new(
50
50
  [{ a: 1 }, { b: 2 }]
@@ -64,6 +64,18 @@ describe Filemaker::Api::QueryCommands::CompoundFind do
64
64
  [{ a: [1, 2, 3], b: 1 }, { c: 4, '-omit' => true }]
65
65
  ).key_maps_string).to eq '(q0,q3);(q1,q3);(q2,q3);!(q4)'
66
66
  end
67
+
68
+ it '[{a: [1, 2]}, {b: 2, c: 3, "-omit" => true}] to (q0);(q1);!(q2,q3)' do
69
+ expect(Filemaker::Api::QueryCommands::CompoundFind.new(
70
+ [{ a: [1, 2] }, { b: 2, c: 3, '-omit' => true }]
71
+ ).key_maps_string).to eq '(q0);(q1);!(q2,q3)'
72
+ end
73
+
74
+ it '[{a: [1, 2] }, { b: [3, 4] }] to (q0);(q1);(q2);(q3)' do
75
+ expect(Filemaker::Api::QueryCommands::CompoundFind.new(
76
+ [{ a: [1, 2] }, { b: [3, 4] }]
77
+ ).key_maps_string).to eq '(q0);(q1);(q2);(q3)'
78
+ end
67
79
  end
68
80
 
69
81
  end
@@ -0,0 +1,23 @@
1
+ describe 'Configuration' do
2
+
3
+ context 'with yaml file' do
4
+ it 'load settings based on environment' do
5
+ path = File.expand_path('../../support/filemaker.yml', __FILE__)
6
+ Filemaker.load!(path, 'development')
7
+ expect(Filemaker.registry['default']).to be_a Filemaker::Server
8
+ expect(Filemaker.registry['default'].host).to eq 'host.com'
9
+ expect(Filemaker.registry['default'].account_name).to eq \
10
+ 'FILEMAKER_ACCOUNT_NAME'
11
+ expect(Filemaker.registry['default'].ssl).to eq({ 'verify' => false })
12
+ expect(Filemaker.registry['default'].log).to eq :curl
13
+ end
14
+
15
+ it 'raises ConfigurationError for wrong environment' do
16
+ path = File.expand_path('../../support/filemaker.yml', __FILE__)
17
+ expect do
18
+ Filemaker.load!(path, 'unknown')
19
+ end.to raise_error Filemaker::Error::ConfigurationError
20
+ end
21
+ end
22
+
23
+ end
@@ -91,7 +91,6 @@ describe Filemaker::Layout do
91
91
  it 'finds some records with criteria' do
92
92
  args = { name: 'Bob', day: Date.parse('25/8/2014') }
93
93
  resultset = @layout.find(args, max: 1)
94
-
95
94
  expect(resultset.params['name']).to eq 'Bob'
96
95
  expect(resultset.params['day']).to eq '08/25/2014'
97
96
  expect(resultset.params['-max']).to eq 1
@@ -0,0 +1,304 @@
1
+ describe Filemaker::Model::Criteria do
2
+
3
+ let(:criteria) { Filemaker::Model::Criteria.new(MyModel) }
4
+ let(:cf) { Filemaker::Api::QueryCommands::CompoundFind }
5
+
6
+ context 'selectable' do
7
+ describe 'where' do
8
+ it 'raises MixedClauseError if mixed with -findquery' do
9
+ expect do
10
+ criteria.in(status: %w(pending subscribed)).where(name: 'Bob')
11
+ end.to raise_error Filemaker::Error::MixedClauseError
12
+ end
13
+
14
+ it 'single hash criterion are recorded as is' do
15
+ criteria.where(name: 'Bob', email: 'bob@cern.org')
16
+ expect(criteria.selector).to eq(
17
+ { 'name' => 'Bob', 'email' => 'bob@cern.org' }
18
+ )
19
+ end
20
+
21
+ it 'chains where' do
22
+ criteria.where(name: 'Bob').where(email: 'bob@cern.org')
23
+ expect(criteria.selector).to eq(
24
+ { 'name' => 'Bob', 'email' => 'bob@cern.org' }
25
+ )
26
+ end
27
+
28
+ it 'accepts a block to configure additional options' do
29
+ criteria.where(name: 'Bob') do |options|
30
+ options[:script] = 'Remove Duplicates'
31
+ end
32
+
33
+ expect(criteria.options[:script]).to eq 'Remove Duplicates'
34
+ end
35
+
36
+ it 'only accepts fields from model' do
37
+ criteria.where(name: 'Bob', email: 'bob@cern.org', unit: '< 50')
38
+ expect(criteria.selector).to eq(
39
+ { 'name' => 'Bob', 'email' => 'bob@cern.org' }
40
+ )
41
+ end
42
+ end
43
+
44
+ describe 'or' do
45
+ it 'chains `or` as logical OR option' do
46
+ criteria.where(name: 'Bob').or(email: 'bob@cern.org')
47
+ expect(criteria.selector).to eq(
48
+ { 'name' => 'Bob', 'email' => 'bob@cern.org' }
49
+ )
50
+ expect(criteria.options[:lop]).to eq 'or'
51
+ end
52
+
53
+ it 'chains multiple `or`, adding more fields' do
54
+ criteria.where(name: 'Bob').or(email: 'bob@cern.org').or(salary: 5000)
55
+ expect(criteria.selector).to eq(
56
+ { 'name' => 'Bob', 'email' => 'bob@cern.org', 'salary' => 5000 }
57
+ )
58
+ expect(criteria.options[:lop]).to eq 'or'
59
+ end
60
+ end
61
+
62
+ context 'comparison operators' do
63
+ it 'only works on `where` query' do
64
+ expect do
65
+ criteria.in(status: %w(pending subscribed)).eq(name: 'Bob')
66
+ end.to raise_error Filemaker::Error::MixedClauseError
67
+ end
68
+
69
+ describe 'not' do
70
+ it 'appends neq operator on the field name' do
71
+ criteria.not(salary: 50)
72
+ expect(criteria.selector['salary']).to eq 50
73
+ expect(criteria.selector['salary.op']).to eq 'neq'
74
+ end
75
+ end
76
+
77
+ describe 'cn' do
78
+ it 'appends cn operator on the field name' do
79
+ criteria.cn(name: 'Chong') do |options|
80
+ options[:script] = 'Remove Duplicates'
81
+ end
82
+
83
+ expect(criteria.selector['name']).to eq 'Chong'
84
+ expect(criteria.selector['name.op']).to eq 'cn'
85
+ end
86
+ end
87
+
88
+ describe 'bw' do
89
+ it 'can do range operation ...' do
90
+ criteria.bw(salary: '3000...4500')
91
+ expect(criteria.selector['salary']).to eq '3000...4500'
92
+ end
93
+ end
94
+
95
+ # TODO: Do more operator tests
96
+ end
97
+
98
+ describe 'in' do
99
+ it 'raises MixedClauseError if mixed with -find' do
100
+ expect do
101
+ criteria.where(name: 'Bob').in(status: %w(pending subscribed))
102
+ end.to raise_error Filemaker::Error::MixedClauseError
103
+ end
104
+
105
+ it '{a: [1, 2]} to (q0);(q1)' do
106
+ criteria.in(name: %w(Bob Lee))
107
+ compound_find = cf.new(criteria.selector)
108
+ expect(compound_find.key_maps_string).to eq '(q0);(q1)'
109
+ expect(criteria.selector).to eq [{ 'name' => %w(Bob Lee) }]
110
+ end
111
+
112
+ it '{a: [1, 2], b: [3, 4]} to (q0,q2);(q0,q3);(q1,q2);(q1,q3)' do
113
+ criteria.in(name: %w(Bob Lee), age: ['20', 30])
114
+ compound_find = cf.new(criteria.selector)
115
+ expect(compound_find.key_maps_string).to eq \
116
+ '(q0,q2);(q0,q3);(q1,q2);(q1,q3)'
117
+ expect(criteria.selector).to eq \
118
+ [{ 'name' => %w(Bob Lee), 'passage of time' => [20, 30] }]
119
+ end
120
+
121
+ it '{a: [1, 2], b: 3} to (q0,q2);(q1,q2)' do
122
+ criteria.in(name: %w(Bob Lee), age: '30')
123
+ compound_find = cf.new(criteria.selector)
124
+ expect(compound_find.key_maps_string).to eq '(q0,q2);(q1,q2)'
125
+ expect(criteria.selector).to eq \
126
+ [{ 'name' => %w(Bob Lee), 'passage of time' => 30 }]
127
+ end
128
+
129
+ it '{a: 1, b: 2} to (q0,q1)' do
130
+ criteria.in(name: 'Bob', age: 30)
131
+ compound_find = cf.new(criteria.selector)
132
+ expect(compound_find.key_maps_string).to eq '(q0,q1)'
133
+ expect(criteria.selector).to eq \
134
+ [{ 'name' => 'Bob', 'passage of time' => 30 }]
135
+ end
136
+
137
+ it '{a: 1, b: [2, 3]} to (q0,q1);(q0,q2)' do
138
+ criteria.in(name: 'Bob', age: [20, 30])
139
+ compound_find = cf.new(criteria.selector)
140
+ expect(compound_find.key_maps_string).to eq '(q0,q1);(q0,q2)'
141
+ expect(criteria.selector).to eq \
142
+ [{ 'name' => 'Bob', 'passage of time' => [20, 30] }]
143
+ end
144
+
145
+ it '[{a: [1, 2]}, {b: [1, 2]}] to (q0);(q1);(q2);(q3)' do
146
+ criteria.in([{ name: %w(Bob Lee) }, { age: [20, 30] }])
147
+ compound_find = cf.new(criteria.selector)
148
+ expect(compound_find.key_maps_string).to eq '(q0);(q1);(q2);(q3)'
149
+ expect(criteria.selector).to eq \
150
+ [{ 'name' => %w(Bob Lee) }, { 'passage of time' => [20, 30] }]
151
+ end
152
+
153
+ it '[{a: 1}, {b: 2}] to (q0);(q1)' do
154
+ criteria.in([{ name: 'Bob' }, { age: 20 }])
155
+ compound_find = cf.new(criteria.selector)
156
+ expect(compound_find.key_maps_string).to eq '(q0);(q1)'
157
+ expect(criteria.selector).to eq \
158
+ [{ 'name' => 'Bob' }, { 'passage of time' => 20 }]
159
+ end
160
+
161
+ it '[{a: 1}, {b: [1, 2]}] to (q0);(q1);(q2)' do
162
+ criteria.in([{ name: 'Bob' }, { age: [20, 30] }])
163
+ compound_find = cf.new(criteria.selector)
164
+ expect(compound_find.key_maps_string).to eq '(q0);(q1);(q2)'
165
+ expect(criteria.selector).to eq \
166
+ [{ 'name' => 'Bob' }, { 'passage of time' => [20, 30] }]
167
+ end
168
+
169
+ it '[{a: 1}, {b: 1, c: 2}] to (q0);(q1,q2)' do
170
+ criteria.in([{ name: 'Bob' }, { age: 20, email: 'A' }])
171
+ compound_find = cf.new(criteria.selector)
172
+ expect(compound_find.key_maps_string).to eq '(q0);(q1,q2)'
173
+ expect(criteria.selector).to eq \
174
+ [{ 'name' => 'Bob' }, { 'passage of time' => 20, 'email' => 'A' }]
175
+ end
176
+ end
177
+
178
+ describe 'not_in' do
179
+ it '{a: [1, 2]} to !(q0);!(q1)' do
180
+ criteria.not_in(name: %w(Bob Lee))
181
+ compound_find = cf.new(criteria.selector)
182
+ expect(compound_find.key_maps_string).to eq '!(q0);!(q1)'
183
+ end
184
+
185
+ it '{a: [1, 2], b: [3, 4]} to !(q0,q2);!(q0,q3);!(q1,q2);!(q1,q3)' do
186
+ criteria.not_in(name: %w(Bob Lee), age: ['20', 30])
187
+ compound_find = cf.new(criteria.selector)
188
+ expect(compound_find.key_maps_string).to eq \
189
+ '!(q0,q2);!(q0,q3);!(q1,q2);!(q1,q3)'
190
+ end
191
+
192
+ it '{a: [1, 2], b: 3} to !(q0,q2);!(q1,q2)' do
193
+ criteria.not_in(name: %w(Bob Lee), age: '30')
194
+ compound_find = cf.new(criteria.selector)
195
+ expect(compound_find.key_maps_string).to eq '!(q0,q2);!(q1,q2)'
196
+ end
197
+
198
+ it '{a: 1, b: 2} to !(q0,q1)' do
199
+ criteria.not_in(name: 'Bob', age: 30)
200
+ compound_find = cf.new(criteria.selector)
201
+ expect(compound_find.key_maps_string).to eq '!(q0,q1)'
202
+ end
203
+
204
+ it '{a: 1, b: [2, 3]} to !(q0,q1);!(q0,q2)' do
205
+ criteria.not_in(name: 'Bob', age: [20, 30])
206
+ compound_find = cf.new(criteria.selector)
207
+ expect(compound_find.key_maps_string).to eq '!(q0,q1);!(q0,q2)'
208
+ end
209
+
210
+ it '[{a: [1, 2]}, {b: [1, 2]}] to !(q0);!(q1);!(q2);!(q3)' do
211
+ criteria.not_in([{ name: %w(Bob Lee) }, { age: [20, 30] }])
212
+ compound_find = cf.new(criteria.selector)
213
+ expect(compound_find.key_maps_string).to eq '!(q0);!(q1);!(q2);!(q3)'
214
+ end
215
+
216
+ it '[{a: 1}, {b: 2}] to !(q0);!(q1)' do
217
+ criteria.not_in([{ name: 'Bob' }, { age: 20 }])
218
+ compound_find = cf.new(criteria.selector)
219
+ expect(compound_find.key_maps_string).to eq '!(q0);!(q1)'
220
+ end
221
+
222
+ it '[{a: 1}, {b: [1, 2]}] to !(q0);!(q1);!(q2)' do
223
+ criteria.not_in([{ name: 'Bob' }, { age: [20, 30] }])
224
+ compound_find = cf.new(criteria.selector)
225
+ expect(compound_find.key_maps_string).to eq '!(q0);!(q1);!(q2)'
226
+ end
227
+
228
+ it '[{a: 1}, {b: 1, c: 2}] to !(q0);!(q1,q2)' do
229
+ criteria.not_in([{ name: 'Bob' }, { age: 20, email: 'A' }])
230
+ compound_find = cf.new(criteria.selector)
231
+ expect(compound_find.key_maps_string).to eq '!(q0);!(q1,q2)'
232
+ end
233
+
234
+ it 'using in and not_in at the same time' do
235
+ criteria.in(name: %w(Bob Lee)).not_in(age: 20, email: 'A')
236
+ compound_find = cf.new(criteria.selector)
237
+ expect(compound_find.key_maps_string).to eq '(q0);(q1);!(q2,q3)'
238
+ end
239
+ end
240
+ end
241
+
242
+ context 'optional' do
243
+ it 'accepts skip option' do
244
+ criteria.skip(10)
245
+ expect(criteria.options[:skip]).to eq 10
246
+ end
247
+
248
+ it 'will override skip if chain repeatedly' do
249
+ criteria.skip(10).skip(100).skip(1000)
250
+ expect(criteria.options[:skip]).to eq 1000
251
+ end
252
+
253
+ it 'accepts limit option' do
254
+ criteria.limit(10)
255
+ expect(criteria.options[:max]).to eq 10
256
+ end
257
+
258
+ it 'will override limit if chain repeatedly' do
259
+ criteria.limit(10).limit(100).limit(1000)
260
+ expect(criteria.options[:max]).to eq 1000
261
+ end
262
+
263
+ it 'accepts order option' do
264
+ criteria.order('name desc')
265
+ expect(criteria.options[:sortfield]).to eq ['name']
266
+ expect(criteria.options[:sortorder]).to eq ['descend']
267
+ end
268
+
269
+ it 'does not entertain invalid fieldname' do
270
+ criteria.order('zzz desc')
271
+ expect(criteria.options[:sortfield]).to be_nil
272
+ expect(criteria.options[:sortorder]).to be_nil
273
+ end
274
+
275
+ it 'will default to asc for missing order' do
276
+ criteria.order('name, email')
277
+ expect(criteria.options[:sortorder]).to eq %w(ascend ascend)
278
+ end
279
+
280
+ it 'will use real FileMaker fieldname' do
281
+ criteria.order('updated_at desc')
282
+ expect(criteria.options[:sortfield]).to eq ['modifieddate']
283
+ end
284
+ end
285
+
286
+ context 'pagination' do
287
+ it 'sets the limit' do
288
+ expect(criteria.per(50).options[:max]).to eq 50
289
+ end
290
+
291
+ it 'sets the page to skip' do
292
+ expect(criteria.page(2).per(50).options[:skip]).to eq 50
293
+ end
294
+
295
+ it 'sets the page to skip with larger page' do
296
+ expect(criteria.page(12).per(50).options[:skip]).to eq 550
297
+ end
298
+
299
+ it 'will not populate skip option if there is no page' do
300
+ expect(criteria.per(50).options[:skip]).to be_nil
301
+ end
302
+ end
303
+
304
+ end