gooddata 0.6.24 → 0.6.25
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 +54 -0
- data/CHANGELOG.md +3 -0
- data/DEPENDENCIES.md +155 -154
- data/README.md +15 -6
- data/Rakefile +5 -3
- data/dependency_decisions.yml +2 -0
- data/gooddata.gemspec +2 -3
- data/lib/gooddata/cli/cli.rb +1 -3
- data/lib/gooddata/cli/commands/auth_cmd.rb +16 -7
- data/lib/gooddata/cli/commands/project_cmd.rb +16 -178
- data/lib/gooddata/cli/shared.rb +46 -44
- data/lib/gooddata/commands/auth.rb +4 -0
- data/lib/gooddata/commands/project.rb +7 -24
- data/lib/gooddata/exceptions/object_migration.rb +4 -0
- data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
- data/lib/gooddata/extensions/object.rb +12 -0
- data/lib/gooddata/goodzilla/goodzilla.rb +56 -9
- data/lib/gooddata/helpers/global_helpers.rb +92 -0
- data/lib/gooddata/mixins/md_finders.rb +2 -8
- data/lib/gooddata/mixins/md_grantees.rb +42 -0
- data/lib/gooddata/mixins/md_id_to_uri.rb +1 -8
- data/lib/gooddata/mixins/md_object_id.rb +1 -1
- data/lib/gooddata/mixins/md_object_indexer.rb +5 -8
- data/lib/gooddata/mixins/md_object_query.rb +2 -2
- data/lib/gooddata/mixins/not_group.rb +17 -0
- data/lib/gooddata/mixins/rest_getters.rb +2 -2
- data/lib/gooddata/mixins/rest_resource.rb +1 -0
- data/lib/gooddata/mixins/to_json.rb +11 -0
- data/lib/gooddata/mixins/uri_getter.rb +9 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +14 -0
- data/lib/gooddata/models/blueprint/project_blueprint.rb +15 -1
- data/lib/gooddata/models/blueprint/to_wire.rb +10 -0
- data/lib/gooddata/models/client.rb +178 -0
- data/lib/gooddata/models/client_synchronization_result.rb +31 -0
- data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
- data/lib/gooddata/models/datawarehouse.rb +1 -5
- data/lib/gooddata/models/domain.rb +85 -1
- data/lib/gooddata/models/execution.rb +0 -2
- data/lib/gooddata/models/execution_detail.rb +0 -2
- data/lib/gooddata/models/from_wire.rb +10 -0
- data/lib/gooddata/models/invitation.rb +1 -1
- data/lib/gooddata/models/links.rb +1 -1
- data/lib/gooddata/models/membership.rb +10 -6
- data/lib/gooddata/models/metadata.rb +98 -11
- data/lib/gooddata/models/metadata/attribute.rb +6 -7
- data/lib/gooddata/models/metadata/dashboard.rb +41 -75
- data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +20 -4
- data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
- data/lib/gooddata/models/metadata/dashboard/filter_item.rb +49 -0
- data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
- data/lib/gooddata/models/metadata/dashboard/report_item.rb +49 -8
- data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
- data/lib/gooddata/models/metadata/dashboard_tab.rb +83 -30
- data/lib/gooddata/models/metadata/dataset.rb +0 -2
- data/lib/gooddata/models/metadata/dimension.rb +1 -3
- data/lib/gooddata/models/metadata/fact.rb +1 -3
- data/lib/gooddata/models/metadata/label.rb +1 -3
- data/lib/gooddata/models/metadata/metric.rb +11 -42
- data/lib/gooddata/models/metadata/report.rb +7 -18
- data/lib/gooddata/models/metadata/report_definition.rb +21 -113
- data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
- data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
- data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
- data/lib/gooddata/models/metadata/variable.rb +8 -2
- data/lib/gooddata/models/model.rb +2 -9
- data/lib/gooddata/models/process.rb +7 -29
- data/lib/gooddata/models/profile.rb +1 -1
- data/lib/gooddata/models/project.rb +131 -167
- data/lib/gooddata/models/project_creator.rb +2 -7
- data/lib/gooddata/models/project_metadata.rb +2 -10
- data/lib/gooddata/models/project_role.rb +4 -10
- data/lib/gooddata/models/report_data_result.rb +3 -5
- data/lib/gooddata/models/schedule.rb +4 -31
- data/lib/gooddata/models/segment.rb +192 -0
- data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +2 -2
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +1 -1
- data/lib/gooddata/models/user_filters/variable_user_filter.rb +11 -0
- data/lib/gooddata/models/user_group.rb +241 -0
- data/lib/gooddata/rest/connection.rb +81 -16
- data/lib/gooddata/rest/object.rb +29 -0
- data/lib/gooddata/rest/object_factory.rb +6 -1
- data/lib/gooddata/rest/resource.rb +7 -1
- data/lib/gooddata/version.rb +1 -1
- data/spec/environment/default.rb +19 -16
- data/spec/environment/develop.rb +10 -10
- data/spec/environment/hotfix.rb +6 -6
- data/spec/environment/production.rb +14 -14
- data/spec/environment/release.rb +6 -6
- data/spec/environment/staging.rb +9 -9
- data/spec/environment/staging_3.rb +14 -15
- data/spec/integration/blueprint_with_grain_spec.rb +72 -0
- data/spec/integration/clients_spec.rb +135 -0
- data/spec/integration/date_dim_switch_spec.rb +142 -0
- data/spec/integration/full_project_spec.rb +3 -3
- data/spec/integration/project_spec.rb +20 -0
- data/spec/integration/segments_spec.rb +141 -0
- data/spec/integration/user_group_spec.rb +127 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/models/domain_spec.rb +7 -1
- data/spec/unit/models/metric_spec.rb +0 -8
- data/spec/unit/models/profile_spec.rb +1 -1
- data/spec/unit/models/report_result_data_spec.rb +6 -0
- metadata +38 -38
- data/lib/gooddata/cli/commands/api_cmd.rb +0 -34
- data/lib/gooddata/cli/commands/console_cmd.rb +0 -40
- data/lib/gooddata/cli/commands/domain_cmd.rb +0 -46
- data/lib/gooddata/cli/commands/process_cmd.rb +0 -145
- data/lib/gooddata/cli/commands/projects_cmd.rb +0 -23
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +0 -77
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +0 -35
- data/lib/gooddata/cli/commands/user_cmd.rb +0 -24
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
require 'gooddata'
|
|
8
|
+
|
|
9
|
+
describe 'Create project using GoodData client', :constraint => 'slow' do
|
|
10
|
+
before(:all) do
|
|
11
|
+
@client = ConnectionHelper.create_default_connection
|
|
12
|
+
@blueprint = GoodData::Model::ProjectBlueprint.build("My project from blueprint") do |p|
|
|
13
|
+
p.add_date_dimension('created_on')
|
|
14
|
+
|
|
15
|
+
p.add_dataset('dataset.users') do |d|
|
|
16
|
+
d.add_anchor('attr.users.id', grain: [{ date: 'created_on' }, { attribute: 'attribute.user' }])
|
|
17
|
+
d.add_date('created_on')
|
|
18
|
+
d.add_attribute('attribute.user')
|
|
19
|
+
d.add_label('label.user.email', reference: 'attribute.user')
|
|
20
|
+
d.add_fact('fact.users.some_number')
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
@blueprint.valid? # => true
|
|
24
|
+
|
|
25
|
+
@project = @client.create_project_from_blueprint(@blueprint, auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
after(:all) do
|
|
29
|
+
@project.delete
|
|
30
|
+
@client.disconnect
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'Should load the data with grain' do
|
|
34
|
+
data = [
|
|
35
|
+
['created_on', 'label.user.email', 'fact.users.some_number'],
|
|
36
|
+
['01/01/2011', 'thomas', '1'],
|
|
37
|
+
['01/01/2011', 'thomas', '2'],
|
|
38
|
+
['01/01/2011', 'jim', '2'],
|
|
39
|
+
['01/01/2011', 'peter', '2'],
|
|
40
|
+
['01/01/2011', 'john', '3']]
|
|
41
|
+
@project.upload(data, @blueprint, 'dataset.users')
|
|
42
|
+
|
|
43
|
+
expect(@project.blueprint.datasets.first.count(@project)).to eq 4
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'Should be able to remove grain and load the same data' do
|
|
47
|
+
updated_blueprint = GoodData::Model::ProjectBlueprint.build("My project from blueprint") do |p|
|
|
48
|
+
p.add_date_dimension('created_on')
|
|
49
|
+
|
|
50
|
+
p.add_dataset('dataset.users') do |d|
|
|
51
|
+
d.add_anchor('attr.users.id')
|
|
52
|
+
d.add_date('created_on')
|
|
53
|
+
d.add_attribute('attribute.user')
|
|
54
|
+
d.add_label('label.user.email', reference: 'attribute.user')
|
|
55
|
+
d.add_fact('fact.users.some_number')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@project.update_from_blueprint(updated_blueprint)
|
|
60
|
+
|
|
61
|
+
data = [
|
|
62
|
+
['created_on', 'label.user.email', 'fact.users.some_number'],
|
|
63
|
+
['01/01/2011', 'thomas', '1'],
|
|
64
|
+
['01/01/2011', 'thomas', '2'],
|
|
65
|
+
['01/01/2011', 'jim', '2'],
|
|
66
|
+
['01/01/2011', 'peter', '2'],
|
|
67
|
+
['01/01/2011', 'john', '3']]
|
|
68
|
+
@project.upload(data, @blueprint, 'dataset.users')
|
|
69
|
+
|
|
70
|
+
expect(@project.blueprint.datasets.first.count(@project)).to eq 5
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
require 'gooddata/models/segment'
|
|
8
|
+
require 'securerandom'
|
|
9
|
+
|
|
10
|
+
describe GoodData::Client do
|
|
11
|
+
TOKEN = 'mustangs'
|
|
12
|
+
|
|
13
|
+
before(:all) do
|
|
14
|
+
@client = GoodData.connect('mustang@gooddata.com', 'jindrisska', server: 'https://mustangs.intgdc.com', verify_ssl: false )
|
|
15
|
+
@domain = @client.domain('mustangs')
|
|
16
|
+
@master_project = @client.create_project(title: 'Test project', auth_token: TOKEN)
|
|
17
|
+
@segment_name = "segment-#{SecureRandom.uuid}"
|
|
18
|
+
@segment = @domain.create_segment(segment_id: @segment_name, master_project: @master_project)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
after(:all) do
|
|
22
|
+
@segment && @segment.delete
|
|
23
|
+
@master_project && @master_project.delete
|
|
24
|
+
@client.disconnect
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#[]' do
|
|
28
|
+
before(:all) do
|
|
29
|
+
client_id = SecureRandom.uuid
|
|
30
|
+
@client_project = @client.create_project(title: "client_#{client_id} project", auth_token: TOKEN)
|
|
31
|
+
@segment_client = @segment.create_client(id: "tenant_#{client_id}", project: @client_project)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'Returns all clients of a segment' do
|
|
35
|
+
clients = @segment.clients
|
|
36
|
+
expect(clients.to_a).to be_an_instance_of(Array)
|
|
37
|
+
expect(clients.to_a.count).to eq 1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'Returns specific tenant when schedule ID passed' do
|
|
41
|
+
client = @segment.clients(@segment_client.uri)
|
|
42
|
+
expect(client).to be_an_instance_of(GoodData::Client)
|
|
43
|
+
expect(client.uri).to eq @segment_client.uri
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
after(:all) do
|
|
47
|
+
@segment_client && @segment_client.delete
|
|
48
|
+
@client_project && @client_project.delete
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe '#delete' do
|
|
54
|
+
before(:all) do
|
|
55
|
+
client_id = SecureRandom.uuid
|
|
56
|
+
@segment_client = @segment.create_client(id: "tenant_#{client_id}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'Deletes particular client' do
|
|
60
|
+
expect(@segment.clients.count).to eq 1
|
|
61
|
+
s = @segment.clients(@segment_client.uri)
|
|
62
|
+
s.delete
|
|
63
|
+
expect(@segment.clients.count).to eq 0
|
|
64
|
+
@segment_client = nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
after(:all) do
|
|
68
|
+
@segment_client && @segment_client.delete
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#delete' do
|
|
73
|
+
before(:all) do
|
|
74
|
+
client_id = SecureRandom.uuid
|
|
75
|
+
@client_project = @client.create_project(title: 'client_1 project', auth_token: TOKEN)
|
|
76
|
+
@segment_client = @segment.create_client(id: "tenant_#{client_id}", project: @client_project)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'Deletes particular client. Project is cleaned up as well' do
|
|
80
|
+
expect(@segment.clients.count).to eq 1
|
|
81
|
+
s = @segment.clients(@segment_client.uri)
|
|
82
|
+
s.delete
|
|
83
|
+
expect(@segment.clients.count).to eq 0
|
|
84
|
+
expect(@client_project.reload!.state).to eq :deleted
|
|
85
|
+
@segment_client = nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
after(:all) do
|
|
89
|
+
@segment_client && segment_client.delete
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe '#save' do
|
|
94
|
+
before(:all) do
|
|
95
|
+
@client_id = SecureRandom.uuid
|
|
96
|
+
@client_project = @client.create_project(title: 'client_1 project', auth_token: TOKEN)
|
|
97
|
+
@segment_client = @segment.create_client(id: "tenant_#{@client_id}", project: @client_project)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'can update project id' do
|
|
101
|
+
begin
|
|
102
|
+
other_client_project = @client.create_project(title: "client_#{@client_id} other project", auth_token: TOKEN)
|
|
103
|
+
@segment_client.project = other_client_project
|
|
104
|
+
@segment_client.save
|
|
105
|
+
expect(@segment.clients('tenant_1').project_uri).to eq other_client_project.uri
|
|
106
|
+
ensure
|
|
107
|
+
other_client_project && other_client_project.delete
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'can update tenants segment id' do
|
|
112
|
+
pending 'Fix the test '
|
|
113
|
+
|
|
114
|
+
second_segment_name = "segment-#{SecureRandom.uuid}"
|
|
115
|
+
second_master_project = @client.create_project(title: 'Test project', auth_token: TOKEN)
|
|
116
|
+
second_segment = @domain.create_segment(segment_id: second_segment_name, master_project: second_master_project)
|
|
117
|
+
@segment_client.segment = second_segment
|
|
118
|
+
@segment_client.save
|
|
119
|
+
expect(second_segment.clients.find { |s| s.uri == @segment_client.uri }).not_to be_nil
|
|
120
|
+
expect(@segment.clients.find { |s| s.uri == @segment_client.uri }).to be_nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'cannot update a client id' do
|
|
124
|
+
@segment_client.client_id = 'different_id'
|
|
125
|
+
expect {
|
|
126
|
+
@segment_client.save
|
|
127
|
+
}.to raise_error RestClient::BadRequest
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
after(:all) do
|
|
131
|
+
@segment_client && @segment_client.delete
|
|
132
|
+
@client_project && @client_project.delete
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
require 'gooddata'
|
|
8
|
+
|
|
9
|
+
describe "Swapping a date dimension and exchanging all attributes/elements", :constraint => 'slow' do
|
|
10
|
+
before(:all) do
|
|
11
|
+
@client = ConnectionHelper::create_default_connection
|
|
12
|
+
@blueprint = GoodData::Model::ProjectBlueprint.build("My project from blueprint") do |p|
|
|
13
|
+
p.add_date_dimension('created_on')
|
|
14
|
+
p.add_date_dimension('created_on_2')
|
|
15
|
+
|
|
16
|
+
p.add_dataset('dataset.users') do |d|
|
|
17
|
+
d.add_anchor('attr.users.id')
|
|
18
|
+
d.add_label('label.users.id', reference: 'attr.users.id')
|
|
19
|
+
d.add_date('created_on')
|
|
20
|
+
d.add_fact('fact.users.some_number')
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Create a project
|
|
25
|
+
@project = @client.create_project_from_blueprint(@blueprint, token: ConnectionHelper::GD_PROJECT_TOKEN, environment: ProjectHelper::ENVIRONMENT)
|
|
26
|
+
|
|
27
|
+
# Load data
|
|
28
|
+
users_data = [
|
|
29
|
+
["label.users.id", "created_on", "fact.users.some_number"],
|
|
30
|
+
[1,"01/01/2014",1],
|
|
31
|
+
[2,"10/15/2014",2],
|
|
32
|
+
[3,"05/02/2014",3]
|
|
33
|
+
]
|
|
34
|
+
@project.upload(users_data, @blueprint, 'dataset.users')
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
after(:all) do
|
|
39
|
+
@project.delete unless @project.nil?
|
|
40
|
+
|
|
41
|
+
@client.disconnect
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should swap the dimension, exhcange all stuff and not break anything" do
|
|
45
|
+
|
|
46
|
+
# WE have 2 date dims
|
|
47
|
+
expect(@blueprint.date_dimensions.map(&:id)).to eq ["created_on", "created_on_2"]
|
|
48
|
+
# One is connected
|
|
49
|
+
expect(@blueprint.datasets.flat_map(&:references).map(&:reference).include?('created_on')).to be_truthy
|
|
50
|
+
# The other is disconnected
|
|
51
|
+
expect(@blueprint.datasets.flat_map(&:references).map(&:reference).include?('created_on_2')).to be_falsey
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Create a metric
|
|
55
|
+
@metric_1 = @project.attributes('created_on.date').create_metric(title: 'Count of days in DD')
|
|
56
|
+
@metric_1.save
|
|
57
|
+
|
|
58
|
+
# Create a report
|
|
59
|
+
@report = @project.create_report(left: @metric_1, top: ['created_on.date'], title: 'Beautiful report')
|
|
60
|
+
@report.save
|
|
61
|
+
|
|
62
|
+
def suggest_mapping(label_a, label_b, project)
|
|
63
|
+
as = project.attributes
|
|
64
|
+
a1 = as.select {|a| a.identifier.include?("#{label_a}.")}.pmapcat { |a| [a] + a.labels }
|
|
65
|
+
a2 = as.select {|a| a.identifier.include?("#{label_b}.")}.pmapcat { |a| [a] + a.labels }
|
|
66
|
+
a1.reduce({}) do |a, e|
|
|
67
|
+
match = a2.find { |l| l.identifier.gsub(/^#{label_b}/, '') == e.identifier.gsub(/^#{label_a}/, '') }
|
|
68
|
+
a[e.identifier] = match && match.identifier
|
|
69
|
+
a
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Create definition with report specific metric
|
|
74
|
+
@metric_2 = @project.attributes('created_on.date').create_metric(title: 'Count of days in DD Secret')
|
|
75
|
+
@metric_2.deprecated = true
|
|
76
|
+
@metric_2.save
|
|
77
|
+
@report_with_private = @project.create_report({
|
|
78
|
+
left: @metric_2,
|
|
79
|
+
top: ['created_on.day.in.week'],
|
|
80
|
+
title: 'Beautiful report with private'
|
|
81
|
+
})
|
|
82
|
+
@report_with_private.save
|
|
83
|
+
|
|
84
|
+
# Create a definition with a filter value
|
|
85
|
+
@report = @project.create_report({
|
|
86
|
+
left: @metric_2,
|
|
87
|
+
top: ['created_on.quarter'],
|
|
88
|
+
filters: [['created_on.year', 2015, 2016]],
|
|
89
|
+
title: 'Beautiful report with filters'
|
|
90
|
+
})
|
|
91
|
+
@report.save
|
|
92
|
+
|
|
93
|
+
@label = @project.labels('created_on.year').primary_label
|
|
94
|
+
@variable = @project.create_variable(title: 'uaaa', attribute: @label.attribute).save
|
|
95
|
+
filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, '2015', '2016']]
|
|
96
|
+
@project.add_variable_permissions(filters, @variable)
|
|
97
|
+
|
|
98
|
+
as = @project.attributes.select {|a| a.identifier.include?('created_on_2.')}
|
|
99
|
+
expect(as.pmapcat {|a| a.usedby('report')}).to be_empty
|
|
100
|
+
expect(as.pmapcat {|a| a.usedby('metric')}).to be_empty
|
|
101
|
+
expect(as.pmapcat {|a| a.usedby('dashboard')}).to be_empty
|
|
102
|
+
|
|
103
|
+
# replace values
|
|
104
|
+
mapping = GoodData::Helpers.prepare_mapping(suggest_mapping('created_on', 'created_on_2', @project), project: @project)
|
|
105
|
+
@project.replace_from_mapping(mapping)
|
|
106
|
+
|
|
107
|
+
# Check if any of the attributes is used by any of the objects. All should be empty
|
|
108
|
+
as = @project.attributes.select {|a| a.identifier.include?('created_on.')}
|
|
109
|
+
expect(as.pmapcat {|a| a.usedby('report')}).to be_empty
|
|
110
|
+
expect(as.pmapcat {|a| a.usedby('metric')}).to be_empty
|
|
111
|
+
expect(as.pmapcat {|a| a.usedby('dashboard')}).to be_empty
|
|
112
|
+
|
|
113
|
+
# Reload stuff
|
|
114
|
+
@metric_2.reload!
|
|
115
|
+
@report.reload!
|
|
116
|
+
@report_with_private.reload!
|
|
117
|
+
|
|
118
|
+
# Stuff should be still computable
|
|
119
|
+
@metric_2.execute
|
|
120
|
+
@report.execute
|
|
121
|
+
@report_with_private.execute
|
|
122
|
+
|
|
123
|
+
# Labels
|
|
124
|
+
GoodData::SmallGoodZilla.get_uris(@metric_2.expression)
|
|
125
|
+
expect(@report.definition.attributes.map(&:identifier)).to eq ["created_on_2.quarter"]
|
|
126
|
+
ids = GoodData::SmallGoodZilla.get_uris(@report.definition.filters.first).map { |x| x.split('/')[-2..-1].join('/') }
|
|
127
|
+
expect(ids).to eq ["obj/2286", "2286/elements?id=2015", "2286/elements?id=2016"]
|
|
128
|
+
|
|
129
|
+
ids = GoodData::SmallGoodZilla.get_uris(@report.definition.filters.first).map { |x| x.split('/')[-2..-1].join('/') }
|
|
130
|
+
expect(ids).to eq ["obj/2286", "2286/elements?id=2015", "2286/elements?id=2016"]
|
|
131
|
+
|
|
132
|
+
ids = GoodData::SmallGoodZilla.get_uris(@variable.values.first.expression).map {|v| v.split('/')[-2..-1].join('/')}
|
|
133
|
+
expect(ids).to eq ["obj/2286", "2286/elements?id=2015", "2286/elements?id=2016"]
|
|
134
|
+
|
|
135
|
+
# Swap the dims
|
|
136
|
+
bp = @project.blueprint
|
|
137
|
+
bp.swap_date_dimension!('created_on', 'created_on_2')
|
|
138
|
+
@project.update_from_blueprint(bp)
|
|
139
|
+
expect(bp.datasets.flat_map(&:references).map(&:reference).include?('created_on')).to be_falsey
|
|
140
|
+
expect(bp.datasets.flat_map(&:references).map(&:reference).include?('created_on_2')).to be_truthy
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -226,6 +226,7 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
|
226
226
|
expect(r.locked?).to eq true
|
|
227
227
|
r.unlock!
|
|
228
228
|
expect(r.locked?).to eq false
|
|
229
|
+
r.delete
|
|
229
230
|
end
|
|
230
231
|
|
|
231
232
|
it "should be able to purge report from older revisions" do
|
|
@@ -365,7 +366,7 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
|
365
366
|
fact = @project.fact_by_title('Lines Changed')
|
|
366
367
|
expect(fact.tags.empty?).to be_truthy
|
|
367
368
|
|
|
368
|
-
fact.tags = "tag1
|
|
369
|
+
fact.tags = "tag1 tag2 tag3"
|
|
369
370
|
fact.save
|
|
370
371
|
|
|
371
372
|
tagged_facts = GoodData::Fact.find_by_tag('tag3', :client => @client, :project => @project)
|
|
@@ -413,8 +414,7 @@ describe "Full project implementation", :constraint => 'slow' do
|
|
|
413
414
|
|
|
414
415
|
expect(metric.contain?(attribute)).to be true
|
|
415
416
|
expect(metric.contain?(repo_attribute)).to be false
|
|
416
|
-
|
|
417
|
-
metric.replace(attribute, repo_attribute)
|
|
417
|
+
metric.replace!(attribute => repo_attribute)
|
|
418
418
|
metric.save
|
|
419
419
|
expect(metric.execute).not_to eq 4
|
|
420
420
|
|
|
@@ -207,6 +207,26 @@ describe GoodData::Project, :constraint => 'slow' do
|
|
|
207
207
|
expect(logins.map {|l| users.find {|u| u.login == l}}.pmap {|u| u.role.title}).to eq roles.flatten
|
|
208
208
|
|
|
209
209
|
end
|
|
210
|
+
|
|
211
|
+
it 'can work with groups as well. Groups have to be set up. It can only eat hashes on input in this case' do
|
|
212
|
+
users = (1..5).to_a.map { |x| ProjectHelper.create_random_user(@client).to_hash }
|
|
213
|
+
group_names = ['group_1', 'group_2']
|
|
214
|
+
groups = group_names.map { |g| @project.create_group(name: g) }
|
|
215
|
+
users_with_groups = users.map { |u| u[:user_group] = groups.take(rand(2) + 1).map(&:name); u}
|
|
216
|
+
@domain.create_users(users_with_groups, domain: @domain)
|
|
217
|
+
@project.import_users(users_with_groups, domain: @domain, whitelists: [/gem_tester@gooddata.com/])
|
|
218
|
+
expect(users_with_groups.flat_map { |u| u[:user_group].map { |g| [u[:login], g] } }.all? do |u, g|
|
|
219
|
+
@project.user_groups(g).member?(@project.member(u).uri) rescue false
|
|
220
|
+
end).to be_truthy
|
|
221
|
+
|
|
222
|
+
users_with_group = users.map { |u| u[:user_group] = ['group_1']; u}
|
|
223
|
+
to_whitelist = @project.user_groups('group_2').members.to_a.sample
|
|
224
|
+
@project.import_users(users_with_group, domain: @domain, whitelists: [to_whitelist.login, /gem_tester@gooddata.com/])
|
|
225
|
+
expect(@project.user_groups('group_2').members.map(&:login)).to eq [to_whitelist.login]
|
|
226
|
+
expect(users_with_group.flat_map { |u| u[:user_group].map { |g| [u[:login], g] } }.all? do |u, g|
|
|
227
|
+
@project.user_groups(g).member?(@project.member(u).uri) rescue false
|
|
228
|
+
end).to be_truthy
|
|
229
|
+
end
|
|
210
230
|
end
|
|
211
231
|
|
|
212
232
|
describe '#summary' do
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
require 'gooddata/models/segment'
|
|
8
|
+
require 'securerandom'
|
|
9
|
+
|
|
10
|
+
describe GoodData::Segment do
|
|
11
|
+
TOKEN = 'mustangs'
|
|
12
|
+
|
|
13
|
+
before(:all) do
|
|
14
|
+
@client = GoodData.connect('mustang@gooddata.com', 'jindrisska', server: 'https://mustangs.intgdc.com', verify_ssl: false )
|
|
15
|
+
@domain = @client.domain('mustangs')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before(:each) do
|
|
19
|
+
@uuid = SecureRandom.uuid
|
|
20
|
+
@master_project = @client.create_project(title: "Test MASTER project for #{@uuid}", auth_token: TOKEN)
|
|
21
|
+
@segment_name = "segment-#{@uuid}"
|
|
22
|
+
@segment = @domain.create_segment(segment_id: @segment_name, master_project: @master_project)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
after(:each) do
|
|
26
|
+
@segment && @segment.delete(force: true)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
after(:all) do
|
|
30
|
+
@master_project.delete if @master_project
|
|
31
|
+
@client.disconnect
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#[]' do
|
|
35
|
+
it 'Returns all segments when :all passed' do
|
|
36
|
+
res = @domain.segments
|
|
37
|
+
expect(res).to be_an_instance_of(Array)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'Returns specific segment when segment ID passed' do
|
|
41
|
+
s = @domain.segments(@segment_name)
|
|
42
|
+
@segment.uri == s.uri
|
|
43
|
+
expect(s).to be_an_instance_of(GoodData::Segment)
|
|
44
|
+
expect(@segment).to be_an_instance_of(GoodData::Segment)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '#delete' do
|
|
49
|
+
it 'Deletes particular segment' do
|
|
50
|
+
old_count = @domain.segments.count
|
|
51
|
+
s = @domain.segments(@segment_name)
|
|
52
|
+
s.delete
|
|
53
|
+
expect(@domain.segments.length).to eq (old_count - 1)
|
|
54
|
+
# prevent delete attempt in the after hook
|
|
55
|
+
@segment = nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#save' do
|
|
60
|
+
it 'can update a segment master project' do
|
|
61
|
+
different_master = @client.create_project(title: 'Test project', auth_token: TOKEN)
|
|
62
|
+
@segment.master_project = different_master
|
|
63
|
+
@segment.save
|
|
64
|
+
@segment = @domain.segments(@segment_name)
|
|
65
|
+
expect(@segment.master_project_uri).not_to eq @master_project.uri
|
|
66
|
+
expect(@segment.master_project_uri).to eq different_master.uri
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'cannot update a segment id' do
|
|
70
|
+
@segment.segment_id = 'different_id'
|
|
71
|
+
expect {
|
|
72
|
+
@segment.save
|
|
73
|
+
}.to raise_error RestClient::BadRequest
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#create_client' do
|
|
78
|
+
it 'can create a new client in a segment' do
|
|
79
|
+
begin
|
|
80
|
+
client_project = @client.create_project(title: 'client_1 project', auth_token: TOKEN)
|
|
81
|
+
segment_client = @segment.create_client(id: 'tenant_1', project: client_project)
|
|
82
|
+
expect(segment_client).to be_an_instance_of(GoodData::Client)
|
|
83
|
+
expect(@segment.clients.count).to eq 1
|
|
84
|
+
ensure
|
|
85
|
+
segment_client && segment_client.delete
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe '#provision_client_projects' do
|
|
91
|
+
it 'can create a new client in a segment without project and then provision' do
|
|
92
|
+
begin
|
|
93
|
+
segment_client = @segment.create_client(id: 'tenant_1')
|
|
94
|
+
expect(segment_client).to be_an_instance_of(GoodData::Client)
|
|
95
|
+
expect(@segment.clients.count).to eq 1
|
|
96
|
+
@domain.synchronize_clients
|
|
97
|
+
@domain.provision_client_projects
|
|
98
|
+
expect(@domain.segments.flat_map { |s| s.clients.to_a }.all?(&:project?)).to be_truthy
|
|
99
|
+
ensure
|
|
100
|
+
segment_client && segment_client.delete
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe '#update_clients' do
|
|
106
|
+
it 'can create a new client in a segment without project and then provision' do
|
|
107
|
+
begin
|
|
108
|
+
uuid_2 = SecureRandom.uuid
|
|
109
|
+
master_project_2 = @client.create_project(title: "Test MASTER project for #{uuid_2}", auth_token: TOKEN)
|
|
110
|
+
segment_name_2 = "segment-#{uuid_2}"
|
|
111
|
+
segment_2 = @domain.create_segment(segment_id: segment_name_2, master_project: master_project_2)
|
|
112
|
+
|
|
113
|
+
client_1 = "client-#{SecureRandom.uuid}"
|
|
114
|
+
client_2 = "client-#{SecureRandom.uuid}"
|
|
115
|
+
data = [{id: client_1, segment: segment_name_2 },
|
|
116
|
+
{id: client_2, segment: @segment_name }]
|
|
117
|
+
res = @domain.update_clients(data)
|
|
118
|
+
expect(@domain.segments.map(&:id)).to include(@segment.id, segment_2.id)
|
|
119
|
+
expect(@domain.segments.pmapcat {|s| s.clients.to_a }.map(&:id)).to include(client_1, client_2)
|
|
120
|
+
|
|
121
|
+
client_3 = "client-#{SecureRandom.uuid}"
|
|
122
|
+
client_4 = "client-#{SecureRandom.uuid}"
|
|
123
|
+
data = [{id: client_3, segment: segment_name_2 },
|
|
124
|
+
{id: client_4, segment: @segment_name }]
|
|
125
|
+
res = @domain.update_clients(data)
|
|
126
|
+
expect(@domain.segments.pmapcat {|s| s.clients.to_a }.map(&:id)).to include(client_1, client_2, client_3, client_4)
|
|
127
|
+
|
|
128
|
+
# bring the projects
|
|
129
|
+
@domain.synchronize_clients
|
|
130
|
+
@domain.provision_client_projects
|
|
131
|
+
projects_to_delete = @domain.segments.pmapcat {|s| s.clients.to_a }.select { |c| [client_1, client_2].include?(c.id) }.map(&:project)
|
|
132
|
+
res = @domain.update_clients(data, delete_extra: true)
|
|
133
|
+
expect(@domain.segments.pmapcat {|s| s.clients.to_a }.map(&:id)).to include(client_3, client_4)
|
|
134
|
+
expect(@domain.segments.pmapcat {|s| s.clients.to_a }.map(&:id)).not_to include(client_1, client_2)
|
|
135
|
+
expect(projects_to_delete.pmap(&:reload!).map(&:state)).to eq [:deleted, :deleted]
|
|
136
|
+
ensure
|
|
137
|
+
segment_2.delete(force: true) if segment_2
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|