gooddata 0.6.10 → 0.6.11
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 +4 -4
- data/.rubocop.yml +9 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/README.md +1 -0
- data/gooddata.gemspec +38 -40
- data/lib/gooddata/bricks/base_downloader.rb +1 -1
- data/lib/gooddata/bricks/middleware/base_middleware.rb +36 -0
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +8 -38
- data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +14 -0
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +7 -6
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +7 -5
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +1 -1
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +20 -14
- data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +33 -0
- data/lib/gooddata/cli/commands/api_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/console_cmd.rb +2 -2
- data/lib/gooddata/cli/commands/process_cmd.rb +54 -7
- data/lib/gooddata/cli/commands/project_cmd.rb +9 -9
- data/lib/gooddata/cli/commands/projects_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +24 -7
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +2 -2
- data/lib/gooddata/cli/commands/user_cmd.rb +1 -1
- data/lib/gooddata/cli/hooks.rb +3 -3
- data/lib/gooddata/commands/datasets.rb +1 -1
- data/lib/gooddata/commands/project.rb +2 -2
- data/lib/gooddata/commands/role.rb +1 -1
- data/lib/gooddata/commands/runners.rb +2 -2
- data/lib/gooddata/connection.rb +2 -2
- data/lib/gooddata/core/nil_logger.rb +1 -1
- data/lib/gooddata/core/rest.rb +12 -8
- data/lib/gooddata/data/guesser.rb +1 -1
- data/lib/gooddata/exceptions/attr_element_not_found.rb +1 -1
- data/lib/gooddata/extensions/enumerable.rb +1 -1
- data/lib/gooddata/extensions/hash.rb +20 -0
- data/lib/gooddata/helpers/csv_helper.rb +1 -1
- data/lib/gooddata/helpers/global_helpers.rb +59 -1
- data/lib/gooddata/mixins/md_lock.rb +83 -0
- data/lib/gooddata/mixins/md_object_indexer.rb +1 -1
- data/lib/gooddata/mixins/md_object_query.rb +1 -1
- data/lib/gooddata/mixins/md_relations.rb +0 -9
- data/lib/gooddata/models/dashboard_builder.rb +1 -1
- data/lib/gooddata/models/domain.rb +2 -2
- data/lib/gooddata/models/empty_result.rb +5 -5
- data/lib/gooddata/models/execution.rb +74 -0
- data/lib/gooddata/models/execution_detail.rb +74 -0
- data/lib/gooddata/models/membership.rb +1 -1
- data/lib/gooddata/models/metadata/attribute.rb +4 -6
- data/lib/gooddata/models/metadata/dashboard.rb +2 -0
- data/lib/gooddata/models/metadata/fact.rb +2 -2
- data/lib/gooddata/models/metadata/metric.rb +4 -1
- data/lib/gooddata/models/metadata/report.rb +84 -34
- data/lib/gooddata/models/metadata/report_definition.rb +28 -17
- data/lib/gooddata/models/metadata.rb +1 -1
- data/lib/gooddata/models/model.rb +1 -1
- data/lib/gooddata/models/process.rb +70 -54
- data/lib/gooddata/models/profile.rb +47 -10
- data/lib/gooddata/models/project.rb +74 -30
- data/lib/gooddata/models/project_blueprint.rb +9 -10
- data/lib/gooddata/models/project_builder.rb +2 -2
- data/lib/gooddata/models/project_creator.rb +4 -4
- data/lib/gooddata/models/report_data_result.rb +1 -1
- data/lib/gooddata/models/schedule.rb +39 -32
- data/lib/gooddata/models/to_manifest.rb +5 -5
- data/lib/gooddata/models/to_wire.rb +3 -3
- data/lib/gooddata/rest/client.rb +64 -31
- data/lib/gooddata/rest/connection.rb +7 -7
- data/lib/gooddata/rest/connections/dummy_connection.rb +5 -5
- data/lib/gooddata/rest/connections/rest_client_connection.rb +106 -44
- data/lib/gooddata/rest/object.rb +1 -1
- data/lib/gooddata/version.rb +1 -1
- data/spec/bricks/bricks_spec.rb +67 -0
- data/spec/bricks/default-config.json +8 -0
- data/spec/data/gooddata_version_process/gooddata_version.rb +3 -0
- data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
- data/spec/data/ruby_params_process/ruby_params.rb +3 -0
- data/spec/helpers/process_helper.rb +12 -0
- data/spec/helpers/schedule_helper.rb +21 -0
- data/spec/integration/create_project_spec.rb +19 -0
- data/spec/integration/full_process_schedule_spec.rb +129 -8
- data/spec/integration/full_project_spec.rb +52 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/core/rest_spec.rb +76 -3
- data/spec/unit/helpers_spec.rb +43 -0
- data/spec/unit/models/metric_spec.rb +33 -0
- data/spec/unit/models/params_spec.rb +96 -0
- data/spec/unit/models/profile_spec.rb +16 -0
- data/spec/unit/models/schedule_spec.rb +12 -3
- metadata +350 -187
- data/lib/gooddata/helper/class_helper.rb +0 -1
- data/lib/gooddata/helper/helpers.rb +0 -8
data/lib/gooddata/rest/object.rb
CHANGED
data/lib/gooddata/version.rb
CHANGED
data/spec/bricks/bricks_spec.rb
CHANGED
@@ -17,6 +17,73 @@ describe GoodData::Bricks do
|
|
17
17
|
p.call({})
|
18
18
|
end
|
19
19
|
|
20
|
+
describe "#load_defaults" do
|
21
|
+
context "when you define a middleware with default_loaded_call and give it some defaults file with prefix" do
|
22
|
+
class TestMiddleWare < GoodData::Bricks::Middleware
|
23
|
+
def initialize(options={})
|
24
|
+
@config = 'spec/bricks/default-config.json'
|
25
|
+
super(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(params)
|
29
|
+
params = super(params)
|
30
|
+
my_stuff = params['config']['my']['namespace']
|
31
|
+
puts "Now I have the defaults and runtime parameters merged and loaded: #{my_stuff['key']}"
|
32
|
+
|
33
|
+
# Doing something cool and puting it into params
|
34
|
+
params['something_cool'] = "#{my_stuff['key']} and also #{my_stuff['default_key']}"
|
35
|
+
|
36
|
+
@app.call(params)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class TestBrick
|
41
|
+
def call(params)
|
42
|
+
# doing something with params
|
43
|
+
puts "Brick: #{params['something_cool']}"
|
44
|
+
params
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "puts them into params" do
|
49
|
+
p = GoodData::Bricks::Pipeline.prepare([
|
50
|
+
TestMiddleWare,
|
51
|
+
TestBrick
|
52
|
+
])
|
53
|
+
|
54
|
+
res = p.call({
|
55
|
+
'config' => {
|
56
|
+
'my' => {
|
57
|
+
'namespace' => {
|
58
|
+
'key' => 'redefined value',
|
59
|
+
'new_key' => 'new value'
|
60
|
+
}
|
61
|
+
},
|
62
|
+
'other_namespace' => {
|
63
|
+
'some_key' => 'some value'
|
64
|
+
}
|
65
|
+
}
|
66
|
+
})
|
67
|
+
|
68
|
+
res.should eq({
|
69
|
+
'config' => {
|
70
|
+
'my' => {
|
71
|
+
'namespace' => {
|
72
|
+
'key' => 'redefined value',
|
73
|
+
'new_key' => 'new value',
|
74
|
+
'default_key' => 'default value 2'
|
75
|
+
}
|
76
|
+
},
|
77
|
+
'other_namespace' => {
|
78
|
+
'some_key' => 'some value'
|
79
|
+
}
|
80
|
+
},
|
81
|
+
"something_cool" => "redefined value and also default value 2"
|
82
|
+
})
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
20
87
|
|
21
88
|
# TODO: Better test pre and post so we are sure it is executed in right order
|
22
89
|
it "should be possible to use instance both as middleware and app" do
|
Binary file
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# Global requires
|
4
4
|
require 'multi_json'
|
5
|
+
require 'pmap'
|
5
6
|
|
6
7
|
# Local requires
|
7
8
|
require 'gooddata/models/models'
|
@@ -9,4 +10,15 @@ require 'gooddata/models/models'
|
|
9
10
|
module ProcessHelper
|
10
11
|
PROCESS_ID = 'dc143d80-58a1-4acd-96b6-8d11fc4571de'
|
11
12
|
DEPLOY_NAME = 'graph'
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def remove_old_processes(project)
|
16
|
+
processes = project.processes
|
17
|
+
processes.pmap do |process|
|
18
|
+
next if process.obj_id == PROCESS_ID
|
19
|
+
puts "Deleting #{process.inspect}"
|
20
|
+
process.delete
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
12
24
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'pmap'
|
4
|
+
|
5
|
+
require_relative 'process_helper'
|
6
|
+
|
7
|
+
module ScheduleHelper
|
8
|
+
SCHEDULE_ID = '53e029bde4b035034ad4abb6'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def remove_old_schedules(project)
|
12
|
+
schedules = project.schedules
|
13
|
+
schedules.pmap do |schedule|
|
14
|
+
next if schedule.obj_id == SCHEDULE_ID
|
15
|
+
|
16
|
+
puts "Deleting #{schedule.inspect}"
|
17
|
+
schedule.delete
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'gooddata'
|
2
|
+
|
3
|
+
describe 'Create project using GoodData client', :constraint => 'slow' do
|
4
|
+
before(:all) do
|
5
|
+
@client = ConnectionHelper.create_default_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:all) do
|
9
|
+
@client.disconnect
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'Should create project using GoodData::Rest::Client#create_project' do
|
13
|
+
project_title = 'Test #create_project'
|
14
|
+
project = @client.create_project(:title => project_title, :auth_token => ConnectionHelper::GD_PROJECT_TOKEN)
|
15
|
+
expect(project.title).to eq(project_title)
|
16
|
+
project.delete
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -1,6 +1,25 @@
|
|
1
1
|
require 'gooddata'
|
2
2
|
|
3
3
|
describe "Full process and schedule exercise", :constraint => 'slow' do
|
4
|
+
COMPLEX_PARAMS ||= {
|
5
|
+
type: 'Person',
|
6
|
+
model_version: 1,
|
7
|
+
data_version: 1.5,
|
8
|
+
some_true_flag: true,
|
9
|
+
some_false_flag: false,
|
10
|
+
empty_value: nil,
|
11
|
+
user: {
|
12
|
+
firstname: 'Joe',
|
13
|
+
lastname: 'Doe',
|
14
|
+
age: 42
|
15
|
+
},
|
16
|
+
address: {
|
17
|
+
street: '#111 Sutter St.',
|
18
|
+
city: 'San Francisco',
|
19
|
+
zip: '94133'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
4
23
|
before(:all) do
|
5
24
|
@client = ConnectionHelper::create_default_connection
|
6
25
|
@project = @client.create_project(title: 'Project for schedule testing', auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
|
@@ -17,23 +36,50 @@ describe "Full process and schedule exercise", :constraint => 'slow' do
|
|
17
36
|
|
18
37
|
it "should be able to execute a process" do
|
19
38
|
result = @process.execute(@process.executables.first)
|
20
|
-
log =
|
39
|
+
log = result.log
|
21
40
|
expect(log.index('Hello Ruby executors')).not_to eq nil
|
22
41
|
expect(log.index('Hello Ruby from the deep')).not_to eq nil
|
23
42
|
end
|
24
43
|
|
25
|
-
it "should be able to
|
44
|
+
it "should be able to start executing a process" do
|
45
|
+
result = @process.start_execution(@process.executables.first)
|
46
|
+
expect(result["executionTask"]).not_to be_nil
|
47
|
+
expect(result["executionTask"]['links']['detail']).not_to be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be able to grab executables" do
|
26
51
|
|
27
|
-
expect(@process.executables).to eq ['
|
52
|
+
expect(@process.executables).to eq ['process.rb']
|
28
53
|
end
|
29
54
|
|
30
|
-
it "should have empty schedules on deploy" do
|
55
|
+
it "should have empty schedules on deploy" do
|
31
56
|
expect(@process.schedules).to eq []
|
32
57
|
end
|
33
58
|
|
59
|
+
it "should be able to create schedule triggered by another schedule" do
|
60
|
+
schedule_first = @process.create_schedule('0 15 27 7 *', @process.executables.first)
|
61
|
+
schedule = @process.create_schedule(schedule_first, @process.executables.first)
|
62
|
+
res = @process.schedules
|
63
|
+
expect(res.count).to eq 2
|
64
|
+
expect(@process.schedules.map(&:uri)).to include(schedule_first.uri, schedule.uri)
|
65
|
+
schedule.delete
|
66
|
+
schedule_first.delete
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should be able to create schedule triggered by another schedule specified by ID" do
|
70
|
+
schedule_first = @process.create_schedule('0 15 27 7 *', @process.executables.first)
|
71
|
+
schedule = @process.create_schedule(schedule_first.obj_id, @process.executables.first)
|
72
|
+
res = @process.schedules
|
73
|
+
expect(res.count).to eq 2
|
74
|
+
expect(@process.schedules.map(&:uri)).to include(schedule_first.uri, schedule.uri)
|
75
|
+
schedule.delete
|
76
|
+
schedule_first.delete
|
77
|
+
end
|
78
|
+
|
34
79
|
it "should be able to delete schedule" do
|
35
80
|
schedule = @process.create_schedule('0 15 27 7 *', @process.executables.first)
|
36
|
-
|
81
|
+
res = @process.schedules
|
82
|
+
expect(res.count).to eq 1
|
37
83
|
expect(@process.schedules).to eq [schedule]
|
38
84
|
schedule.delete
|
39
85
|
end
|
@@ -47,7 +93,8 @@ describe "Full process and schedule exercise", :constraint => 'slow' do
|
|
47
93
|
it "should be possible to execute schedule" do
|
48
94
|
schedule = @process.create_schedule('0 15 27 7 *', @process.executables.first)
|
49
95
|
result = schedule.execute
|
50
|
-
|
96
|
+
expect(result.status).to eq :ok
|
97
|
+
log = result.log
|
51
98
|
expect(log.index('Hello Ruby executors')).not_to eq nil
|
52
99
|
expect(log.index('Hello Ruby from the deep')).not_to eq nil
|
53
100
|
end
|
@@ -59,7 +106,8 @@ describe "Full process and schedule exercise", :constraint => 'slow' do
|
|
59
106
|
begin
|
60
107
|
schedule = process.create_schedule('0 15 27 7 *', process.executables.first)
|
61
108
|
result = schedule.execute
|
62
|
-
|
109
|
+
expect(result.status).to eq :ok
|
110
|
+
log = result.log
|
63
111
|
expect(log.index('HELLO WORLD')).not_to eq nil
|
64
112
|
expect(schedule.enabled?).to be_true
|
65
113
|
schedule.disable
|
@@ -70,6 +118,7 @@ describe "Full process and schedule exercise", :constraint => 'slow' do
|
|
70
118
|
schedule.save
|
71
119
|
expect(schedule.enabled?).to be_true
|
72
120
|
ensure
|
121
|
+
schedule && schedule.delete
|
73
122
|
process && process.delete
|
74
123
|
end
|
75
124
|
end
|
@@ -82,9 +131,81 @@ describe "Full process and schedule exercise", :constraint => 'slow' do
|
|
82
131
|
expect(process.schedules.count).to eq 0
|
83
132
|
schedule = process.create_schedule('0 15 27 7 *', process.executables.first)
|
84
133
|
result = schedule.execute
|
85
|
-
|
134
|
+
expect(result.status).to eq :ok
|
135
|
+
log = result.log
|
86
136
|
expect(log.index('HELLO WORLD')).not_to eq nil
|
87
137
|
expect(process.schedules.count).to eq 1
|
138
|
+
ensure
|
139
|
+
schedule && schedule.delete
|
140
|
+
process && process.delete
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should be possible to deploy and run zipped file and print GoodData::VERSION' do
|
145
|
+
process = @project.deploy_process('./spec/data/gooddata_version_process/gooddata_version.zip',
|
146
|
+
type: 'RUBY',
|
147
|
+
name: 'Test ETL zipped file GoodData Process')
|
148
|
+
begin
|
149
|
+
expect(process.schedules.count).to eq 0
|
150
|
+
schedule = process.create_schedule('0 15 27 7 *', process.executables.first)
|
151
|
+
result = schedule.execute
|
152
|
+
expect(result.status).to eq :ok
|
153
|
+
log = result.log
|
154
|
+
expect(log.index(GoodData::VERSION)).not_to eq nil
|
155
|
+
expect(process.schedules.count).to eq 1
|
156
|
+
ensure
|
157
|
+
schedule && schedule.delete
|
158
|
+
process && process.delete
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should be possible to deploy and run directory and use nested parameters' do
|
163
|
+
process = @project.deploy_process('./spec/data/ruby_params_process',
|
164
|
+
type: 'RUBY',
|
165
|
+
name: 'Test ETL dir GoodData Process')
|
166
|
+
begin
|
167
|
+
expect(process.schedules.count).to eq 0
|
168
|
+
schedule = process.create_schedule('0 15 27 7 *', process.executables.first, params: COMPLEX_PARAMS)
|
169
|
+
result = schedule.execute
|
170
|
+
expect(result.status).to eq :ok
|
171
|
+
log = result.log
|
172
|
+
expect(log.index('Joe')).not_to eq nil
|
173
|
+
expect(log.index('San Francisco')).not_to eq nil
|
174
|
+
expect(process.schedules.count).to eq 1
|
175
|
+
ensure
|
176
|
+
schedule && schedule.delete
|
177
|
+
process && process.delete
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should be possible to deploy and run directory and use nested hidden parameters' do
|
182
|
+
process = @project.deploy_process('./spec/data/ruby_params_process',
|
183
|
+
type: 'RUBY',
|
184
|
+
name: 'Test ETL dir GoodData Process')
|
185
|
+
begin
|
186
|
+
expect(process.schedules.count).to eq 0
|
187
|
+
schedule = process.create_schedule('0 15 27 7 *', process.executables.first, hidden_params: COMPLEX_PARAMS)
|
188
|
+
result = schedule.execute
|
189
|
+
# expect(result.status).to eq :ok
|
190
|
+
log = result.log
|
191
|
+
expect(process.schedules.count).to eq 1
|
192
|
+
ensure
|
193
|
+
schedule && schedule.delete
|
194
|
+
process && process.delete
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be possible to download deployed process" do
|
199
|
+
size = File.size('./spec/data/hello_world_process/hello_world.zip')
|
200
|
+
process = @project.deploy_process('./spec/data/hello_world_process/hello_world.zip',
|
201
|
+
type: 'RUBY',
|
202
|
+
name: 'Test ETL zipped file Process')
|
203
|
+
begin
|
204
|
+
Tempfile.open('downloaded-process') do |temp|
|
205
|
+
temp << process.download
|
206
|
+
temp.flush
|
207
|
+
expect(File.size(temp.path)).to eq size
|
208
|
+
end
|
88
209
|
ensure
|
89
210
|
process && process.delete
|
90
211
|
end
|
@@ -109,6 +109,26 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
109
109
|
expect(result2).to eq result
|
110
110
|
end
|
111
111
|
|
112
|
+
it "should be able to lock reports and everything underneath" do
|
113
|
+
m = @project.metrics.first
|
114
|
+
r = @project.create_report(top: [m], title: 'xy')
|
115
|
+
r.save
|
116
|
+
expect(m.locked?).to eq false
|
117
|
+
expect(r.locked?).to eq false
|
118
|
+
r.lock_with_dependencies!
|
119
|
+
expect(r.locked?).to eq true
|
120
|
+
m.reload!
|
121
|
+
expect(m.locked?).to eq true
|
122
|
+
r.unlock_with_dependencies!
|
123
|
+
expect(r.locked?).to eq false
|
124
|
+
m.reload!
|
125
|
+
expect(m.locked?).to eq false
|
126
|
+
r.lock!
|
127
|
+
expect(r.locked?).to eq true
|
128
|
+
r.unlock!
|
129
|
+
expect(r.locked?).to eq false
|
130
|
+
end
|
131
|
+
|
112
132
|
it "should be able to purge report from older revisions" do
|
113
133
|
m = @project.metrics.first
|
114
134
|
r = @project.create_report(top: [m], title: 'xy')
|
@@ -121,6 +141,25 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
121
141
|
expect(r.definitions.count).to eq 2
|
122
142
|
end
|
123
143
|
|
144
|
+
it "should be able to clean colors from a chart report def" do
|
145
|
+
f = @project.fact_by_title('Lines Changed')
|
146
|
+
m = @project.create_metric("SELECT SUM(#\"#{f.title}\")", title: 'test metric').save
|
147
|
+
r = @project.create_report(top: [m], title: 'xy')
|
148
|
+
rd = r.latest_report_definition
|
149
|
+
rd.content['chart'] = { 'styles' => { 'global' => { 'colorMapping' => 1 } } }
|
150
|
+
expect(GoodData::Helpers.get_path(rd.content, %w(chart styles global))).to eq ({ 'colorMapping' => 1 })
|
151
|
+
rd.reset_color_mapping!
|
152
|
+
expect(GoodData::Helpers.get_path(rd.content, %w(chart styles global))).to eq ({ 'colorMapping' => [] })
|
153
|
+
r.delete
|
154
|
+
res = m.used_by
|
155
|
+
res.each do |dependency|
|
156
|
+
@client.delete dependency['link']
|
157
|
+
end
|
158
|
+
res = m.used_by
|
159
|
+
expect(res.length).to eq 0
|
160
|
+
m.delete
|
161
|
+
end
|
162
|
+
|
124
163
|
it "should be possible to get all metrics" do
|
125
164
|
metrics1 = @project.metrics
|
126
165
|
expect(metrics1.count).to be >= 0
|
@@ -176,10 +215,12 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
176
215
|
expect(fact1).not_to eq fact3
|
177
216
|
|
178
217
|
metric.using(nil)
|
179
|
-
|
218
|
+
res = metric.using('fact')
|
219
|
+
expect(res.count).to eq 1
|
180
220
|
|
181
221
|
fact1.used_by(nil)
|
182
|
-
|
222
|
+
res = fact1.used_by('metric')
|
223
|
+
expect(res.count).to eq 1
|
183
224
|
|
184
225
|
res = metric.using?(fact1)
|
185
226
|
expect(res).to be(true)
|
@@ -362,4 +403,13 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
362
403
|
expect(cloned_project.facts.first.create_metric.execute).to eq nil
|
363
404
|
cloned_project.delete
|
364
405
|
end
|
406
|
+
|
407
|
+
it "should be able to delete report along with its definitions" do
|
408
|
+
m = @project.metrics.first
|
409
|
+
r = @project.create_report(top: [m], title: 'Report to delete')
|
410
|
+
r.save
|
411
|
+
def_uris = r.definition_uris
|
412
|
+
r.delete
|
413
|
+
expect { def_uris.each {|uri| @client.get(uri)} }.to raise_error(RestClient::ResourceNotFound)
|
414
|
+
end
|
365
415
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/core/rest_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
require 'tempfile'
|
2
3
|
|
3
4
|
require 'gooddata/core/rest'
|
4
5
|
|
@@ -18,13 +19,85 @@ describe GoodData do
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
22
|
+
|
23
|
+
def test_webdav_upload(params)
|
24
|
+
GoodData.with_project(@project, :client => @client) do
|
25
|
+
dir = Time.now.to_i.to_s
|
26
|
+
|
27
|
+
path = 'spec/data/test-ci-data.csv'
|
28
|
+
|
29
|
+
if params[:special_chars]
|
30
|
+
source_file = Tempfile.new('abc-16:55:29+ha#he.csv')
|
31
|
+
FileUtils.cp(path, source_file)
|
32
|
+
path = source_file.path
|
33
|
+
end
|
34
|
+
|
35
|
+
path = File.expand_path(path) if params[:absolute_path]
|
36
|
+
|
37
|
+
# upload it there
|
38
|
+
upload_method = GoodData.method(params[:upload_method])
|
39
|
+
upload_method.call(path, directory: dir)
|
40
|
+
|
41
|
+
# download it from there
|
42
|
+
file = Tempfile.new('foo.csv')
|
43
|
+
|
44
|
+
download_method = GoodData.method(params[:download_method])
|
45
|
+
download_method.call(File.basename(path), file, directory: dir)
|
46
|
+
|
47
|
+
expect(file.size).to be > 0
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
21
51
|
describe '#upload_to_project_webdav' do
|
22
|
-
it 'Uploads file' do
|
23
|
-
|
24
|
-
|
52
|
+
it 'Uploads file with relative path to a dir' do
|
53
|
+
test_webdav_upload(
|
54
|
+
upload_method: 'upload_to_project_webdav',
|
55
|
+
download_method: 'download_from_project_webdav'
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'Uploads file with absolute path to a dir' do
|
60
|
+
test_webdav_upload(
|
61
|
+
absolute_path: true,
|
62
|
+
upload_method: 'upload_to_project_webdav',
|
63
|
+
download_method: 'download_from_project_webdav'
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'Uploads file with special chars in filename' do
|
68
|
+
test_webdav_upload(
|
69
|
+
special_chars: true,
|
70
|
+
upload_method: 'upload_to_project_webdav',
|
71
|
+
download_method: 'download_from_project_webdav'
|
72
|
+
)
|
25
73
|
end
|
26
74
|
end
|
27
75
|
|
76
|
+
describe '#upload_to_user_webdav' do
|
77
|
+
it 'Uploads file with relative path to a dir' do
|
78
|
+
test_webdav_upload(
|
79
|
+
upload_method: 'upload_to_user_webdav',
|
80
|
+
download_method: 'download_from_user_webdav'
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'Uploads file with absolute path to a dir' do
|
85
|
+
test_webdav_upload(
|
86
|
+
absolute_path: true,
|
87
|
+
upload_method: 'upload_to_user_webdav',
|
88
|
+
download_method: 'download_from_user_webdav'
|
89
|
+
)
|
90
|
+
end
|
91
|
+
it 'Uploads file with special chars in filename' do
|
92
|
+
test_webdav_upload(
|
93
|
+
special_chars: true,
|
94
|
+
upload_method: 'upload_to_user_webdav',
|
95
|
+
download_method: 'download_from_user_webdav'
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
28
101
|
describe '#get_user_webdav_path' do
|
29
102
|
it 'Gets the path' do
|
30
103
|
@client.get_user_webdav_path('test.csv', :project => @project)
|
data/spec/unit/helpers_spec.rb
CHANGED
@@ -44,4 +44,47 @@ describe GoodData::Helpers do
|
|
44
44
|
result.should == expect
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
describe "#decode_params" do
|
49
|
+
it 'decodes the data params from json' do
|
50
|
+
params = {
|
51
|
+
'param' => 'value',
|
52
|
+
'number_param' => 5,
|
53
|
+
'gd_encoded_params' => '{"deep": {"deeper": "deep value"}}',
|
54
|
+
}
|
55
|
+
expected_result = {
|
56
|
+
'param' => 'value',
|
57
|
+
'number_param' => 5,
|
58
|
+
'deep' => {
|
59
|
+
'deeper' => 'deep value'
|
60
|
+
}
|
61
|
+
}
|
62
|
+
result = GoodData::Helpers.decode_params(params)
|
63
|
+
expect(result).to eq(expected_result)
|
64
|
+
end
|
65
|
+
it 'decodes the hidden_data in hidden params' do
|
66
|
+
params = {
|
67
|
+
'param' => 'value',
|
68
|
+
'number_param' => 5,
|
69
|
+
'gd_encoded_hidden_params' => '{"deep_secret": {"deeper_secret": "hidden value"}}'
|
70
|
+
}
|
71
|
+
expected_result = {
|
72
|
+
'param' => 'value',
|
73
|
+
'number_param' => 5,
|
74
|
+
"deep_secret" => {
|
75
|
+
"deeper_secret" => "hidden value"
|
76
|
+
}
|
77
|
+
}
|
78
|
+
result = GoodData::Helpers.decode_params(params)
|
79
|
+
expect(result).to eq(expected_result)
|
80
|
+
end
|
81
|
+
it 'throws an error when data params is not a valid json' do
|
82
|
+
params = {
|
83
|
+
'param' => 'value',
|
84
|
+
'number_param' => 5,
|
85
|
+
'gd_encoded_params' => 'This is no json.'
|
86
|
+
}
|
87
|
+
expect { GoodData::Helpers.decode_params(params) }.to raise_error(JSON::ParserError)
|
88
|
+
end
|
89
|
+
end
|
47
90
|
end
|
@@ -17,6 +17,7 @@ describe GoodData::Metric do
|
|
17
17
|
'identifier' => 'afo7bx1VakCz',
|
18
18
|
'deprecated' => '0',
|
19
19
|
'summary' => '',
|
20
|
+
'locked' => 0,
|
20
21
|
'title' => 'sum of Lines changed',
|
21
22
|
'category' => 'metric',
|
22
23
|
'updated' => '2014-05-05 20:00:42',
|
@@ -34,6 +35,7 @@ describe GoodData::Metric do
|
|
34
35
|
'identifier' => 'afo7bx1VakCz',
|
35
36
|
'deprecated' => '0',
|
36
37
|
'summary' => '',
|
38
|
+
'locked' => 1,
|
37
39
|
'title' => 'sum of Lines changed',
|
38
40
|
'category' => 'metric',
|
39
41
|
'updated' => '2014-05-05 20:00:42',
|
@@ -55,6 +57,7 @@ describe GoodData::Metric do
|
|
55
57
|
'identifier' => 'afo7bx1VakCz',
|
56
58
|
'deprecated' => '0',
|
57
59
|
'summary' => '',
|
60
|
+
'locked' => 0,
|
58
61
|
'title' => 'sum of Lines changed',
|
59
62
|
'category' => 'metric',
|
60
63
|
'updated' => '2014-05-05 20:00:42',
|
@@ -89,4 +92,34 @@ describe GoodData::Metric do
|
|
89
92
|
@instance.contain?(UNUSED_METRIC).should == true
|
90
93
|
end
|
91
94
|
end
|
95
|
+
|
96
|
+
describe "#locked?" do
|
97
|
+
it "should be able to say if an object is locked" do
|
98
|
+
expect(@instance.locked?).to eq false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#unlocked?" do
|
103
|
+
it "should be able to say if an object is unlocked" do
|
104
|
+
expect(@instance.unlocked?).to eq true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#lock" do
|
109
|
+
it "should be able to lock an object" do
|
110
|
+
expect(@instance.locked?).to eq false
|
111
|
+
@instance.lock
|
112
|
+
expect(@instance.locked?).to eq true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#lock" do
|
117
|
+
it "should be able to unlock an object" do
|
118
|
+
@instance.lock
|
119
|
+
expect(@instance.locked?).to eq true
|
120
|
+
@instance.unlock
|
121
|
+
expect(@instance.locked?).to eq false
|
122
|
+
expect(@instance.unlocked?).to eq true
|
123
|
+
end
|
124
|
+
end
|
92
125
|
end
|