gooddata 0.6.3 → 0.6.4

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.markdown +6 -0
  4. data/README.md +1 -0
  5. data/gooddata.gemspec +2 -1
  6. data/lib/gooddata.rb +4 -1
  7. data/lib/gooddata/bricks/base_downloader.rb +33 -19
  8. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +49 -25
  9. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -33
  10. data/lib/gooddata/cli/commands/project_cmd.rb +6 -4
  11. data/lib/gooddata/client.rb +1 -1
  12. data/lib/gooddata/commands/api.rb +1 -1
  13. data/lib/gooddata/commands/auth.rb +1 -1
  14. data/lib/gooddata/connection.rb +13 -10
  15. data/lib/gooddata/core/connection.rb +1 -1
  16. data/lib/gooddata/core/user.rb +11 -3
  17. data/lib/gooddata/exceptions/validation_error.rb +12 -0
  18. data/lib/gooddata/extensions/extensions.rb +6 -0
  19. data/lib/gooddata/goodzilla/goodzilla.rb +2 -2
  20. data/lib/gooddata/helpers/csv_helper.rb +57 -0
  21. data/lib/gooddata/{helpers.rb → helpers/global_helpers.rb} +0 -0
  22. data/lib/gooddata/helpers/helpers.rb +6 -0
  23. data/lib/gooddata/models/domain.rb +134 -24
  24. data/lib/gooddata/models/membership.rb +402 -0
  25. data/lib/gooddata/models/metadata.rb +64 -7
  26. data/lib/gooddata/models/metadata/attribute.rb +27 -12
  27. data/lib/gooddata/models/metadata/column.rb +1 -1
  28. data/lib/gooddata/models/metadata/dashboard.rb +7 -6
  29. data/lib/gooddata/models/metadata/display_form.rb +17 -2
  30. data/lib/gooddata/models/metadata/fact.rb +13 -7
  31. data/lib/gooddata/models/metadata/metric.rb +9 -9
  32. data/lib/gooddata/models/metadata/report.rb +7 -8
  33. data/lib/gooddata/models/metadata/report_definition.rb +10 -11
  34. data/lib/gooddata/models/metadata/schema.rb +1 -1
  35. data/lib/gooddata/models/model.rb +1 -1
  36. data/lib/gooddata/models/process.rb +44 -25
  37. data/lib/gooddata/models/profile.rb +365 -13
  38. data/lib/gooddata/models/project.rb +245 -35
  39. data/lib/gooddata/models/project_blueprint.rb +42 -18
  40. data/lib/gooddata/models/project_creator.rb +4 -1
  41. data/lib/gooddata/models/project_role.rb +7 -7
  42. data/lib/gooddata/models/schedule.rb +17 -1
  43. data/lib/gooddata/models/schema_blueprint.rb +19 -2
  44. data/lib/gooddata/version.rb +1 -1
  45. data/out.txt +0 -0
  46. data/spec/data/users.csv +12 -0
  47. data/spec/helpers/connection_helper.rb +1 -0
  48. data/spec/helpers/csv_helper.rb +12 -0
  49. data/spec/helpers/project_helper.rb +1 -1
  50. data/spec/integration/full_project_spec.rb +136 -3
  51. data/spec/spec_helper.rb +9 -0
  52. data/spec/unit/commands/command_user_spec.rb +1 -1
  53. data/spec/unit/extensions/hash_spec.rb +19 -0
  54. data/spec/unit/godzilla/goodzilla_spec.rb +15 -0
  55. data/spec/unit/helpers/csv_helper_spec.rb +18 -0
  56. data/spec/unit/models/domain_spec.rb +47 -4
  57. data/spec/unit/models/md_object_spec.rb +8 -0
  58. data/spec/unit/models/membership_spec.rb +128 -0
  59. data/spec/unit/models/metadata_spec.rb +38 -0
  60. data/spec/unit/models/profile_spec.rb +212 -0
  61. data/spec/unit/models/project_blueprint_spec.rb +35 -8
  62. data/spec/unit/models/project_role_spec.rb +6 -6
  63. data/spec/unit/models/project_spec.rb +226 -13
  64. data/spec/unit/models/schedule_spec.rb +58 -0
  65. data/tmp/.gitkeepme +0 -0
  66. metadata +36 -11
  67. data/lib/gooddata/models/account_settings.rb +0 -124
  68. data/lib/gooddata/models/user.rb +0 -165
  69. data/spec/unit/models/account_settings_spec.rb +0 -28
  70. data/spec/unit/models/user_spec.rb +0 -16
@@ -18,12 +18,21 @@ RSpec.configure do |config|
18
18
  config.include BlueprintHelper
19
19
  config.include CliHelper
20
20
  config.include ConnectionHelper
21
+ config.include CsvHelper
21
22
  config.include ProjectHelper
22
23
  config.include SchemaHelper
23
24
 
24
25
  config.filter_run_excluding :broken => true
25
26
 
26
27
  config.before(:all) do
28
+ # TODO: Move this to some method.
29
+ # TODO Make more intelligent so two test suites can run at the same time.
30
+ # ConnectionHelper.create_default_connection
31
+ # users = GoodData::Domain.users_map(ConnectionHelper::DEFAULT_DOMAIN)
32
+ # users.each do |user|
33
+ # user.delete if user.email != ConnectionHelper::DEFAULT_USERNAME
34
+ # end
35
+
27
36
  # TODO: Fully setup global environment
28
37
  GoodData.logging_off
29
38
  end
@@ -9,7 +9,7 @@ describe GoodData::Command::User do
9
9
  GoodData.disconnect
10
10
  end
11
11
 
12
- it "Is Possible to create GoodData::Command::User instance" do
12
+ it "Is Possible to create GoodData::Command::Membership instance" do
13
13
  cmd = GoodData::Command::User.new()
14
14
  cmd.should be_a(GoodData::Command::User)
15
15
  end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ describe Hash do
4
+
5
+ describe '#deep_dup' do
6
+ it 'should crete a deep copy' do
7
+ x = {
8
+ :a => {
9
+ :b => :c
10
+ }
11
+ }
12
+ y = x.dup
13
+ deep_y = x.deep_dup
14
+
15
+ y[:a].object_id.should === x[:a].object_id
16
+ deep_y[:a].object_id.should_not === x[:a].object_id
17
+ end
18
+ end
19
+ end
@@ -56,4 +56,19 @@ describe GoodData::SmallGoodZilla do
56
56
  interpolated.should == "SELECT SUM([a]) WHERE [d]=[x] AND [snap]=1"
57
57
  end
58
58
 
59
+ it "should be able to parse several ids correctly." do
60
+ metric = "SELECT SUM(
61
+ CASE
62
+ WHEN ![attr.customer_profiles.profile_id] = [/gdc/md/pxa3aic06undadkc5s7t5lxpne11vgyt/obj/257/elements?id=65] THEN ![fact.perfomance_by_campaign_id.general_score_1]
63
+ WHEN ![attr.customer_profiles.profile_id] = [/gdc/md/pxa3aic06undadkc5s7t5lxpne11vgyt/obj/257/elements?id=50] THEN ![fact.perfomance_by_campaign_id.general_score_5]
64
+ WHEN ![attr.customer_profiles.profile_id] = [/gdc/md/pxa3aic06undadkc5s7t5lxpne11vgyt/obj/257/elements?id=20] THEN ![fact.perfomance_by_campaign_id.general_score_12]
65
+ END)"
66
+ GoodData::SmallGoodZilla.get_ids(metric).should == [
67
+ "attr.customer_profiles.profile_id",
68
+ "fact.perfomance_by_campaign_id.general_score_1",
69
+ "fact.perfomance_by_campaign_id.general_score_5",
70
+ "fact.perfomance_by_campaign_id.general_score_12"
71
+ ]
72
+ end
73
+
59
74
  end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'gooddata/helpers/csv_helper'
4
+
5
+ describe GoodData::Helpers::Csv do
6
+ describe '#read' do
7
+ it 'Reads data from CSV file' do
8
+ data = GoodData::Helpers::Csv.read(:path => CsvHelper::CSV_PATH_IMPORT)
9
+ end
10
+ end
11
+
12
+ describe '#write' do
13
+ it 'Writes data to CSV' do
14
+ data = []
15
+ GoodData::Helpers::Csv.write(:path => CsvHelper::CSV_PATH_EXPORT, :data => data)
16
+ end
17
+ end
18
+ end
@@ -13,7 +13,9 @@ describe GoodData::Domain do
13
13
 
14
14
  describe '#add_user' do
15
15
  it 'Should add user' do
16
- GoodData::Domain.add_user(ConnectionHelper::DEFAULT_DOMAIN, "gemtest#{rand(1e6)}@gooddata.com", 'password')
16
+ user = GoodData::Domain.add_user(:domain => ConnectionHelper::DEFAULT_DOMAIN, :login => "gemtest#{rand(1e6)}@gooddata.com", :password => 'password')
17
+ expect(user).to be_an_instance_of(GoodData::Profile)
18
+ user.delete
17
19
  end
18
20
  end
19
21
 
@@ -22,7 +24,7 @@ describe GoodData::Domain do
22
24
  users = GoodData::Domain.users(ConnectionHelper::DEFAULT_DOMAIN)
23
25
  expect(users).to be_instance_of(Array)
24
26
  users.each do |user|
25
- expect(user).to be_an_instance_of(GoodData::AccountSettings)
27
+ expect(user).to be_an_instance_of(GoodData::Profile)
26
28
  end
27
29
  end
28
30
 
@@ -30,7 +32,7 @@ describe GoodData::Domain do
30
32
  users = GoodData::Domain.users(ConnectionHelper::DEFAULT_DOMAIN, {:limit =>1})
31
33
  expect(users).to be_instance_of(Array)
32
34
  users.each do |user|
33
- expect(user).to be_an_instance_of(GoodData::AccountSettings)
35
+ expect(user).to be_an_instance_of(GoodData::Profile)
34
36
  end
35
37
  end
36
38
 
@@ -38,7 +40,48 @@ describe GoodData::Domain do
38
40
  users = GoodData::Domain.users(ConnectionHelper::DEFAULT_DOMAIN, {:offset => 1})
39
41
  expect(users).to be_instance_of(Array)
40
42
  users.each do |user|
41
- expect(user).to be_an_instance_of(GoodData::AccountSettings)
43
+ expect(user).to be_an_instance_of(GoodData::Profile)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#users_create' do
49
+ it 'Creates new users from list' do
50
+ list = []
51
+ (0...10).each do |i|
52
+ num = rand(1e6)
53
+ login = "gemtest#{num}@gooddata.com"
54
+
55
+ json = {
56
+ 'user' => {
57
+ 'content' => {
58
+ 'email' => login,
59
+ 'login' => login,
60
+ 'firstname' => 'the',
61
+ 'lastname' => num.to_s,
62
+
63
+ # Following lines are ugly hack
64
+ 'role' => 'admin',
65
+ 'password' => 'password',
66
+ 'domain' => ConnectionHelper::DEFAULT_DOMAIN,
67
+
68
+ # And following lines are even much more ugly hack
69
+ # 'sso_provider' => '',
70
+ # 'authentication_modes' => ['sso', 'password']
71
+ },
72
+ 'meta' => {}
73
+ }
74
+ }
75
+ user = GoodData::Membership.new(json)
76
+ list << user
77
+ end
78
+
79
+ res = GoodData::Domain.users_create(list, ConnectionHelper::DEFAULT_DOMAIN)
80
+
81
+ expect(res).to be_an_instance_of(Array)
82
+ res.each do |r|
83
+ expect(r).to be_an_instance_of(GoodData::Profile)
84
+ r.delete
42
85
  end
43
86
  end
44
87
  end
@@ -44,4 +44,12 @@ describe GoodData::Model::MdObject do
44
44
  result.should == be_an_instance_of(String)
45
45
  end
46
46
  end
47
+
48
+ describe '#all' do
49
+ it 'Throws an error. This is implemented on subclasses' do
50
+ expect do
51
+ GoodData::MdObject.all
52
+ end.to raise_exception(NotImplementedError)
53
+ end
54
+ end
47
55
  end
@@ -0,0 +1,128 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'gooddata/models/domain'
4
+ require 'gooddata/models/membership'
5
+ require 'gooddata/models/project_role'
6
+
7
+ describe GoodData::Membership do
8
+ before(:all) do
9
+ ConnectionHelper.create_default_connection
10
+
11
+ @users = [
12
+ GoodData::Membership.new(
13
+ {
14
+ 'user' => {
15
+ 'content' => {
16
+ 'email' => 'petr.cvengros@gooddata.com',
17
+ 'firstname' => 'Petr',
18
+ 'lastname' => 'Cvengros'
19
+ },
20
+ 'meta' => {}
21
+ }
22
+ }
23
+ ),
24
+
25
+ GoodData::Membership.new(
26
+ {
27
+ 'user' => {
28
+ 'content' => {
29
+ 'email' => 'tomas.korcak@gooddata.com',
30
+ 'firstname' => 'Tomas',
31
+ 'lastname' => 'Korcak'
32
+ },
33
+ 'meta' => {}
34
+ }
35
+ }
36
+ ),
37
+
38
+ GoodData::Membership.new(
39
+ {
40
+ 'user' => {
41
+ 'content' => {
42
+ 'email' => 'patrick.mcconlogue@gooddata.com',
43
+ 'firstname' => 'Patrick',
44
+ 'lastname' => 'McConlogue'
45
+ },
46
+ 'meta' => {}
47
+ }
48
+ }
49
+ ),
50
+
51
+ GoodData::Membership.new(
52
+ {
53
+ 'user' => {
54
+ 'content' => {
55
+ 'email' => 'tomas.svarovsky@gooddata.com',
56
+ 'firstname' => 'Tomas',
57
+ 'lastname' => 'Svarovsky'
58
+ },
59
+ 'meta' => {}
60
+ }
61
+ }
62
+ ),
63
+ ]
64
+ end
65
+
66
+ after(:all) do
67
+ GoodData.disconnect
68
+ end
69
+
70
+ describe '#diff_list' do
71
+ it 'Returns empty diff for same arrays' do
72
+ l1 = [
73
+ @users[0]
74
+ ]
75
+
76
+ l2 = [
77
+ @users[0]
78
+ ]
79
+
80
+ diff = GoodData::Membership.diff_list(l1, l2)
81
+ diff[:added].length.should eql(0)
82
+ diff[:changed].length.should eql(0)
83
+ diff[:removed].length.should eql(0)
84
+ end
85
+
86
+ it 'Recognizes added element' do
87
+ l1 = []
88
+
89
+ l2 = [
90
+ @users[0]
91
+ ]
92
+
93
+ diff = GoodData::Membership.diff_list(l1, l2)
94
+ diff[:added].length.should eql(1)
95
+ diff[:changed].length.should eql(0)
96
+ diff[:removed].length.should eql(0)
97
+ end
98
+
99
+ it 'Recognizes changed element' do
100
+ l1 = [
101
+ @users[0]
102
+ ]
103
+
104
+ l2 = [
105
+ GoodData::Membership.new(@users[0].json.deep_dup)
106
+ ]
107
+ l2[0].first_name = 'Peter'
108
+
109
+ diff = GoodData::Membership.diff_list(l1, l2)
110
+ diff[:added].length.should eql(0)
111
+ diff[:changed].length.should eql(1)
112
+ diff[:removed].length.should eql(0)
113
+ end
114
+
115
+ it 'Recognizes removed element' do
116
+ l1 = [
117
+ @users[0]
118
+ ]
119
+
120
+ l2 = []
121
+
122
+ diff = GoodData::Membership.diff_list(l1, l2)
123
+ diff[:added].length.should eql(0)
124
+ diff[:changed].length.should eql(0)
125
+ diff[:removed].length.should eql(1)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'gooddata'
4
+
5
+ RAW_DATA = {'metric'=>
6
+ {'content'=>
7
+ {'format'=>'#,##0',
8
+ 'expression'=> 'SELECT SUM([/gdc/md/ksjy0nr3goz6k8yrpklz97l0mych7nez/obj/700])'},
9
+ 'meta' =>
10
+ {'author'=>'/gdc/account/profile/4e1e8cacc4989228e0ae531b30853248',
11
+ 'uri'=>'/gdc/md/ksjy0nr3goz6k8yrpklz97l0mych7nez/obj/70',
12
+ 'tags'=>'a b cg r t',
13
+ 'created'=>'2014-04-30 22:47:57',
14
+ 'identifier'=>'afo7bx1VakCz',
15
+ 'deprecated'=>'0',
16
+ 'summary'=>'',
17
+ 'title'=>'sum of Lines changed',
18
+ 'category'=>'metric',
19
+ 'updated'=>'2014-05-05 20:00:42',
20
+ 'contributor'=>'/gdc/account/profile/4e1e8cacc4989228e0ae531b30853248'}}}
21
+
22
+
23
+ describe GoodData::MdObject do
24
+ before(:each) do
25
+ @instance = GoodData::MdObject.new(RAW_DATA)
26
+ end
27
+
28
+ describe '#identifier=' do
29
+ it 'Allows setting a new identifier' do
30
+ identifier = @instance.identifier
31
+ @instance.identifier = 'new_id'
32
+ new_identifier = @instance.identifier
33
+
34
+ new_identifier.should_not == identifier
35
+ new_identifier.should == 'new_id'
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,212 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ require 'gooddata/models/profile'
5
+ require 'gooddata/models/domain'
6
+ require 'gooddata/models/project'
7
+
8
+ describe GoodData::Profile do
9
+ before(:all) do
10
+ ConnectionHelper.create_default_connection
11
+ @user = GoodData::Domain.find_user_by_login(ConnectionHelper::DEFAULT_DOMAIN, ConnectionHelper::DEFAULT_USERNAME)
12
+
13
+ @users = [
14
+ GoodData::Profile.new(
15
+ {
16
+ 'accountSetting' => {
17
+ 'email' => 'petr.cvengros@gooddata.com',
18
+ 'firstName' => 'Petr',
19
+ 'lastName' => 'Cvengros'
20
+ }
21
+ }
22
+ ),
23
+
24
+ GoodData::Profile.new(
25
+ {
26
+ 'accountSetting' => {
27
+ 'email' => 'tomas.korcak@gooddata.com',
28
+ 'firstName' => 'Tomas',
29
+ 'lastName' => 'Korcak'
30
+ }
31
+ }
32
+ ),
33
+
34
+ GoodData::Profile.new(
35
+ {
36
+ 'accountSetting' => {
37
+ 'email' => 'patrick.mcconlogue@gooddata.com',
38
+ 'firstName' => 'Patrick',
39
+ 'lastName' => 'McConlogue'
40
+
41
+ }
42
+ }
43
+ ),
44
+
45
+ GoodData::Profile.new(
46
+ {
47
+ 'accountSetting' => {
48
+ 'email' => 'tomas.svarovsky@gooddata.com',
49
+ 'firstName' => 'Tomas',
50
+ 'lastName' => 'Svarovsky'
51
+ }
52
+ }
53
+ ),
54
+ ]
55
+ end
56
+
57
+ after(:all) do
58
+ GoodData.disconnect
59
+ end
60
+
61
+ describe '#==' do
62
+ it 'Returns true for same objects' do
63
+ user1 = GoodData.user.dup
64
+ user2 = GoodData.user.dup
65
+ res = user1 == user2
66
+ res.should be_true
67
+ end
68
+
69
+ it 'Returns false for different objects' do
70
+ user1 = GoodData.user.dup
71
+ user2 = GoodData.user.dup
72
+
73
+ # Do some little modification
74
+ user2.first_name = 'kokos'
75
+
76
+ res = user1 == user2
77
+ res.should be_false
78
+ end
79
+ end
80
+
81
+ describe '#!=' do
82
+ it 'Returns false for same objects' do
83
+ user1 = GoodData.user.dup
84
+ user2 = GoodData.user.dup
85
+ res = user1 != user2
86
+ res.should be_false
87
+ end
88
+
89
+ it 'Returns true for different objects' do
90
+ user1 = GoodData.user.dup
91
+ user2 = GoodData.user.dup
92
+
93
+ # Do some little modification
94
+ user2.first_name = 'kokos'
95
+
96
+ res = user1 != user2
97
+ res.should be_true
98
+ end
99
+ end
100
+
101
+ describe '#apply' do
102
+ it 'When diff of two objects applied to first result should be same as second object' do
103
+ user1 = GoodData.user.dup
104
+ user2 = GoodData.user.dup
105
+
106
+ # Do some little modification
107
+ user2.first_name = 'kokos'
108
+
109
+ diff = user1.diff(user2)
110
+
111
+ expect(diff).to be_instance_of(Hash)
112
+ diff.length.should_not eql(0)
113
+
114
+ user1.apply(diff)
115
+
116
+ res = user1 == user2
117
+ res.should be_true
118
+ end
119
+ end
120
+
121
+ describe '#diff' do
122
+ it 'Returns empty hash for same objects' do
123
+ user1 = GoodData.user.dup
124
+ user2 = GoodData.user.dup
125
+ res = user1.diff(user2)
126
+ expect(res).to be_instance_of(Hash)
127
+ res.length.should eql(0)
128
+ end
129
+
130
+ it 'Returns non empty hash for different objects' do
131
+ user1 = GoodData.user.dup
132
+ user2 = GoodData.user.dup
133
+
134
+ # Do some little modification
135
+ user2.first_name = 'kokos'
136
+
137
+ res = user1.diff(user2)
138
+ expect(res).to be_instance_of(Hash)
139
+ res.length.should_not eql(0)
140
+ end
141
+ end
142
+
143
+ describe '#diff_list' do
144
+ it 'Returns empty diff for same arrays' do
145
+ l1 = [
146
+ @users[0]
147
+ ]
148
+
149
+ l2 = [
150
+ @users[0]
151
+ ]
152
+
153
+ diff = GoodData::Profile.diff_list(l1, l2)
154
+ diff[:added].length.should eql(0)
155
+ diff[:changed].length.should eql(0)
156
+ diff[:removed].length.should eql(0)
157
+ end
158
+
159
+ it 'Recognizes added element' do
160
+ l1 = []
161
+
162
+ l2 = [
163
+ @users[0]
164
+ ]
165
+
166
+ diff = GoodData::Profile.diff_list(l1, l2)
167
+ diff[:added].length.should eql(1)
168
+ diff[:changed].length.should eql(0)
169
+ diff[:removed].length.should eql(0)
170
+ end
171
+
172
+ it 'Recognizes changed element' do
173
+ l1 = [
174
+ @users[0]
175
+ ]
176
+
177
+ l2 = [
178
+ GoodData::Profile.new(@users[0].json.deep_dup)
179
+ ]
180
+ l2[0].first_name = 'Peter'
181
+
182
+ diff = GoodData::Profile.diff_list(l1, l2)
183
+ diff[:added].length.should eql(0)
184
+ diff[:changed].length.should eql(1)
185
+ diff[:removed].length.should eql(0)
186
+ end
187
+
188
+ it 'Recognizes removed element' do
189
+ l1 = [
190
+ @users[0]
191
+ ]
192
+
193
+ l2 = []
194
+
195
+ diff = GoodData::Profile.diff_list(l1, l2)
196
+ diff[:added].length.should eql(0)
197
+ diff[:changed].length.should eql(0)
198
+ diff[:removed].length.should eql(1)
199
+ end
200
+ end
201
+
202
+ describe '#projects' do
203
+ it 'Returns user projects as array of GoodData::Project' do
204
+ projects = @user.projects
205
+ expect(projects).to be_an_instance_of(Array)
206
+
207
+ projects.each do |project|
208
+ expect(project).to be_an_instance_of(GoodData::Project)
209
+ end
210
+ end
211
+ end
212
+ end