task_helper 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +317 -0
- data/Rakefile +4 -0
- data/lib/task_helper/api/cache.rb +28 -0
- data/lib/task_helper/api/call.rb +48 -0
- data/lib/task_helper/api.rb +23 -0
- data/lib/task_helper/base.rb +55 -0
- data/lib/task_helper/database.rb +30 -0
- data/lib/task_helper/field.rb +20 -0
- data/lib/task_helper/form.rb +57 -0
- data/lib/task_helper/record.rb +29 -0
- data/lib/task_helper/version.rb +3 -0
- data/lib/task_helper.rb +15 -0
- data/lib/tasks/spec_setup.rake +41 -0
- data/spec/lib/task_helper/api/cache_spec.rb +73 -0
- data/spec/lib/task_helper/api/call_spec.rb +136 -0
- data/spec/lib/task_helper/api_spec.rb +45 -0
- data/spec/lib/task_helper/database_spec.rb +91 -0
- data/spec/lib/task_helper/field_spec.rb +50 -0
- data/spec/lib/task_helper/form_spec.rb +141 -0
- data/spec/lib/task_helper/record_spec.rb +73 -0
- data/spec/lib/task_helper/version_spec.rb +5 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/fake_mth.rb +74 -0
- data/spec/support/fixture_parser.rb +67 -0
- data/spec/support/fixtures/.keep +0 -0
- data/task_helper.gemspec +27 -0
- metadata +173 -0
data/lib/task_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
require 'task_helper/version'
|
4
|
+
require 'task_helper/api/call'
|
5
|
+
require 'task_helper/api/cache'
|
6
|
+
require 'task_helper/api'
|
7
|
+
require 'task_helper/base'
|
8
|
+
require 'task_helper/record'
|
9
|
+
require 'task_helper/field'
|
10
|
+
require 'task_helper/form'
|
11
|
+
require 'task_helper/database'
|
12
|
+
|
13
|
+
module TaskHelper
|
14
|
+
# Your code goes here...
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
namespace :spec do
|
2
|
+
task :setup, [:api_key] do |t, args|
|
3
|
+
TaskHelper::API.rest_api_key = args[:api_key]
|
4
|
+
|
5
|
+
File.open('spec/support/fixtures/databases.json', 'w') do |f|
|
6
|
+
f.write(JSON.pretty_generate(TaskHelper::API.get(route: 'apps.json')))
|
7
|
+
end
|
8
|
+
|
9
|
+
TaskHelper::API.get(route: 'apps.json')['databases'].each do |db|
|
10
|
+
db_dir = "spec/support/fixtures/databases/#{db['id']}"
|
11
|
+
db_route = "apps/#{db['id']}"
|
12
|
+
forms_route = "#{db_route}/entities"
|
13
|
+
FileUtils.mkdir_p(db_dir)
|
14
|
+
File.open("#{db_dir}/forms.json", 'w') do |f|
|
15
|
+
f.write(JSON.pretty_generate(TaskHelper::API.get(route: "#{forms_route}.json")))
|
16
|
+
end
|
17
|
+
|
18
|
+
TaskHelper::API.get(route: "apps/#{db['id']}/entities.json")['forms'].each do |form|
|
19
|
+
form_dir = "#{db_dir}/forms/#{form['id']}"
|
20
|
+
fields_route = "#{forms_route}/#{form['id']}/properties"
|
21
|
+
FileUtils.mkdir_p(form_dir)
|
22
|
+
File.open("#{form_dir}/fields.json", 'w') do |f|
|
23
|
+
f.write(JSON.pretty_generate(TaskHelper::API.get(route: "#{fields_route}.json")))
|
24
|
+
end
|
25
|
+
|
26
|
+
if TaskHelper::API.get(route: "#{fields_route}.json")['fields'].any?
|
27
|
+
records_route = "#{db_route}/dtypes/entity/#{form['id']}"
|
28
|
+
records_dir = "#{form_dir}/records"
|
29
|
+
FileUtils.mkdir_p(records_dir)
|
30
|
+
page_count = db['dtypes_count'].to_i / form['per_page'].to_i + 1
|
31
|
+
(1..page_count).each do |page|
|
32
|
+
File.open("#{records_dir}/#{page}.json", 'w') do |f|
|
33
|
+
f.write(JSON.pretty_generate(TaskHelper::API
|
34
|
+
.get(route: "#{records_route}.json", params: { page: page })))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
describe TaskHelper::API::Cache do
|
2
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
3
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
4
|
+
|
5
|
+
subject { described_class.new(limit: 2) }
|
6
|
+
|
7
|
+
describe '#get' do
|
8
|
+
context 'call already cached' do
|
9
|
+
it 'should query the existing call' do
|
10
|
+
call1 = TaskHelper::API::Call.new(route: 'hello')
|
11
|
+
call2 = TaskHelper::API::Call.new(route: 'hello')
|
12
|
+
expect(TaskHelper::API::Call).to receive(:new).with(route: 'hello')
|
13
|
+
.twice.and_return(call1, call2)
|
14
|
+
expect(call1).to receive(:run).twice
|
15
|
+
subject.get(route: 'hello')
|
16
|
+
subject.get(route: 'hello')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'call not yet cached' do
|
21
|
+
it 'should query a new call' do
|
22
|
+
call1 = TaskHelper::API::Call.new(route: 'hello')
|
23
|
+
call2 = TaskHelper::API::Call.new(route: 'goodbye')
|
24
|
+
expect(call1).to receive(:run).once
|
25
|
+
expect(call2).to receive(:run).once
|
26
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
27
|
+
.with(route: 'hello').and_return(call1)
|
28
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
29
|
+
.with(route: 'goodbye').and_return(call2)
|
30
|
+
subject.get(route: 'hello')
|
31
|
+
subject.get(route: 'goodbye')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should cache the new call' do
|
35
|
+
call1 = TaskHelper::API::Call.new(route: 'hello')
|
36
|
+
call2 = TaskHelper::API::Call.new(route: 'goodbye')
|
37
|
+
call3 = TaskHelper::API::Call.new(route: 'goodbye')
|
38
|
+
expect(call1).to receive(:run).once
|
39
|
+
expect(call2).to receive(:run).twice
|
40
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
41
|
+
.with(route: 'hello').and_return(call1)
|
42
|
+
expect(TaskHelper::API::Call).to receive(:new).twice.ordered
|
43
|
+
.with(route: 'goodbye').and_return(call2, call3)
|
44
|
+
subject.get(route: 'hello')
|
45
|
+
subject.get(route: 'goodbye')
|
46
|
+
subject.get(route: 'goodbye')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should remove older calls if the limit is reached' do
|
50
|
+
call1 = TaskHelper::API::Call.new(route: 'hello')
|
51
|
+
call2 = TaskHelper::API::Call.new(route: 'goodbye')
|
52
|
+
call3 = TaskHelper::API::Call.new(route: 'foobar')
|
53
|
+
call4 = TaskHelper::API::Call.new(route: 'hello')
|
54
|
+
expect(call1).to receive(:run).once
|
55
|
+
expect(call2).to receive(:run).once
|
56
|
+
expect(call3).to receive(:run).once
|
57
|
+
expect(call4).to receive(:run).once
|
58
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
59
|
+
.with(route: 'hello').and_return(call1)
|
60
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
61
|
+
.with(route: 'goodbye').and_return(call2)
|
62
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
63
|
+
.with(route: 'foobar').and_return(call3)
|
64
|
+
expect(TaskHelper::API::Call).to receive(:new).once.ordered
|
65
|
+
.with(route: 'hello').and_return(call4)
|
66
|
+
subject.get(route: 'hello')
|
67
|
+
subject.get(route: 'goodbye')
|
68
|
+
subject.get(route: 'foobar')
|
69
|
+
subject.get(route: 'hello')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
describe TaskHelper::API::Call do
|
2
|
+
let(:key) { { rest_api_key: 'foobar' } }
|
3
|
+
let(:response) { double(parsed_response: [{ 'a' => 1 }]) }
|
4
|
+
|
5
|
+
it 'should define a reader for time' do
|
6
|
+
t = Time.now
|
7
|
+
args = { route: 'hello', params: key, time: t }
|
8
|
+
expect(described_class.new(args).time).to eq(t)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
context 'given an api key' do
|
13
|
+
subject { described_class.new(route: 'hello', params: key) }
|
14
|
+
|
15
|
+
it 'should not raise a missing key error' do
|
16
|
+
expect { subject }.not_to raise_exception
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should replace the default key' do
|
20
|
+
TaskHelper::API.rest_api_key = 'hello'
|
21
|
+
expect(HTTParty).to receive(:get)
|
22
|
+
.with(anything, query: key).and_return(response)
|
23
|
+
subject.run
|
24
|
+
TaskHelper::API.rest_api_key = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'without an api key' do
|
29
|
+
subject { described_class.new(route: 'hello') }
|
30
|
+
|
31
|
+
it 'should attempt to use the default' do
|
32
|
+
TaskHelper::API.rest_api_key = 'hello'
|
33
|
+
expect(HTTParty).to receive(:get)
|
34
|
+
.with(anything, query: { rest_api_key: 'hello' }).and_return(response)
|
35
|
+
subject.run
|
36
|
+
TaskHelper::API.rest_api_key = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should raise an exception if no default is set' do
|
40
|
+
expect { subject }.to raise_exception(TaskHelper::API::Call::MissingAPIKey)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#run' do
|
46
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
47
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
48
|
+
|
49
|
+
subject { described_class.new(route: 'hello') }
|
50
|
+
|
51
|
+
it 'should reset the time' do
|
52
|
+
expect { subject.run }.to change { subject.time }
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should make a request to the given route at mytaskhelper.com' do
|
56
|
+
expect(HTTParty).to receive(:get)
|
57
|
+
.with('https://mytaskhelper.com/hello', query: { rest_api_key: 'foobar' })
|
58
|
+
.and_return(response)
|
59
|
+
subject.run
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'call has expired' do
|
63
|
+
it 'should resend the request' do
|
64
|
+
params = { route: 'hello', timeout: 0 }
|
65
|
+
call = described_class.new(params)
|
66
|
+
expect(HTTParty).to receive(:get).twice.and_return(response)
|
67
|
+
call.run
|
68
|
+
call.run
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'call has not expired' do
|
73
|
+
context 'request has been cached' do
|
74
|
+
it 'should return the cached response' do
|
75
|
+
expect(HTTParty).to receive(:get).once.and_return(response)
|
76
|
+
result = subject.run
|
77
|
+
expect(subject.run).to eq(result)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'request has not been chached' do
|
82
|
+
it 'should retrieve the response' do
|
83
|
+
expect(HTTParty).to receive(:get).once.and_return(response)
|
84
|
+
expect(subject.run).to eq(response.parsed_response)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#expired?' do
|
91
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
92
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
93
|
+
|
94
|
+
context 'request timed out' do
|
95
|
+
it 'shoud return false' do
|
96
|
+
args = { route: 'hello', timeout: 0, time: Time.now - 5 }
|
97
|
+
expect(described_class.new(args).expired?).to be(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'request not timed out' do
|
102
|
+
it 'shoud return false' do
|
103
|
+
args = { route: 'hello', timeout: 100, time: Time.now - 5 }
|
104
|
+
expect(described_class.new(args).expired?).to be(false)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#==' do
|
110
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
111
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
112
|
+
|
113
|
+
subject { described_class.new(route: 'hello', params: { a: 1 }) }
|
114
|
+
|
115
|
+
context 'route does not match' do
|
116
|
+
it 'should return false' do
|
117
|
+
expect(subject == described_class.new(route: 'hi'))
|
118
|
+
.to be(false)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'args do not match' do
|
123
|
+
it 'should return false' do
|
124
|
+
expect(subject == described_class.new(route: 'hello', params: { b: 2 }))
|
125
|
+
.to be(false)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'route and args match' do
|
130
|
+
it 'should return true' do
|
131
|
+
expect(subject == described_class.new(route: 'hello', params: { a: 1 }))
|
132
|
+
.to be(true)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
describe TaskHelper::API do
|
2
|
+
subject { TaskHelper::API }
|
3
|
+
|
4
|
+
it 'should define a singleton accessor for "rest_api_key"' do
|
5
|
+
expect(subject.rest_api_key).to eq(nil)
|
6
|
+
expect { subject.rest_api_key = 'foobar' }
|
7
|
+
.to change { subject.rest_api_key }.from(nil).to('foobar')
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.get' do
|
11
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
12
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
13
|
+
|
14
|
+
it 'should forward to the cache' do
|
15
|
+
expect_any_instance_of(TaskHelper::API::Cache).to receive(:get)
|
16
|
+
.with(route: 'hello')
|
17
|
+
subject.get(route: 'hello')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.set_cache' do
|
22
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
23
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
24
|
+
|
25
|
+
it 'should reset the cache to a new instance with the given arguments' do
|
26
|
+
cache = TaskHelper::API::Cache.new(limit: 2)
|
27
|
+
expect(TaskHelper::API::Cache).to receive(:new).with(limit: 2)
|
28
|
+
.and_return(cache)
|
29
|
+
subject.set_cache(limit: 2)
|
30
|
+
expect(cache).to receive(:get).with(route: 'hello')
|
31
|
+
subject.get(route: 'hello')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.extended' do
|
36
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
37
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
38
|
+
|
39
|
+
it 'should set the cache for the class' do
|
40
|
+
test = Class.new
|
41
|
+
expect(test).to receive(:set_cache)
|
42
|
+
test.extend(subject)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
describe TaskHelper::Database do
|
2
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
3
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
4
|
+
|
5
|
+
describe '.all' do
|
6
|
+
it 'should return an array of databases' do
|
7
|
+
expect(described_class.all.first).to be_a(described_class)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should return databases corresponding to the API response' do
|
11
|
+
expect(described_class.all.map(&:to_h).to_json)
|
12
|
+
.to eq(FixtureParser.databases.to_json)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.find_by' do
|
17
|
+
it 'should return the corresponding database if found' do
|
18
|
+
db = described_class.all.sample
|
19
|
+
expect(described_class.find_by(name: db.name)).to eq(db)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return nil if no database found' do
|
23
|
+
expect(described_class.find_by(name: 'odiasoutee')).to be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.find_by_name' do
|
28
|
+
it 'should return the corresponding database if found' do
|
29
|
+
db = described_class.all.sample
|
30
|
+
expect(described_class.find_by_name(db.name)).to eq(db)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should return nil if no database found' do
|
34
|
+
expect(described_class.find_by_name('odiasoutee')).to be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '.find' do
|
39
|
+
it 'should return the corresponding database if found' do
|
40
|
+
db = described_class.all.sample
|
41
|
+
expect(described_class.find(db.id)).to eq(db)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should retrun nil if the database is not found' do
|
45
|
+
expect(described_class.find('hasdof')).to be_nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'data members' do
|
50
|
+
described_class.data_members.each do |m|
|
51
|
+
describe "##{m}" do
|
52
|
+
it "should return the value of #{m}" do
|
53
|
+
db = described_class.new(FixtureParser.databases.sample)
|
54
|
+
data = FixtureParser.pretty(:database, db.id)
|
55
|
+
expect(db.public_send(m)).to eq(data.send(m))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#created_at' do
|
62
|
+
it 'should return the parsed time of created_at' do
|
63
|
+
db = described_class.all.sample
|
64
|
+
db_hash = FixtureParser.database(db.id)
|
65
|
+
expect(db.created_at).to eq(Time.parse(db_hash['created_at']))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#updated_at' do
|
70
|
+
it 'should return the parsed time of updated_at' do
|
71
|
+
db = described_class.all.sample
|
72
|
+
db_hash = FixtureParser.database(db.id)
|
73
|
+
expect(db.updated_at).to eq(Time.parse(db_hash['updated_at']))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#forms' do
|
78
|
+
it 'should return all forms associated with the database' do
|
79
|
+
db = described_class.all.sample
|
80
|
+
forms = FixtureParser.pretty(:forms, db.id)
|
81
|
+
expect(db.forms.all? { |f| f.kind_of?(TaskHelper::Form) }).to be(true)
|
82
|
+
expect(db.forms).to match_array(forms)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should pre-load the form's database attribute" do
|
86
|
+
db = described_class.all.sample
|
87
|
+
expect(described_class).not_to receive(:find)
|
88
|
+
db.forms.first.database
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe TaskHelper::Field do
|
2
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
3
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
4
|
+
|
5
|
+
describe '.new' do
|
6
|
+
it 'should pass all params except form to super' do
|
7
|
+
form = TaskHelper::Form.all.first
|
8
|
+
field = described_class.new(name: 'foobar', form: form,
|
9
|
+
'entity_id' => form.id)
|
10
|
+
expect(field.name).to eq('foobar')
|
11
|
+
expect(field.entity_id).to eq(form.id)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'given an optional form' do
|
15
|
+
it 'should store the form' do
|
16
|
+
form = TaskHelper::Form.all.first
|
17
|
+
expect(TaskHelper::Form).not_to receive(:find)
|
18
|
+
field = described_class.new(form: form)
|
19
|
+
expect(field.form).to eq(form)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'without optional form' do
|
24
|
+
it 'should fetch the form when needed' do
|
25
|
+
expect(TaskHelper::Form).to receive(:find).at_least(1)
|
26
|
+
described_class.new.form
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#form' do
|
32
|
+
it 'should return the associated form' do
|
33
|
+
field = described_class.new(FixtureParser.fields.sample)
|
34
|
+
expect(field.form).to be_a(TaskHelper::Form)
|
35
|
+
expect(field.form.id).to eq(field.entity_id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'data members' do
|
40
|
+
described_class.data_members.each do |m|
|
41
|
+
describe "##{m}" do
|
42
|
+
it "should return the value of #{m}" do
|
43
|
+
field = described_class.new(FixtureParser.fields.sample)
|
44
|
+
data = FixtureParser.pretty(:field, field.id, field.entity_id)
|
45
|
+
expect(field.public_send(m)).to eq(data.send(m))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
describe TaskHelper::Form do
|
2
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
3
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
4
|
+
|
5
|
+
describe '.new' do
|
6
|
+
it 'should pass all params except database to super' do
|
7
|
+
db = TaskHelper::Database.all.sample
|
8
|
+
form = described_class.new(app_id: db.id, database: db,
|
9
|
+
'name' => 'foobar')
|
10
|
+
expect(form.app_id).to eq(db.id)
|
11
|
+
expect(form.name).to eq('foobar')
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'given an optional database' do
|
15
|
+
it 'should store the database' do
|
16
|
+
db = TaskHelper::Database.all.sample
|
17
|
+
expect(TaskHelper::Database).not_to receive(:find)
|
18
|
+
form = described_class.new(database: db)
|
19
|
+
expect(form.database).to eq(db)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'without optional database' do
|
24
|
+
it 'should fetch the database when needed' do
|
25
|
+
expect(TaskHelper::Database).to receive(:find)
|
26
|
+
described_class.new.database
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.all' do
|
32
|
+
it 'should return all forms for all databases' do
|
33
|
+
forms = FixtureParser.pretty(:forms)
|
34
|
+
expect(described_class.all.all? { |f| f.kind_of?(described_class) })
|
35
|
+
.to be(true)
|
36
|
+
expect(described_class.all).to match_array(forms)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should use a Lazy Enumerator' do
|
40
|
+
expect(described_class.all).to be_an(Enumerator::Lazy)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.find' do
|
45
|
+
it 'should return the corresponding form if found' do
|
46
|
+
form = FixtureParser.pretty(:forms).sample
|
47
|
+
result = described_class.find(database: form.app_id, form: form.id)
|
48
|
+
expect(result).to be_a(described_class)
|
49
|
+
expect(result).to eq(form)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should retrun nil if the form is not found' do
|
53
|
+
expect(described_class.find(database: 'hasdof', form: 'hasdof'))
|
54
|
+
.to be_nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '.find_by' do
|
59
|
+
it 'should return the corresponding form if found' do
|
60
|
+
form = FixtureParser.pretty(:forms).sample
|
61
|
+
db = FixtureParser.pretty(:database, form.app_id)
|
62
|
+
result = described_class.find_by(database_name: db.name,
|
63
|
+
form_name: form.name)
|
64
|
+
expect(result).to be_a(described_class)
|
65
|
+
expect(result).to eq(form)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should retrun nil if the form is not found' do
|
69
|
+
expect(described_class.find_by(database_name: 'hasdof',
|
70
|
+
form_name: 'hasdof')).to be_nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#database' do
|
75
|
+
it 'should return the database associated with the form' do
|
76
|
+
form = described_class.new(FixtureParser.forms.sample)
|
77
|
+
expect(form.database).to be_a(TaskHelper::Database)
|
78
|
+
expect(form.database.id).to eq(form.app_id)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#fields' do
|
83
|
+
it 'should return the associated fields' do
|
84
|
+
form = described_class.new(FixtureParser.forms.sample)
|
85
|
+
expect(form.fields.all? { |f| f.kind_of?(TaskHelper::Field) }).to be(true)
|
86
|
+
expect(form.fields.all? { |f| f.entity_id == form.id }).to be(true)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should pre-load the fields' form attribute" do
|
90
|
+
form = described_class.all.first
|
91
|
+
expect(described_class).not_to receive(:find)
|
92
|
+
form.fields.first.form
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#records' do
|
97
|
+
context 'form has no fields' do
|
98
|
+
it 'should return nil' do
|
99
|
+
if form = described_class.all.find { |f| f.fields.none? }
|
100
|
+
expect(form.records).to be(nil)
|
101
|
+
else
|
102
|
+
expect(TaskHelper::Field).to receive(:get).and_return('fields' => [])
|
103
|
+
expect(described_class.new.records).to be(nil)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'form has at least one field' do
|
109
|
+
it 'should return a lazy enumerator containing the associated records' do
|
110
|
+
if form = described_class.all.find { |f| f.fields.any? }
|
111
|
+
expect(form.records).to be_a(Enumerator::Lazy)
|
112
|
+
expect(form.records.first).to be_a(TaskHelper::Record)
|
113
|
+
expect(form.records.first.entity_id).to eq(form.id)
|
114
|
+
else
|
115
|
+
raise 'No forms with fields found'.inspect
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should pre-load the records' form attribute" do
|
120
|
+
if form = described_class.all.find { |f| f.fields.any? }
|
121
|
+
expect(described_class).not_to receive(:find)
|
122
|
+
form.records.first.form
|
123
|
+
else
|
124
|
+
raise 'No forms with fields found'.inspect
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'data members' do
|
131
|
+
described_class.data_members.each do |m|
|
132
|
+
describe "##{m}" do
|
133
|
+
it "should return the value of #{m}" do
|
134
|
+
form = described_class.new(FixtureParser.forms.sample)
|
135
|
+
data = FixtureParser.pretty(:form, form.id, form.database.id)
|
136
|
+
expect(form.public_send(m)).to eq(data.send(m))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
describe TaskHelper::Record do
|
2
|
+
before(:all) { TaskHelper::API.rest_api_key = 'foobar' }
|
3
|
+
after(:all) { TaskHelper::API.rest_api_key = nil }
|
4
|
+
|
5
|
+
let(:form) { TaskHelper::Form.all.find(:form_with_fields_needed) { |f| f.fields.any? } }
|
6
|
+
let(:data) { FixtureParser.pretty(:records, form.id, form.app_id).sample }
|
7
|
+
subject { described_class.new(data.to_h) }
|
8
|
+
|
9
|
+
describe '.new' do
|
10
|
+
it 'should pass all params except form to super' do
|
11
|
+
form = TaskHelper::Form.all.first
|
12
|
+
record = described_class.new(app_id: form.app_id, form: form,
|
13
|
+
'entity_id' => form.id)
|
14
|
+
expect(record.app_id).to eq(form.app_id)
|
15
|
+
expect(record.entity_id).to eq(form.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given an optional form' do
|
19
|
+
it 'should store the form' do
|
20
|
+
form = TaskHelper::Form.all.first
|
21
|
+
expect(TaskHelper::Form).not_to receive(:find)
|
22
|
+
record = described_class.new(form: form)
|
23
|
+
expect(record.form).to eq(form)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'without optional form' do
|
28
|
+
it 'should fetch the form when needed' do
|
29
|
+
expect(TaskHelper::Form).to receive(:find).at_least(1)
|
30
|
+
described_class.new.form
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#form' do
|
36
|
+
it 'should return the associated form' do
|
37
|
+
expect(subject.form).to eq(form)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#fields' do
|
42
|
+
it 'should return the fields of the associated form' do
|
43
|
+
expect(subject.fields).to match_array(form.fields)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#[]' do
|
48
|
+
it 'should return the value of the field with the given name' do
|
49
|
+
field = form.fields.sample
|
50
|
+
expect(subject[field.name]).to eq(subject.values[field.id])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#pretty_values' do
|
55
|
+
it 'should return the values hashed by field name' do
|
56
|
+
result = subject.values.each_with_object({}) do |(k, v), r|
|
57
|
+
field = form.fields.find { |f| f.id == k }
|
58
|
+
r[field.name] = v
|
59
|
+
end
|
60
|
+
expect(subject.pretty_values).to eq(result)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'data members' do
|
65
|
+
described_class.data_members.each do |m|
|
66
|
+
describe "##{m}" do
|
67
|
+
it "should return the value of #{m}" do
|
68
|
+
expect(subject.public_send(m)).to eq(data.public_send(m))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|