exist 0.1.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ module Exist
2
+ class InsightList < Hashie::Mash
3
+ include Hashie::Extensions::Coercion
4
+
5
+ coerce_key :insights, Array[Insight]
6
+
7
+ def size
8
+ insights.size
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Exist
2
+ class User < Hashie::Mash
3
+ include Hashie::Extensions::Coercion
4
+
5
+ coerce_key :local_time, ->(v) { Time.parse(v) }
6
+ coerce_key :attributes, Array[Exist::Attributes]
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Exist
2
+ VERSION = "0.1.0.beta.2"
3
+ end
@@ -0,0 +1,238 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Exist::API do
4
+ context "initialization" do
5
+ let(:token) { 'SOMETOKEN' }
6
+
7
+ it 'initializes with a token' do
8
+ client = described_class.new(token: token)
9
+ expect(client.api_key).to eq(token)
10
+ end
11
+
12
+ it 'reads the token from environment if not given' do
13
+ ENV['EXIST_API_TOKEN'] = token
14
+ client = described_class.new
15
+ expect(client.api_key).to eq(token)
16
+ end
17
+
18
+ it 'raises an error if no token present' do
19
+ ENV.delete('EXIST_API_TOKEN')
20
+
21
+ expect {
22
+ described_class.new
23
+ }.to raise_error(ArgumentError)
24
+ end
25
+
26
+ it 'negotiates a token if username and password are provided' do
27
+ stub_request(:post, api_root + '/auth/simple-token').to_return(
28
+ body: { token: token }.to_json,
29
+ headers: { 'Content-Type' => 'application/json'}
30
+ )
31
+
32
+ client = described_class.new(username: 'some', password: 'pass')
33
+ expect(client.api_key).to be_truthy
34
+ end
35
+
36
+ it 'raises an error if fails to login' do
37
+ stub_request(:post, api_root + '/auth/simple-token').to_return(
38
+ status: 401
39
+ )
40
+ expect {
41
+ described_class.new(username: 'john', password: 'doe')
42
+ }.to raise_error(/There was a problem authenticating with the API/)
43
+ end
44
+ end
45
+
46
+ context 'API' do
47
+ let(:client) { described_class.new(token: 'SOME') }
48
+
49
+ describe '#me' do
50
+ let(:user) { client.me }
51
+
52
+ before do
53
+ stub_request_with_fixture(:get, '/users/$self/', :user_stripped)
54
+ end
55
+
56
+ it 'returns the current user' do
57
+ expect(user.id).to eq(1)
58
+ expect(user.local_time).to be_kind_of(Time)
59
+ end
60
+ end
61
+
62
+ describe '#overview' do
63
+ let(:overview) { client.overview }
64
+
65
+ before do
66
+ stub_request_with_fixture(:get, '/users/$self/today/', :overview)
67
+ end
68
+
69
+ it 'returns the overview for the current user' do
70
+ expect(overview.username).to eq('josh')
71
+ end
72
+
73
+ it 'coerces keys' do
74
+ expect(overview.local_time).to be_kind_of(Time)
75
+ expect(overview.private).to eq(false)
76
+ end
77
+
78
+ it 'contains attributes' do
79
+ expect(overview.attributes.first.group).to eq('steps')
80
+ expect(overview.attributes.first.items.size).to eq(2)
81
+ expect(overview.attributes.first.items.first.value).to eq(258)
82
+ end
83
+ end
84
+
85
+ describe '#attributes' do
86
+ let(:attributes) { client.attributes }
87
+
88
+ before do
89
+ stub_request_with_fixture(:get, '/users/$self/attributes/?limit=31', :attributes)
90
+ end
91
+
92
+ it 'returns the attributes for the current user' do
93
+ expect(attributes).to be
94
+ end
95
+
96
+ it 'wraps into an attribute list' do
97
+ expect(attributes).to be_kind_of(Exist::AttributeList)
98
+ expect(attributes.size).to eq(2)
99
+ end
100
+
101
+ it 'coerces values' do
102
+ pending
103
+ expect(attributes.first.values.first.date).to be_kind_of(Date)
104
+ end
105
+ end
106
+
107
+ describe '#attribute' do
108
+ let(:attribute) { client.attribute(:steps) }
109
+
110
+ before do
111
+ stub_request_with_fixture(
112
+ :get, '/users/$self/attributes/steps/?date_max=&date_min=&limit=31&page=1',
113
+ :specific_attribute
114
+ )
115
+ end
116
+
117
+ it 'returns a specific attribute' do
118
+ expect(attribute.attributes).to be
119
+ end
120
+
121
+ it 'wraps into an attribute list' do
122
+ expect(attribute.total).to eq(655)
123
+ expect(attribute.size).to eq(7)
124
+ end
125
+ end
126
+
127
+ describe '#insights' do
128
+ let(:insights) { client.insights }
129
+
130
+ before do
131
+ stub_request_with_fixture(
132
+ :get, '/users/$self/insights/?date_max=&date_min=&limit=31&page=1',
133
+ :insights
134
+ )
135
+ end
136
+
137
+ it 'returns the user insights' do
138
+ expect(insights.insights).to be
139
+ end
140
+
141
+ it 'wraps inside an insight list' do
142
+ expect(insights.total).to eq(740)
143
+ expect(insights.size).to eq(2)
144
+ end
145
+ end
146
+
147
+ describe '#insights_for_attribute' do
148
+ let(:insights) { client.insights_for_attribute(:sleep) }
149
+
150
+ before do
151
+ stub_request_with_fixture(
152
+ :get, '/users/$self/insights/attribute/sleep/?date_max=&date_min=&limit=31&page=1',
153
+ :insights_for_specific_attribute
154
+ )
155
+ end
156
+
157
+ it 'returns the specific attribute insights' do
158
+ expect(insights.insights).to be
159
+ end
160
+
161
+ it 'wrap in an insights list' do
162
+ expect(insights.size).to eq(1)
163
+ expect(insights.total).to eq(220)
164
+ end
165
+ end
166
+
167
+ describe '#averages' do
168
+ let(:averages) { client.averages }
169
+
170
+ before do
171
+ stub_request_with_fixture(:get, '/users/$self/averages/', :averages)
172
+ end
173
+
174
+ it 'returns the current averages' do
175
+ expect(averages.averages).to be
176
+ end
177
+
178
+ it 'wraps in an average list' do
179
+ expect(averages.size).to eq(2)
180
+ end
181
+ end
182
+
183
+ describe '#average_for_attribute' do
184
+ let(:average) { client.average_for_attribute(:steps) }
185
+
186
+ before do
187
+ stub_request_with_fixture(
188
+ :get, '/users/$self/averages/attribute/steps/?date_max=&date_min=&limit=31&page=1',
189
+ :average_for_specific_attribute
190
+ )
191
+ end
192
+
193
+ it 'returns the average for an specific attribute' do
194
+ expect(average.averages).to be
195
+ end
196
+
197
+ it 'wraps in an average list' do
198
+ expect(average.size).to eq(2)
199
+ end
200
+ end
201
+
202
+ describe '#correlations' do
203
+ let(:correlations) { client.correlations(:$self, :steps) }
204
+
205
+ before do
206
+ stub_request_with_fixture(
207
+ :get, '/users/$self/correlations/attribute/steps/?date_max=&date_min=&limit=31&page=1',
208
+ :correlations
209
+ )
210
+ end
211
+
212
+ it 'returns the correlations for an attribute' do
213
+ expect(correlations.correlations).to be
214
+ end
215
+
216
+ it 'wraps in a correlation list' do
217
+ expect(correlations.total).to eq(479)
218
+ expect(correlations.size).to eq(2)
219
+ end
220
+
221
+ context 'when specifying latest_only' do
222
+ before do
223
+ stub_request(
224
+ :get,
225
+ api_root + '/users/$self/correlations/attribute/steps/?latest_only=true&limit=31&page=1'
226
+ ).to_return(
227
+ body: {}.to_json,
228
+ headers: { 'Content-Type' => 'application/json'}
229
+ )
230
+ end
231
+
232
+ it 'returns only the latest correlations, avoiding date ranges' do
233
+ client.correlations(:$self, :steps, latest_only: true)
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Exist do
4
+ it "specifies the version" do
5
+ expect(subject.const_get('VERSION')).to_not be_empty
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ [
2
+ {
3
+ "attribute": "steps",
4
+ "label": "Steps",
5
+ "group": "activity",
6
+ "service": "Fitbit",
7
+ "private": false,
8
+ "values": [
9
+ {
10
+ "value": 331,
11
+ "date": "2014-08-01"
12
+ },
13
+ {
14
+ "value": 5872,
15
+ "date": "2014-07-31"
16
+ },
17
+ {
18
+ "value": 2832,
19
+ "date": "2014-07-30"
20
+ },
21
+ {
22
+ "value": 5153,
23
+ "date": "2014-07-29"
24
+ },
25
+ {
26
+ "value": 4354,
27
+ "date": "2014-07-28"
28
+ },
29
+ {
30
+ "value": 7132,
31
+ "date": "2014-07-27"
32
+ },
33
+ {
34
+ "value": 4144,
35
+ "date": "2014-07-26"
36
+ }
37
+ ]
38
+ },
39
+ {
40
+ "attribute": "floors",
41
+ "label": "Floors",
42
+ "group": "activity",
43
+ "service": "Fitbit",
44
+ "private": false,
45
+ "values": [ ]
46
+ }
47
+ ]
@@ -0,0 +1,31 @@
1
+ {
2
+ "count": 11,
3
+ "next": null,
4
+ "previous": null,
5
+ "results": [
6
+ {
7
+ "attribute": "steps",
8
+ "date": "2020-04-29",
9
+ "overall": 4174.0,
10
+ "monday": 4057.0,
11
+ "tuesday": 6614.0,
12
+ "wednesday": 4001.0,
13
+ "thursday": 3923.0,
14
+ "friday": 4528.0,
15
+ "saturday": 3649.0,
16
+ "sunday": 3904.0
17
+ },
18
+ {
19
+ "attribute": "steps",
20
+ "date": "2020-03-30",
21
+ "overall": 4062.0,
22
+ "monday": 4057.0,
23
+ "tuesday": 6618.0,
24
+ "wednesday": 3610.0,
25
+ "thursday": 3923.0,
26
+ "friday": 4063.0,
27
+ "saturday": 3636.0,
28
+ "sunday": 3904.0
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,26 @@
1
+ [
2
+ {
3
+ "attribute": "steps",
4
+ "date": "2020-04-29",
5
+ "overall": 4174.0,
6
+ "monday": 4057.0,
7
+ "tuesday": 6614.0,
8
+ "wednesday": 4001.0,
9
+ "thursday": 3923.0,
10
+ "friday": 4528.0,
11
+ "saturday": 3649.0,
12
+ "sunday": 3904.0
13
+ },
14
+ {
15
+ "attribute": "floors",
16
+ "date": "2020-04-29",
17
+ "overall": 13.0,
18
+ "monday": 13.0,
19
+ "tuesday": 16.0,
20
+ "wednesday": 14.0,
21
+ "thursday": 12.0,
22
+ "friday": 14.0,
23
+ "saturday": 13.0,
24
+ "sunday": 12.0
25
+ }
26
+ ]
@@ -0,0 +1,27 @@
1
+ {
2
+ "count": 479,
3
+ "next": "https://exist.io/api/1/users/josh/correlations/attribute/steps/?page=2",
4
+ "previous": null,
5
+ "results": [
6
+ {
7
+ "date": "2015-05-11",
8
+ "period": 90,
9
+ "attribute": "steps",
10
+ "attribute2": "steps_distance",
11
+ "value": 0.999735821732415,
12
+ "p": 5.43055953485446e-146,
13
+ "first_person": "I am almost certain (100%) to travel a further distance on days I take more steps.",
14
+ "second_person": "You are almost certain (100%) to travel a further distance on days you take more steps."
15
+ },
16
+ {
17
+ "date": "2015-05-11",
18
+ "period": 90,
19
+ "attribute": "steps",
20
+ "attribute2": "floors",
21
+ "value": 0.693332839316818,
22
+ "p": 3.63477333939521e-14,
23
+ "first_person": "I am much more likely (69%) to climb floors on days I take more steps.",
24
+ "second_person": "You are much more likely (69%) to climb floors on days you take more steps."
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "count": 740,
3
+ "next": "https://exist.io/api/1/users/josh/insights/?page=2",
4
+ "previous": null,
5
+ "results": [
6
+ {
7
+ "created": "2015-05-09T01:00:02Z",
8
+ "target_date": "2015-05-08",
9
+ "html": "<div class=\"secondary\">Friday night: Shortest sleep for 3 days</div>...",
10
+ "value": "303",
11
+ "value2": "3 days",
12
+ "comment": null,
13
+ "type": {
14
+ "name": "sleep_worst_since_x",
15
+ "period": 1,
16
+ "priority": 2,
17
+ "attribute": {
18
+ "name": "sleep",
19
+ "label": "Time asleep",
20
+ "group": {
21
+ "name": "sleep",
22
+ "priority": 3
23
+ },
24
+ "priority": 2
25
+ }
26
+ }
27
+ },
28
+ {
29
+ "created": "2015-05-08T21:00:03Z",
30
+ "target_date": null,
31
+ "html": "<div class=\"number\">09:38</div>...",
32
+ "value": "578",
33
+ "value2": "65 min earlier",
34
+ "comment": null,
35
+ "type": {
36
+ "name": "sleep_end_average_week",
37
+ "period": 7,
38
+ "priority": 3,
39
+ "attribute": {
40
+ "name": "sleep_end",
41
+ "label": "Wake time",
42
+ "group": {
43
+ "name": "sleep",
44
+ "priority": 3
45
+ },
46
+ "priority": 4
47
+ }
48
+ }
49
+ }
50
+ ]
51
+ }