bluekai 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +44 -0
  8. data/Rakefile +2 -0
  9. data/bluekai.gemspec +28 -0
  10. data/circle.yml +3 -0
  11. data/lib/bluekai.rb +7 -0
  12. data/lib/bluekai/client.rb +407 -0
  13. data/lib/bluekai/error.rb +4 -0
  14. data/lib/bluekai/version.rb +3 -0
  15. data/spec/fixtures/signatures/1952b4f61dbd2187b5589dfc390af2ee985ca6f43020081d420f5d9ca025532e +1 -0
  16. data/spec/fixtures/signatures/26d52d2e4c2d42ba54ec6b4de9e67d9b566aeb8224c28261d1d133b7fb3c3436 +1 -0
  17. data/spec/fixtures/signatures/2db01e685f73149994efc9824c10fa91e704fb7256d748c4305101513444f49f +1 -0
  18. data/spec/fixtures/signatures/391112d6698e9864c1d9b37f92ab7e6db690a7e84949378ee272b011f3b82fc0 +1 -0
  19. data/spec/fixtures/signatures/3c33aa44e5fbea304ffda0390ac2e413a02d187d5425f67c3edab34684b2b18f +1 -0
  20. data/spec/fixtures/signatures/691325444d07bf08ce72b95283f8a8fd74e19f6963263e5367772b7633cbeab0 +1 -0
  21. data/spec/fixtures/signatures/78f40f967bf9cb1ae030412e7c28267a8050926a538226c685fb2dec6f23b44a +1 -0
  22. data/spec/fixtures/signatures/847da153b01c0ea4e3beeeb00f5552c3dd773227ee5aeaf5c9ff9a620adae324 +1 -0
  23. data/spec/fixtures/signatures/a49b4d9ac5b30c91f95a907b887f9b8eaf5c7856b844c49d2b937c00d88af63d +1 -0
  24. data/spec/fixtures/signatures/a6d578d433ca6f7c84ce9da14c415b3d302bf1da2b87f7666c637419fb784f57 +1 -0
  25. data/spec/fixtures/signatures/d30077840edb2b580c1c9a4a6659989b8342cfdc439ceef0c984672849288243 +1 -0
  26. data/spec/fixtures/signatures/d3c90cbaf307901dff229713b703217d7460f3c50400aa981ac20088f58343ad +1 -0
  27. data/spec/fixtures/vcr_cassettes/Bluekai_Client/_ping/when_we_get_a_pong_from_bluekai/.yml +30 -0
  28. data/spec/fixtures/vcr_cassettes/Bluekai_Client/creates_a_category.yml +49 -0
  29. data/spec/fixtures/vcr_cassettes/Bluekai_Client/creates_a_rule.yml +57 -0
  30. data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_10_phint_rules.yml +194 -0
  31. data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_4_categories.yml +3569 -0
  32. data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_Bluekai_taxonomy_nodes.yml +161267 -0
  33. data/spec/fixtures/vcr_cassettes/Bluekai_Client/performs_a_ping.yml +36 -0
  34. data/spec/fixtures/vcr_cassettes/Bluekai_Client/reads_a_category_and_its_reach.yml +2459 -0
  35. data/spec/fixtures/vcr_cassettes/Bluekai_Client/reads_a_rule.yml +56 -0
  36. data/spec/fixtures/vcr_cassettes/Bluekai_Client/updates_a_category.yml +48 -0
  37. data/spec/fixtures/vcr_cassettes/Bluekai_Client/updates_a_rule.yml +57 -0
  38. data/spec/lib/bluekai/client_integration_spec.rb +153 -0
  39. data/spec/lib/bluekai/client_spec.rb +19 -0
  40. data/spec/spec_helper.rb +108 -0
  41. metadata +193 -0
@@ -0,0 +1,56 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://bluekai-domain.com/Services/WS/classificationRules/10380?bksig=NcegM6j6CXThFfxrXyjWoXeIi3RoARMRCqX2Co%2B%2BCsQ=&bkuid=bluekai-api-user-key
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Date:
16
+ - Tue, 07 Apr 2015 14:59:48 GMT
17
+ Set-Cookie:
18
+ - JSESSIONID=930E123268B67F2E8FA1DD22E61A4024; Path=/Services; HttpOnly
19
+ Content-Type:
20
+ - application/json
21
+ Cneonction:
22
+ - close
23
+ Transfer-Encoding:
24
+ - chunked
25
+ body:
26
+ encoding: UTF-8
27
+ string: |-
28
+ {
29
+ "name" : "CONVERSION_ACTION_SIMULATION_9126",
30
+ "id" : 10380,
31
+ "type" : "phint",
32
+ "status" : "active",
33
+ "phints" : [ {
34
+ "id" : 14420,
35
+ "key" : "offer_id",
36
+ "value" : "9126",
37
+ "operator" : "is"
38
+ } ],
39
+ "partner_id" : bluekai-partner-id,
40
+ "created_at" : "Thu Apr 02 09:50:57 CDT 2015",
41
+ "updated_at" : "Thu Apr 02 09:50:57 CDT 2015",
42
+ "categories" : [ {
43
+ "id" : 421427,
44
+ "name" : "Simulation"
45
+ }, {
46
+ "id" : 421262,
47
+ "name" : "Action"
48
+ } ],
49
+ "sites" : [ {
50
+ "id" : 23705,
51
+ "name" : "Cake - Data Collection Tag"
52
+ } ]
53
+ }
54
+ http_version:
55
+ recorded_at: Tue, 07 Apr 2015 14:59:49 GMT
56
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: put
5
+ uri: https://bluekai-domain.com/Services/WS/classificationCategories/424251?bksig=6nWdj4cOVG4Cnjm/9qfmjG5MKJ8h446WQKBzT2AP30w=&bkuid=bluekai-api-user-key
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"description":"an example category wohooo","name":"Test Category 321"}'
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Content-Type:
13
+ - application/json
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Date:
20
+ - Wed, 08 Apr 2015 10:26:10 GMT
21
+ Set-Cookie:
22
+ - JSESSIONID=B2B5C8E137645B87EC6C602FDAF735AC; Path=/Services; HttpOnly
23
+ Content-Type:
24
+ - application/json
25
+ Cneonction:
26
+ - close
27
+ Transfer-Encoding:
28
+ - chunked
29
+ body:
30
+ encoding: UTF-8
31
+ string: |-
32
+ {
33
+ "name" : "Test Category 321",
34
+ "id" : 424251,
35
+ "description" : "an example category wohooo",
36
+ "leaf" : true,
37
+ "notes" : "",
38
+ "parent_id" : 422741,
39
+ "created_at" : "2015-04-08 05:21:29-0500",
40
+ "updated_at" : "2015-04-08 05:26:10-0500",
41
+ "navigation_only" : false,
42
+ "analytics_excluded" : false,
43
+ "mutex_children" : false,
44
+ "rules" : [ ]
45
+ }
46
+ http_version:
47
+ recorded_at: Wed, 08 Apr 2015 10:26:11 GMT
48
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,57 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: put
5
+ uri: https://bluekai-domain.com/Services/WS/classificationRules/12490?bksig=C5k49xPl8GSTb3AfU9ICjyo5rgDFRyF3DCAzHrG7QQs=&bkuid=bluekai-api-user-key
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"category_ids":[421262],"name":"CONVERSION_TEST_321","partner_id":"bluekai-partner-id","phints":[{"key":"offer_id","value":321,"operator":"contains"}],"site_ids":[23705],"type":"phint"}'
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Content-Type:
13
+ - application/json
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Date:
20
+ - Tue, 07 Apr 2015 14:59:47 GMT
21
+ Set-Cookie:
22
+ - JSESSIONID=9EF5CCE41946BA0101768D0ED2A19FE7; Path=/Services; HttpOnly
23
+ Content-Type:
24
+ - application/json
25
+ Cneonction:
26
+ - close
27
+ Transfer-Encoding:
28
+ - chunked
29
+ body:
30
+ encoding: UTF-8
31
+ string: |-
32
+ {
33
+ "name" : "CONVERSION_TEST_321",
34
+ "id" : 12490,
35
+ "type" : "phint",
36
+ "status" : "active",
37
+ "phints" : [ {
38
+ "id" : 16543,
39
+ "key" : "offer_id",
40
+ "value" : "321",
41
+ "operator" : "contains"
42
+ } ],
43
+ "partner_id" : bluekai-partner-id,
44
+ "created_at" : "Tue Apr 07 07:29:29 CDT 2015",
45
+ "updated_at" : "Tue Apr 07 09:59:47 CDT 2015",
46
+ "categories" : [ {
47
+ "id" : 421262,
48
+ "name" : "Action"
49
+ } ],
50
+ "sites" : [ {
51
+ "id" : 23705,
52
+ "name" : "Cake - Data Collection Tag"
53
+ } ]
54
+ }
55
+ http_version:
56
+ recorded_at: Tue, 07 Apr 2015 14:59:48 GMT
57
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,153 @@
1
+ require 'bluekai/client'
2
+ require 'bluekai/error'
3
+
4
+ RSpec.describe Bluekai::Client, :vcr do
5
+ before :each do
6
+ allow(subject).to receive(:sign).and_wrap_original do |method, http_method, path, query, body|
7
+ string_to_sign = http_method + path + query.to_s + body.to_s
8
+ hash = Digest::SHA256.hexdigest(string_to_sign)
9
+ file = "spec/fixtures/signatures/#{hash}"
10
+ next File.read(file) if File.exist?(file)
11
+ result = method.call(http_method, path, query, body)
12
+ File.open(file, 'w+') { |f| f.write(result) }
13
+ result
14
+ end
15
+ end
16
+
17
+ it 'performs a ping' do
18
+ expect(subject.ping).to eq(true)
19
+ end
20
+
21
+ it 'lists Bluekai taxonomy nodes' do
22
+ tax_response = subject.taxonomy(parentID: 186)
23
+ expect(tax_response).to all(have_key(:nodeID))
24
+ expect(tax_response).to all(have_key(:nodeName))
25
+ end
26
+
27
+ it 'creates a rule' do
28
+ rule_body = {
29
+ name: 'CONVERSION_TEST_123',
30
+ type: 'phint',
31
+ phints: [{
32
+ key: 'offer_id',
33
+ value: 321,
34
+ operator: 'is'
35
+ }],
36
+ category_ids: [421262],
37
+ site_ids: [23705]
38
+ }
39
+ create_response = subject.rule_create(rule_body)
40
+ expect(create_response).to include(
41
+ name: 'CONVERSION_TEST_123',
42
+ type: 'phint',
43
+ status: 'active',
44
+ phints: [{ id: 16552, key: 'offer_id', value: '321', operator: 'is' }],
45
+ categories: [{ id: 421262, name: 'Action' }],
46
+ sites: [{ id: 23705, name: 'Cake - Data Collection Tag' }]
47
+ )
48
+ end
49
+
50
+ it 'updates a rule' do
51
+ update_body = {
52
+ name: 'CONVERSION_TEST_321',
53
+ type: 'phint',
54
+ phints: [{
55
+ key: 'offer_id',
56
+ value: 321,
57
+ operator: 'contains'
58
+ }],
59
+ category_ids: [421262],
60
+ site_ids: [23705]
61
+ }
62
+
63
+ update_response = subject.rule_update(12490, update_body)
64
+
65
+ expect(update_response).to include(
66
+ name: 'CONVERSION_TEST_321',
67
+ type: 'phint',
68
+ status: 'active',
69
+ phints: [{ id: 16543, key: 'offer_id', value: '321', operator: 'contains' }],
70
+ categories: [{ id: 421262, name: 'Action' }]
71
+ )
72
+ end
73
+
74
+ it 'reads a rule' do
75
+ read_response = subject.rule_read(10380)
76
+ expect(read_response).to include(
77
+ categories: [{ id: 421427, name: 'Simulation' },
78
+ { id: 421262, name: 'Action' }],
79
+ created_at: 'Thu Apr 02 09:50:57 CDT 2015',
80
+ id: 10380,
81
+ name: 'CONVERSION_ACTION_SIMULATION_9126',
82
+ phints: [{ id: 14420, key: 'offer_id', value: '9126', operator: 'is' }],
83
+ sites: [{ id: 23705, name: 'Cake - Data Collection Tag' }],
84
+ status: 'active',
85
+ type: 'phint'
86
+ )
87
+ end
88
+
89
+ it 'lists 10 phint rules' do
90
+ rule_list = subject.rule_list(offset: 0, size: 10, type: 'phint')
91
+ expect(rule_list.count).to eq(10)
92
+ expect(rule_list).to all(include(
93
+ type: 'phint'
94
+ ))
95
+ end
96
+
97
+ ###
98
+ # Categories
99
+ ###
100
+
101
+ it 'reads a category and its reach' do
102
+ read_response = subject.category_read(category_id: 421262, stats: 'True')
103
+ expect(read_response).to include(
104
+ name: 'Action',
105
+ id: 421262,
106
+ description: 'People who converted for Action games',
107
+ leaf: true,
108
+ parent_id: 421229
109
+ )
110
+ expect(read_response[:rules].size).to be > 0
111
+ end
112
+
113
+ it 'lists 4 categories' do
114
+ list_response = subject.category_list(offset: 0, size: 4)
115
+ expect(list_response.count).to eq(4)
116
+ expect(list_response).to all(have_key(:name))
117
+ expect(list_response).to all(have_key(:rules))
118
+ end
119
+
120
+ it 'creates a category' do
121
+ category_body = {
122
+ name: 'Test Category 123',
123
+ parent_id: '422741',
124
+ description: 'an example category',
125
+ analytics_excluded: 'false',
126
+ navigation_only: 'false',
127
+ mutex_children: 'false',
128
+ notes: 'Just an API test'
129
+ }
130
+ create_response = subject.category_create(category_body)
131
+ expect(create_response).to include(
132
+ name: 'Test Category 123',
133
+ parent_id: 422741,
134
+ description: 'an example category',
135
+ analytics_excluded: false,
136
+ navigation_only: false,
137
+ mutex_children: false,
138
+ notes: 'Just an API test'
139
+ )
140
+ end
141
+
142
+ it 'updates a category' do
143
+ category_update_body = {
144
+ name: 'Test Category 321',
145
+ description: 'an example category wohooo'
146
+ }
147
+ update_response = subject.category_update(424251, category_update_body)
148
+ expect(update_response).to include(
149
+ name: 'Test Category 321',
150
+ description: 'an example category wohooo'
151
+ )
152
+ end
153
+ end
@@ -0,0 +1,19 @@
1
+ require 'bluekai/client'
2
+ require 'bluekai/error'
3
+
4
+ RSpec.describe Bluekai::Client do
5
+ subject { described_class.new(api_private_key: '1234') }
6
+
7
+ describe '#sign' do
8
+ it 'computes a correct signature' do
9
+ signature = subject.send(:sign, 'GET', '/Services/WS/classificationCategories/', 'blabli', key1: 'value1', key2: 'value2')
10
+ expect(signature).to eq('msNdVnof8pNLImtDYxh0KDiMHWqrvjExAEh7UcSLJw8%3D')
11
+ end
12
+ end
13
+
14
+ describe '#request' do
15
+ it 'raises ArgumentError if unknown HTTP method is passed' do
16
+ expect { subject.send(:request, 'FOO', '123', {}, nil) }.to raise_error(ArgumentError)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,108 @@
1
+ require 'codeclimate-test-reporter'
2
+ CodeClimate::TestReporter.start
3
+
4
+ require 'vcr'
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
8
+ # file to always be loaded, without a need to explicitly require it in any files.
9
+ #
10
+ # Given that it is always loaded, you are encouraged to keep this file as
11
+ # light-weight as possible. Requiring heavyweight dependencies from this file
12
+ # will add to the boot time of your test suite on EVERY test run, even for an
13
+ # individual file that may not need all of that loaded. Instead, consider making
14
+ # a separate helper file that requires the additional dependencies and performs
15
+ # the additional setup, and require it from the spec files that actually need it.
16
+ #
17
+ # The `.rspec` file also contains a few flags that are not defaults but that
18
+ # users commonly want.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # The settings below are suggested to provide a good initial experience
46
+ # with RSpec, but feel free to customize to your heart's content.
47
+ # # These two settings work together to allow you to limit a spec run
48
+ # # to individual examples or groups you care about by tagging them with
49
+ # # `:focus` metadata. When nothing is tagged with `:focus`, all examples
50
+ # # get run.
51
+ # config.filter_run :focus
52
+ # config.run_all_when_everything_filtered = true
53
+ #
54
+ # # Limits the available syntax to the non-monkey patched syntax that is recommended.
55
+ # # For more details, see:
56
+ # # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
57
+ # # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
58
+ # # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
59
+ # config.disable_monkey_patching!
60
+ #
61
+ # # This setting enables warnings. It's recommended, but in some cases may
62
+ # # be too noisy due to issues in dependencies.
63
+ # config.warnings = true
64
+ #
65
+ # # Many RSpec users commonly either run the entire suite or an individual
66
+ # # file, and it's useful to allow more verbose output when running an
67
+ # # individual spec file.
68
+ # if config.files_to_run.one?
69
+ # # Use the documentation formatter for detailed output,
70
+ # # unless a formatter has already been configured
71
+ # # (e.g. via a command-line flag).
72
+ # config.default_formatter = 'doc'
73
+ # end
74
+ #
75
+ # # Print the 10 slowest examples and example groups at the
76
+ # # end of the spec run, to help surface which specs are running
77
+ # # particularly slow.
78
+ # config.profile_examples = 10
79
+ #
80
+ # # Run specs in random order to surface order dependencies. If you find an
81
+ # # order dependency and want to debug it, you can fix the order by providing
82
+ # # the seed, which is printed after each run.
83
+ # # --seed 1234
84
+ # config.order = :random
85
+ #
86
+ # # Seed global randomization in this process using the `--seed` CLI option.
87
+ # # Setting this allows you to use `--seed` to deterministically reproduce
88
+ # # test failures related to randomization by passing the same `--seed` value
89
+ # # as the one that triggered the failure.
90
+ # Kernel.srand config.seed
91
+ end
92
+
93
+ ENV['BLUEKAI_API_USER_KEY'] ||= 'bluekai-api-user-key'
94
+ ENV['BLUEKAI_API_PRIVATE_KEY'] ||= 'bluekai-private-key'
95
+ ENV['BLUEKAI_DOMAIN'] ||= 'bluekai-domain.com'
96
+ ENV['BLUEKAI_PARTNER_ID'] ||= '2695'
97
+
98
+ VCR.configure do |c|
99
+ c.configure_rspec_metadata!
100
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
101
+ c.hook_into :webmock
102
+ c.filter_sensitive_data('bluekai-api-user-key') { ENV['BLUEKAI_API_USER_KEY'] }
103
+ c.filter_sensitive_data('bluekai-domain.com') { ENV['BLUEKAI_DOMAIN'] }
104
+ c.filter_sensitive_data('bluekai-private-key') { ENV['BLUEKAI_API_PRIVATE_KEY'] }
105
+ c.filter_sensitive_data('bluekai-partner-id') { ENV['BLUEKAI_PARTNER_ID'] }
106
+ # allow codeclimate-test-reporter to call the mothership
107
+ c.ignore_hosts 'codeclimate.com'
108
+ end