keen-cli 0.1.5 → 0.1.6
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.
- data/README.md +77 -49
- data/keen-cli.gemspec +1 -1
- data/lib/keen-cli/batch_processor.rb +104 -0
- data/lib/keen-cli/cli.rb +9 -234
- data/lib/keen-cli/events.rb +70 -0
- data/lib/keen-cli/projects.rb +51 -0
- data/lib/keen-cli/queries.rb +138 -0
- data/lib/keen-cli/shared.rb +28 -0
- data/lib/keen-cli/utils.rb +18 -0
- data/lib/keen-cli/version.rb +1 -1
- data/lib/keen-cli.rb +16 -0
- data/spec/keen-cli/batch_processor_spec.rb +134 -0
- data/spec/keen-cli/cli_spec.rb +4 -161
- data/spec/keen-cli/events_spec.rb +41 -0
- data/spec/keen-cli/projects_spec.rb +42 -0
- data/spec/keen-cli/queries_spec.rb +106 -0
- data/spec/spec_helper.rb +13 -0
- metadata +17 -4
@@ -0,0 +1,51 @@
|
|
1
|
+
module KeenCli
|
2
|
+
|
3
|
+
class CLI < Thor
|
4
|
+
|
5
|
+
desc 'projects:describe', 'Print information about a project'
|
6
|
+
map 'projects:describe' => :projects_describe
|
7
|
+
shared_options
|
8
|
+
|
9
|
+
def projects_describe
|
10
|
+
Utils.process_options!(options)
|
11
|
+
Keen.project_info.tap do |info|
|
12
|
+
Utils.out_json(info, options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'projects:collections', 'Print information about a project\'s collections'
|
17
|
+
map 'projects:collections' => :projects_collections
|
18
|
+
shared_options
|
19
|
+
|
20
|
+
def projects_collections
|
21
|
+
Utils.process_options!(options)
|
22
|
+
Keen.event_collections.tap do |collections|
|
23
|
+
Utils.out_json(collections, options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'projects:open', 'Open a project\'s overview page in a browser'
|
28
|
+
map 'projects:open' => :projects_open
|
29
|
+
shared_options
|
30
|
+
|
31
|
+
def projects_open
|
32
|
+
Utils.process_options!(options)
|
33
|
+
"https://keen.io/project/#{Keen.project_id}".tap do |projects_url|
|
34
|
+
`open #{projects_url}`
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'projects:workbench', 'Open a project\'s workbench page in a browser'
|
39
|
+
map 'projects:workbench' => :projects_workbench
|
40
|
+
shared_options
|
41
|
+
|
42
|
+
def projects_workbench
|
43
|
+
Utils.process_options!(options)
|
44
|
+
"https://keen.io/project/#{Keen.project_id}/workbench".tap do |project_url|
|
45
|
+
`open #{project_url}`
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module KeenCli
|
2
|
+
|
3
|
+
class CLI < Thor
|
4
|
+
|
5
|
+
def self.query_options
|
6
|
+
self.collection_options
|
7
|
+
option :"analysis-type", :aliases => ['-a']
|
8
|
+
option :"group-by", :aliases => ['-g']
|
9
|
+
option :"target-property", :aliases => ['-y']
|
10
|
+
option :interval, :aliases => ['-i']
|
11
|
+
option :timeframe, :aliases => ['-t']
|
12
|
+
option :filters, :aliases => ['-f']
|
13
|
+
option :percentile
|
14
|
+
option :"property-names"
|
15
|
+
option :latest
|
16
|
+
option :email
|
17
|
+
option :start, :aliases => ['s']
|
18
|
+
option :end, :aliases => ['e']
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'queries:run', 'Run a query and print the result'
|
22
|
+
map 'queries:run' => :queries_run
|
23
|
+
shared_options
|
24
|
+
query_options
|
25
|
+
data_options
|
26
|
+
def queries_run(analysis_type=nil)
|
27
|
+
|
28
|
+
Utils.process_options!(options)
|
29
|
+
|
30
|
+
collection = Utils.get_collection_name(options)
|
31
|
+
raise "No collection given!" unless collection
|
32
|
+
|
33
|
+
analysis_type = analysis_type || options[:"analysis-type"]
|
34
|
+
raise "No analysis type given!" unless analysis_type
|
35
|
+
|
36
|
+
query_options = to_query_options(options)
|
37
|
+
|
38
|
+
Keen.query(analysis_type, collection, query_options).tap do |result|
|
39
|
+
if result.is_a?(Hash) || result.is_a?(Array)
|
40
|
+
Utils.out_json(result, options)
|
41
|
+
else
|
42
|
+
Utils.out(result, options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'queries:url', 'Print the URL for a query'
|
48
|
+
map 'queries:url' => :queries_url
|
49
|
+
shared_options
|
50
|
+
query_options
|
51
|
+
data_options
|
52
|
+
option :'exclude-api-key'
|
53
|
+
|
54
|
+
def queries_url
|
55
|
+
|
56
|
+
Utils.process_options!(options)
|
57
|
+
|
58
|
+
collection = Utils.get_collection_name(options)
|
59
|
+
raise "No collection given!" unless collection
|
60
|
+
|
61
|
+
analysis_type = options[:"analysis-type"]
|
62
|
+
raise "No analysis type given!" unless analysis_type
|
63
|
+
|
64
|
+
query_options = to_query_options(options)
|
65
|
+
|
66
|
+
Keen.query_url(analysis_type, collection, query_options,
|
67
|
+
{ :exclude_api_key => options[:'exclude-api-key']}).tap do |url|
|
68
|
+
Utils.out(url, options)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
ANALYSIS_TYPES = %w(average count count-unique extraction median minimum maximum sum percentile select-unique)
|
73
|
+
|
74
|
+
ANALYSIS_TYPES.each do |analysis_type|
|
75
|
+
underscored_analysis_type = analysis_type.sub('-', '_')
|
76
|
+
desc analysis_type, "Alias for queries:run -a #{underscored_analysis_type}"
|
77
|
+
map analysis_type => method_name = "queries_run_#{underscored_analysis_type}"
|
78
|
+
shared_options
|
79
|
+
query_options
|
80
|
+
data_options
|
81
|
+
self.send(:define_method, method_name) { queries_run(underscored_analysis_type) }
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def to_query_options(options)
|
87
|
+
|
88
|
+
data = nil
|
89
|
+
|
90
|
+
if $stdin.tty?
|
91
|
+
data = options[:data]
|
92
|
+
else
|
93
|
+
ARGV.clear
|
94
|
+
ARGF.each_line do |line|
|
95
|
+
data += line
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# setup a holder for query options
|
100
|
+
q_options = {}
|
101
|
+
|
102
|
+
# if data is provided, parse it and merge it
|
103
|
+
unless data.nil?
|
104
|
+
data_options = JSON.parse(data)
|
105
|
+
q_options.merge!(data_options)
|
106
|
+
end
|
107
|
+
|
108
|
+
# copy query options in intelligently
|
109
|
+
q_options[:group_by] = options[:"group-by"]
|
110
|
+
q_options[:target_property] = options[:"target-property"]
|
111
|
+
q_options[:interval] = options[:interval]
|
112
|
+
q_options[:timeframe] = options[:timeframe]
|
113
|
+
q_options[:filters] = options[:filters]
|
114
|
+
q_options[:percentile] = options[:percentile]
|
115
|
+
q_options[:latest] = options[:latest]
|
116
|
+
q_options[:email] = options[:email]
|
117
|
+
|
118
|
+
if property_names = options[:"property-names"]
|
119
|
+
q_options[:property_names] = property_names.split(",")
|
120
|
+
end
|
121
|
+
|
122
|
+
if start_time = options[:start]
|
123
|
+
q_options[:timeframe] = { :start => start_time }
|
124
|
+
end
|
125
|
+
|
126
|
+
if end_time = options[:end]
|
127
|
+
q_options[:timeframe] = q_options[:timeframe] || {}
|
128
|
+
q_options[:timeframe][:end] = end_time
|
129
|
+
end
|
130
|
+
|
131
|
+
q_options.delete_if { |k, v| v.nil? }
|
132
|
+
|
133
|
+
q_options
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module KeenCli
|
2
|
+
|
3
|
+
class CLI < Thor
|
4
|
+
|
5
|
+
def self.shared_options
|
6
|
+
option :project, :aliases => ['-p']
|
7
|
+
option :"master-key", :aliases => ['-k']
|
8
|
+
option :"read-key", :aliases => ['-r']
|
9
|
+
option :"write-key", :aliases => ['-w']
|
10
|
+
option :pretty, :type => :boolean, :default => true
|
11
|
+
option :silent, :type => :boolean, :default => false
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.collection_options
|
15
|
+
option :collection, :aliases => ['-c']
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.data_options
|
19
|
+
option :data, :aliases => ['-d']
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.file_options
|
23
|
+
option :file, :aliases => ['-f']
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/keen-cli/utils.rb
CHANGED
@@ -24,6 +24,24 @@ module KeenCli
|
|
24
24
|
|
25
25
|
end
|
26
26
|
|
27
|
+
def out_json(hash, options)
|
28
|
+
if options[:silent]
|
29
|
+
# do nothing
|
30
|
+
elsif options[:pretty]
|
31
|
+
puts JSON.pretty_generate(hash)
|
32
|
+
else
|
33
|
+
puts JSON.generate(hash)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def out(str, options)
|
38
|
+
if options[:silent]
|
39
|
+
# do nothing
|
40
|
+
else
|
41
|
+
puts str
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
27
45
|
def get_collection_name(options)
|
28
46
|
options["collection"] || options["event_collection"] || ENV['KEEN_COLLECTION_NAME']
|
29
47
|
end
|
data/lib/keen-cli/version.rb
CHANGED
data/lib/keen-cli.rb
CHANGED
@@ -8,3 +8,19 @@ Dotenv.load
|
|
8
8
|
module KeenCli
|
9
9
|
|
10
10
|
end
|
11
|
+
|
12
|
+
class Hash
|
13
|
+
|
14
|
+
def deep_merge(hash)
|
15
|
+
target = dup
|
16
|
+
hash.keys.each do |key|
|
17
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
18
|
+
target[key] = target[key].deep_merge(hash[key])
|
19
|
+
next
|
20
|
+
end
|
21
|
+
target[key] = hash[key]
|
22
|
+
end
|
23
|
+
target
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module KeenCli
|
4
|
+
|
5
|
+
describe BatchProcessor do
|
6
|
+
|
7
|
+
let(:batch_processor) { BatchProcessor.new('signups') }
|
8
|
+
|
9
|
+
describe 'new' do
|
10
|
+
|
11
|
+
it 'defaults batch size to 1000' do
|
12
|
+
expect(batch_processor.batch_size).to eq(1000)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sets the collection' do
|
16
|
+
expect(batch_processor.collection).to eq('signups')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'sets the pretty output' do
|
20
|
+
batch_processor = BatchProcessor.new('signups', :pretty => true)
|
21
|
+
expect(batch_processor.pretty).to eq(true)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets the silent output' do
|
25
|
+
batch_processor = BatchProcessor.new('signups', :silent => true)
|
26
|
+
expect(batch_processor.silent).to eq(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'sets csv and merges csv options with defaults' do
|
30
|
+
csv_processor = BatchProcessor.new('signups', :csv => true, :csv_options => { :headers => ['foo'] })
|
31
|
+
expect(csv_processor.csv).to eq(true)
|
32
|
+
expect(csv_processor.csv_options).to eq(
|
33
|
+
:headers => ['foo'], :converters => :all)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'conversion' do
|
39
|
+
|
40
|
+
let(:batch_processor) { BatchProcessor.new('signups') }
|
41
|
+
|
42
|
+
it 'converts a JSON string to a hash' do
|
43
|
+
batch_processor.add('{ "apple": "sauce", "banana": "pancakes" }')
|
44
|
+
expect(batch_processor.events.first).to eq({
|
45
|
+
"apple" => "sauce",
|
46
|
+
"banana" => "pancakes"
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'converts a param string to a hash' do
|
51
|
+
batch_processor.params = true
|
52
|
+
batch_processor.add('apple=sauce&banana=pancakes')
|
53
|
+
expect(batch_processor.events.first).to eq({
|
54
|
+
"apple" => "sauce",
|
55
|
+
"banana" => "pancakes"
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'converts a csv line to a hash' do
|
60
|
+
batch_processor.csv = true
|
61
|
+
batch_processor.csv_options[:headers] = ['apple', 'banana']
|
62
|
+
batch_processor.add('sauce,pancakes')
|
63
|
+
expect(batch_processor.events.first).to eq({
|
64
|
+
"apple" => "sauce",
|
65
|
+
"banana" => "pancakes"
|
66
|
+
})
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'converts a csv line with dotted properties to nested hashes' do
|
70
|
+
batch_processor.csv = true
|
71
|
+
batch_processor.csv_options[:headers] = ['keen.timestamp', 'apple.date', 'apple.banana.cherry', 'apple.banana.walnut']
|
72
|
+
batch_processor.add('2012-08-09,pudding,smoothie,butter')
|
73
|
+
expect(batch_processor.events.first).to eq({
|
74
|
+
"apple" => {
|
75
|
+
"date" => "pudding",
|
76
|
+
"banana" => {
|
77
|
+
"cherry" => "smoothie",
|
78
|
+
"walnut" => "butter"
|
79
|
+
}
|
80
|
+
},
|
81
|
+
"keen" => {
|
82
|
+
"timestamp" => "2012-08-09"
|
83
|
+
}
|
84
|
+
})
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'add' do
|
90
|
+
|
91
|
+
let(:batch_processor) { BatchProcessor.new('signups', :silent => true) }
|
92
|
+
|
93
|
+
it 'starts empty' do
|
94
|
+
expect(batch_processor.size).to eq(0)
|
95
|
+
expect(batch_processor.events).to be_empty
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'adds events to an array up to batch size and increments count' do
|
99
|
+
batch_processor.add('{ "apple": "sauce", "banana": "pancakes" }')
|
100
|
+
expect(batch_processor.size).to eq(1)
|
101
|
+
expect(batch_processor.events.first).to eq({
|
102
|
+
"apple" => "sauce",
|
103
|
+
"banana" => "pancakes"
|
104
|
+
})
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'flushes at the batch size' do
|
108
|
+
stub_request(:post, "https://api.keen.io/3.0/projects/#{Keen.project_id}/events").
|
109
|
+
with(:body => "{\"signups\":[{\"apple\":\"sauce\",\"banana\":\"pancakes\"},{\"apple\":\"sauce\",\"banana\":\"pancakes\"}]}").
|
110
|
+
to_return(:status => 200, :body => { "signups" => [{ "created" => true }] }.to_json)
|
111
|
+
batch_processor.batch_size = 2
|
112
|
+
batch_processor.add('{ "apple": "sauce", "banana": "pancakes" }')
|
113
|
+
expect(batch_processor.size).to eq(1)
|
114
|
+
batch_processor.add('{ "apple": "sauce", "banana": "pancakes" }')
|
115
|
+
expect(batch_processor.size).to eq(0)
|
116
|
+
expect(batch_processor.events).to be_empty
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'flush' do
|
122
|
+
|
123
|
+
let(:batch_processor) { BatchProcessor.new('signups') }
|
124
|
+
|
125
|
+
it 'does not flush if there are no events' do
|
126
|
+
batch_processor.size = 0
|
127
|
+
batch_processor.flush
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/spec/keen-cli/cli_spec.rb
CHANGED
@@ -2,171 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe KeenCli::CLI do
|
4
4
|
|
5
|
-
let(:project_id) {
|
6
|
-
let(:master_key) {
|
7
|
-
let(:read_key) {
|
8
|
-
let(:write_key) {
|
9
|
-
|
10
|
-
def start(str=nil)
|
11
|
-
KeenCli::CLI.start(str ? str.split(" ") : [])
|
12
|
-
end
|
13
|
-
|
14
|
-
before do
|
15
|
-
Keen.project_id = project_id
|
16
|
-
Keen.read_key = read_key
|
17
|
-
Keen.write_key = write_key
|
18
|
-
Keen.master_key = master_key
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'prints help by default' do
|
22
|
-
_, options = start
|
23
|
-
expect(_).to be_empty
|
24
|
-
end
|
5
|
+
let(:project_id) { Keen.project_id }
|
6
|
+
let(:master_key) { Keen.master_key }
|
7
|
+
let(:read_key) { Keen.read_key }
|
8
|
+
let(:write_key) { Keen.write_key }
|
25
9
|
|
26
10
|
it 'prints version info if -v is used' do
|
27
11
|
_, options = start "-v"
|
28
12
|
expect(_).to match /version/
|
29
13
|
end
|
30
14
|
|
31
|
-
describe 'project:describe' do
|
32
|
-
it 'gets the project' do
|
33
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}"
|
34
|
-
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
35
|
-
_, options = start 'project:describe'
|
36
|
-
expect(_).to eq("fake" => "response")
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'uses the project id param if present' do
|
40
|
-
url = "https://api.keen.io/3.0/projects/GGGG"
|
41
|
-
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
42
|
-
_, options = start 'project:describe --project GGGG'
|
43
|
-
expect(_).to eq("fake" => "response")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe 'project:collections' do
|
48
|
-
it 'prints the project\'s collections' do
|
49
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/events"
|
50
|
-
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
51
|
-
_, options = start 'project:collections'
|
52
|
-
expect(_).to eq("fake" => "response")
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'uses the project id param if present' do
|
56
|
-
url = "https://api.keen.io/3.0/projects/GGGG/events"
|
57
|
-
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
58
|
-
_, options = start 'project:collections --project GGGG'
|
59
|
-
expect(_).to eq("fake" => "response")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe 'queries:run' do
|
64
|
-
it 'runs the query using certain params' do
|
65
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths"
|
66
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
67
|
-
_, options = start 'queries:run --analysis-type count --collection minecraft-deaths'
|
68
|
-
expect(_).to eq(10)
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'runs the query using aliased params' do
|
72
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths"
|
73
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
74
|
-
_, options = start 'queries:run -a count -c minecraft-deaths'
|
75
|
-
expect(_).to eq(10)
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'converts dashes to underscores for certain properties' do
|
79
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths&group_by=foo&target_property=bar"
|
80
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
81
|
-
_, options = start 'queries:run --analysis-type count --collection minecraft-deaths --group-by foo --target-property bar'
|
82
|
-
expect(_).to eq(10)
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'accepts extraction-specific properties' do
|
86
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/extraction?event_collection=minecraft-deaths&property_names=%5B%22foo%22,%22bar%22%5D&latest=1&email=bob@bob.io"
|
87
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
88
|
-
_, options = start 'queries:run --analysis-type extraction --collection minecraft-deaths --property-names foo,bar --latest 1 --email bob@bob.io'
|
89
|
-
expect(_).to eq(10)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'converts comma-delimited property names to an array' do
|
93
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/extraction?event_collection=minecraft-deaths&property_names=%5B%22foo%22,%22bar%22%5D"
|
94
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
95
|
-
_, options = start 'queries:run --analysis-type extraction --collection minecraft-deaths --property-names foo,bar'
|
96
|
-
expect(_).to eq(10)
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
it 'uses a data option to take in query JSON' do
|
101
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths"
|
102
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
103
|
-
_, options = start 'queries:run --analysis-type count --data {"event_collection":"minecraft-deaths"}'
|
104
|
-
expect(_).to eq(10)
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'converts a start parameter into an absolute timeframe' do
|
108
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths&timeframe=%7B%22start%22:%222014-07-06T12:00:00Z%22%7D"
|
109
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
110
|
-
_, options = start 'queries:run --collection minecraft-deaths --analysis-type count --start 2014-07-06T12:00:00Z'
|
111
|
-
expect(_).to eq(10)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'converts an end parameter into an absolute timeframe' do
|
115
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths&timeframe=%7B%22end%22:%222014-07-06T12:00:00Z%22%7D"
|
116
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
117
|
-
_, options = start 'queries:run --collection minecraft-deaths --analysis-type count --end 2014-07-06T12:00:00Z'
|
118
|
-
expect(_).to eq(10)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'converts start and end parameters into an absolute timeframe' do
|
122
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/count?event_collection=minecraft-deaths&timeframe=%7B%22start%22:%222014-07-06T12:00:00Z%22,%22end%22:%222014-07-08T12:00:00Z%22%7D"
|
123
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
124
|
-
_, options = start 'queries:run --collection minecraft-deaths --analysis-type count --start 2014-07-06T12:00:00Z --end 2014-07-08T12:00:00Z'
|
125
|
-
expect(_).to eq(10)
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
describe "queries:run aliases" do
|
131
|
-
KeenCli::CLI::ANALYSIS_TYPES.each do |analysis_type|
|
132
|
-
describe analysis_type do
|
133
|
-
it "aliases to queries run, passing along the #{analysis_type} analysis type" do
|
134
|
-
underscored_analysis_type = analysis_type.sub('-', '_')
|
135
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/queries/#{underscored_analysis_type}?event_collection=minecraft-deaths"
|
136
|
-
stub_request(:get, url).to_return(:body => { :result => 10 }.to_json)
|
137
|
-
_, options = start "#{analysis_type} --collection minecraft-deaths"
|
138
|
-
expect(_).to eq(10)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
describe 'events:add' do
|
145
|
-
it 'should accept JSON events from a data param' do
|
146
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/events/minecraft-deaths"
|
147
|
-
stub_request(:post, url).
|
148
|
-
with(:body => { "foo" => 1 }).
|
149
|
-
to_return(:body => { :created => true }.to_json)
|
150
|
-
_, options = start 'events:add --collection minecraft-deaths --data {"foo":1}'
|
151
|
-
expect(_).to eq("created" => true)
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'should accept JSON events from a file param' do
|
155
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/events/minecraft-deaths"
|
156
|
-
stub_request(:post, "https://api.keen.io/3.0/projects/AAAAAAA/events").
|
157
|
-
with(:body => "{\"minecraft-deaths\":[{\"foo\":1},{\"foo\":2},{\"foo\":3}]}").
|
158
|
-
to_return(:body => { :created => true }.to_json)
|
159
|
-
_, options = start "events:add --collection minecraft-deaths --file #{File.expand_path('../../fixtures/events.json', __FILE__)}"
|
160
|
-
expect(_).to eq("created" => true)
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'should accept JSON events from a file param in CSV format' do
|
164
|
-
url = "https://api.keen.io/3.0/projects/#{project_id}/events/minecraft-deaths"
|
165
|
-
stub_request(:post, "https://api.keen.io/3.0/projects/AAAAAAA/events").
|
166
|
-
with(:body => "{\"minecraft-deaths\":[{\"foo\":1},{\"foo\":2},{\"foo\":3}]}").
|
167
|
-
to_return(:body => { :created => true }.to_json)
|
168
|
-
_, options = start "events:add --collection minecraft-deaths --csv --file #{File.expand_path('../../fixtures/events.csv', __FILE__)}"
|
169
|
-
expect(_).to eq("created" => true)
|
170
|
-
end
|
171
|
-
end
|
172
15
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe KeenCli::CLI do
|
4
|
+
|
5
|
+
describe 'events:add' do
|
6
|
+
|
7
|
+
it 'adds a blank event' do
|
8
|
+
stub_request(:post, "https://api.keen.io/3.0/projects/#{Keen.project_id}/events").
|
9
|
+
with(:body => "{\"minecraft-deaths\":[{}]}").
|
10
|
+
to_return(:body => { :created => true }.to_json)
|
11
|
+
_, options = start 'events:add --collection minecraft-deaths'
|
12
|
+
expect(_).to eq(1)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'accepts JSON events from a data param' do
|
16
|
+
stub_request(:post, "https://api.keen.io/3.0/projects/#{Keen.project_id}/events").
|
17
|
+
with(:body => "{\"minecraft-deaths\":[{\"foo\":1}]}").
|
18
|
+
to_return(:body => { :created => true }.to_json)
|
19
|
+
_, options = start 'events:add --collection minecraft-deaths --data {"foo":1}'
|
20
|
+
expect(_).to eq(1)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'accepts JSON events from a file param' do
|
24
|
+
stub_request(:post, "https://api.keen.io/3.0/projects/#{Keen.project_id}/events").
|
25
|
+
with(:body => "{\"minecraft-deaths\":[{\"foo\":1},{\"foo\":2},{\"foo\":3}]}").
|
26
|
+
to_return(:body => { :created => true }.to_json)
|
27
|
+
_, options = start "events:add --collection minecraft-deaths --file #{File.expand_path('../../fixtures/events.json', __FILE__)}"
|
28
|
+
expect(_).to eq(3)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'accepts JSON events from a file param in CSV format' do
|
32
|
+
stub_request(:post, "https://api.keen.io/3.0/projects/#{Keen.project_id}/events").
|
33
|
+
with(:body => "{\"minecraft-deaths\":[{\"foo\":1},{\"foo\":2},{\"foo\":3}]}").
|
34
|
+
to_return(:body => { :created => true }.to_json)
|
35
|
+
_, options = start "events:add --collection minecraft-deaths --csv --file #{File.expand_path('../../fixtures/events.csv', __FILE__)}"
|
36
|
+
expect(_).to eq(4)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe KeenCli::CLI do
|
4
|
+
|
5
|
+
let(:project_id) { Keen.project_id }
|
6
|
+
let(:master_key) { Keen.master_key }
|
7
|
+
let(:read_key) { Keen.read_key }
|
8
|
+
let(:write_key) { Keen.write_key }
|
9
|
+
|
10
|
+
describe 'projects:describe' do
|
11
|
+
it 'gets the project' do
|
12
|
+
url = "https://api.keen.io/3.0/projects/#{project_id}"
|
13
|
+
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
14
|
+
_, options = start 'projects:describe'
|
15
|
+
expect(_).to eq("fake" => "response")
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'uses the project id param if present' do
|
19
|
+
url = "https://api.keen.io/3.0/projects/GGGG"
|
20
|
+
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
21
|
+
_, options = start 'projects:describe --project GGGG'
|
22
|
+
expect(_).to eq("fake" => "response")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'projects:collections' do
|
27
|
+
it 'prints the project\'s collections' do
|
28
|
+
url = "https://api.keen.io/3.0/projects/#{project_id}/events"
|
29
|
+
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
30
|
+
_, options = start 'projects:collections'
|
31
|
+
expect(_).to eq("fake" => "response")
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'uses the project id param if present' do
|
35
|
+
url = "https://api.keen.io/3.0/projects/GGGG/events"
|
36
|
+
stub_request(:get, url).to_return(:body => { :fake => "response" }.to_json)
|
37
|
+
_, options = start 'projects:collections --project GGGG'
|
38
|
+
expect(_).to eq("fake" => "response")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|