exist 0.1.0.beta.2

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.
@@ -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
+ }