delighted 1.0.0.alpha
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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +20 -0
- data/Rakefile +8 -0
- data/delighted.gemspec +24 -0
- data/lib/delighted.rb +25 -0
- data/lib/delighted/client.rb +65 -0
- data/lib/delighted/enumerable_resource_collection.rb +4 -0
- data/lib/delighted/errors.rb +31 -0
- data/lib/delighted/http_adapter.rb +21 -0
- data/lib/delighted/http_response.rb +15 -0
- data/lib/delighted/json.rb +23 -0
- data/lib/delighted/operations.rb +8 -0
- data/lib/delighted/operations/all.rb +21 -0
- data/lib/delighted/operations/create.rb +17 -0
- data/lib/delighted/operations/retrieve.rb +38 -0
- data/lib/delighted/resource.rb +75 -0
- data/lib/delighted/resource_interface.rb +19 -0
- data/lib/delighted/resources/metrics.rb +9 -0
- data/lib/delighted/resources/person.rb +8 -0
- data/lib/delighted/resources/survey_responses.rb +9 -0
- data/lib/delighted/utils.rb +45 -0
- data/lib/delighted/version.rb +3 -0
- data/test/delighted_test.rb +78 -0
- data/test/test_helper.rb +11 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5713c3b8bbf569d4ea070698eb71615529769c64
|
4
|
+
data.tar.gz: 85fb1b406babe39d9560674a80562952f05e93b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dcd088106f462f56a3bad2f6a339c3c0f1ad0d434ce65253d68e85c5194a70960f6a913cbf56ad83e378972ae34c14154330cd79c481c3cc791cda0739630399
|
7
|
+
data.tar.gz: dd86b0f081e36e4515a761a8e7b0cff16516ba498454b1c9b0891f2a5ed7bcff2617e163f02f21b35bd77eed4dc042609f81094fb4ffd5202507524b28afb9d6
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Delighted Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Delighted API client for Ruby
|
2
|
+
|
3
|
+
Official Ruby client for the [Delighted API](https://delightedapp.com).
|
4
|
+
|
5
|
+
For installation and usage instructions, please [sign in to your Delighted account](https://delightedapp.com/signin) and follow the API documentation under Settings.
|
6
|
+
|
7
|
+
## Supported Rubies
|
8
|
+
|
9
|
+
- Ruby MRI (1.8.7+)
|
10
|
+
- JRuby (1.8 + 1.9 modes)
|
11
|
+
- RBX (1.8 + 1.9 modes)
|
12
|
+
- REE (1.8.7-2012.02)
|
13
|
+
|
14
|
+
## Contributing
|
15
|
+
|
16
|
+
1. Fork it
|
17
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
18
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
19
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
20
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/delighted.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'delighted/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "delighted"
|
7
|
+
spec.version = Delighted::VERSION
|
8
|
+
spec.authors = ["Mark Dodwell"]
|
9
|
+
spec.email = ["mark@madeofcode.com"]
|
10
|
+
spec.description = "Delighted API client for Ruby."
|
11
|
+
spec.summary = "Delighted is the easiest and most beautiful way to measure customer happiness. Are your customers delighted?"
|
12
|
+
spec.homepage = "https://github.com/delighted/delighted-ruby"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "multi_json"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "minitest"
|
23
|
+
spec.add_development_dependency "mocha"
|
24
|
+
end
|
data/lib/delighted.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
require 'cgi'
|
4
|
+
require 'multi_json'
|
5
|
+
require 'set'
|
6
|
+
|
7
|
+
require 'delighted/utils'
|
8
|
+
require 'delighted/json'
|
9
|
+
|
10
|
+
require 'delighted/enumerable_resource_collection'
|
11
|
+
require 'delighted/resource'
|
12
|
+
require 'delighted/operations'
|
13
|
+
require 'delighted/operations/all'
|
14
|
+
require 'delighted/operations/create'
|
15
|
+
require 'delighted/operations/retrieve'
|
16
|
+
|
17
|
+
require 'delighted/resources/metrics'
|
18
|
+
require 'delighted/resources/person'
|
19
|
+
require 'delighted/resources/survey_responses'
|
20
|
+
|
21
|
+
require 'delighted/errors'
|
22
|
+
require 'delighted/resource_interface'
|
23
|
+
require 'delighted/http_response'
|
24
|
+
require 'delighted/http_adapter'
|
25
|
+
require 'delighted/client'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Delighted
|
2
|
+
class Client
|
3
|
+
DEFAULT_API_BASE_URL = "https://api.delightedapp.com/v1"
|
4
|
+
DEFAULT_HTTP_ADAPTER = HTTPAdapter.new
|
5
|
+
|
6
|
+
def initialize(opts = {})
|
7
|
+
@api_key = opts[:api_key] or raise ArgumentError, "You must pass an :api_key."
|
8
|
+
@api_base_url = opts[:api_base_url] || DEFAULT_API_BASE_URL
|
9
|
+
@http_adapter = opts[:http_adapter] || DEFAULT_HTTP_ADAPTER
|
10
|
+
end
|
11
|
+
|
12
|
+
Resource.resources.each do |resource|
|
13
|
+
class_eval <<-END, __FILE__, __LINE__
|
14
|
+
def #{resource.interface_name}
|
15
|
+
@#{resource.interface_name} ||= ResourceInterface.new(self, #{resource.name})
|
16
|
+
end
|
17
|
+
END
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_json(path, params = {})
|
21
|
+
headers = default_headers.dup.merge('Accept' => 'application/json')
|
22
|
+
|
23
|
+
uri = URI.parse(File.join(@api_base_url, path))
|
24
|
+
uri.query = Utils.to_query(params) unless params.empty?
|
25
|
+
|
26
|
+
response = @http_adapter.request(:get, uri, headers)
|
27
|
+
handle_json_response(response)
|
28
|
+
end
|
29
|
+
|
30
|
+
def post_json(path, params = {})
|
31
|
+
headers = default_headers.dup.merge('Accept' => 'application/json', 'Content-Type' => 'application/json')
|
32
|
+
|
33
|
+
uri = URI.parse(File.join(@api_base_url, path))
|
34
|
+
data = JSON.dump(params) unless params.empty?
|
35
|
+
|
36
|
+
response = @http_adapter.request(:post, uri, headers, data)
|
37
|
+
handle_json_response(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def handle_json_response(response)
|
43
|
+
case response.status_code
|
44
|
+
when 200, 201, 202
|
45
|
+
Utils.symbolize_keys(JSON.load(response.body))
|
46
|
+
when 401
|
47
|
+
raise AuthenticationError, response
|
48
|
+
when 406
|
49
|
+
raise UnsupportedFormatRequestedError, response
|
50
|
+
when 422
|
51
|
+
raise ResourceValidationError, response
|
52
|
+
when 503
|
53
|
+
raise ServiceUnavailableError, response
|
54
|
+
else
|
55
|
+
raise GeneralAPIError, response
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_headers
|
60
|
+
@default_headers ||= {
|
61
|
+
'Authorization' => "Basic #{["#{@api_key}:"].pack('m0')}"
|
62
|
+
}.freeze
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Delighted
|
2
|
+
class Error < StandardError
|
3
|
+
def initialize(response)
|
4
|
+
@response = response
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
"#{@response.status_code}: #{@response.body}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AuthenticationError < Error
|
13
|
+
# 401, api auth missing or incorrect
|
14
|
+
end
|
15
|
+
|
16
|
+
class UnsupportedFormatRequestedError < Error
|
17
|
+
# 406, invalid format in Accept header
|
18
|
+
end
|
19
|
+
|
20
|
+
class ResourceValidationError < Error
|
21
|
+
# 422, validation errors
|
22
|
+
end
|
23
|
+
|
24
|
+
class GeneralAPIError < Error
|
25
|
+
# 500, general/unknown error
|
26
|
+
end
|
27
|
+
|
28
|
+
class ServiceUnavailableError < Error
|
29
|
+
# 503, maintenance or overloaded
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Delighted
|
2
|
+
class HTTPAdapter
|
3
|
+
REQUEST_CLASSES = {
|
4
|
+
get: Net::HTTP::Get,
|
5
|
+
post: Net::HTTP::Post,
|
6
|
+
}
|
7
|
+
|
8
|
+
def request(method, uri, headers = {}, data = nil)
|
9
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
10
|
+
http.use_ssl = true
|
11
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
12
|
+
|
13
|
+
request = REQUEST_CLASSES[method].new(uri.request_uri)
|
14
|
+
headers.each { |k,v| request[k] = v }
|
15
|
+
request.body = data
|
16
|
+
|
17
|
+
response = http.request(request)
|
18
|
+
HTTPResponse.new(response.code, response.to_hash, response.body)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Delighted
|
2
|
+
class HTTPResponse
|
3
|
+
attr_reader :status_code, :headers, :body
|
4
|
+
|
5
|
+
def initialize(raw_status_code, raw_headers, raw_body)
|
6
|
+
@status_code = raw_status_code.to_i
|
7
|
+
@headers = raw_headers
|
8
|
+
@body = raw_body
|
9
|
+
end
|
10
|
+
|
11
|
+
def content_type
|
12
|
+
@headers.values_at('content-type', 'Content-Type')[0]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Delighted
|
2
|
+
class JSON
|
3
|
+
class << self
|
4
|
+
if MultiJson.respond_to?(:dump)
|
5
|
+
def dump(*args)
|
6
|
+
MultiJson.dump(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def load(*args)
|
10
|
+
MultiJson.load(*args)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
def dump(*args)
|
14
|
+
MultiJson.encode(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def load(*args)
|
18
|
+
MultiJson.decode(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Delighted
|
2
|
+
module Operations
|
3
|
+
module All
|
4
|
+
def self.included(klass)
|
5
|
+
klass.extend(AuxiliaryClassMethods)
|
6
|
+
Operations.add_operations(klass, OperationClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module OperationClassMethods
|
10
|
+
def all(client, opts = {})
|
11
|
+
json = client.get_json(path, opts)
|
12
|
+
EnumerableResourceCollection.new(json.map { |attributes| new(attributes) })
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module AuxiliaryClassMethods
|
17
|
+
# pagination, enumerable stuff etc.
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Delighted
|
2
|
+
module Operations
|
3
|
+
module Create
|
4
|
+
def self.included(klass)
|
5
|
+
Operations.add_operations(klass, OperationClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module OperationClassMethods
|
9
|
+
def create(client, attributes = {})
|
10
|
+
params = Utils.hash_removing_key(attributes, :id)
|
11
|
+
json = client.post_json(path, params)
|
12
|
+
new(json)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Delighted
|
2
|
+
module Operations
|
3
|
+
module Retrieve
|
4
|
+
def self.included(klass)
|
5
|
+
if klass.singleton_resource?
|
6
|
+
Operations.add_operations(klass, Singleton::OperationClassMethods)
|
7
|
+
else
|
8
|
+
klass.extend(Pluralton::AuxiliaryClassMethods)
|
9
|
+
Operations.add_operations(klass, Pluralton::OperationClassMethods)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Pluralton
|
14
|
+
module OperationClassMethods
|
15
|
+
def retrieve(client, id)
|
16
|
+
json = client.get_json(path(id))
|
17
|
+
new(json)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module AuxiliaryClassMethods
|
22
|
+
def path(id = nil)
|
23
|
+
id ? "#{@path}/#{id}" : @path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module Singleton
|
29
|
+
module OperationClassMethods
|
30
|
+
def retrieve(client, opts = {})
|
31
|
+
json = client.get_json(path, opts)
|
32
|
+
new(json)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Delighted
|
2
|
+
class Resource
|
3
|
+
class << self
|
4
|
+
def interface_name=(interface_name)
|
5
|
+
@interface_name = interface_name
|
6
|
+
end
|
7
|
+
|
8
|
+
def interface_name
|
9
|
+
@interface_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def path=(path)
|
13
|
+
@path = path
|
14
|
+
end
|
15
|
+
|
16
|
+
def path
|
17
|
+
@path
|
18
|
+
end
|
19
|
+
|
20
|
+
def singleton_resource=(singleton_resource)
|
21
|
+
@singleton_resource = singleton_resource
|
22
|
+
end
|
23
|
+
|
24
|
+
def singleton_resource?
|
25
|
+
!!@singleton_resource
|
26
|
+
end
|
27
|
+
|
28
|
+
def operations
|
29
|
+
@operations ||= Set.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def resources
|
33
|
+
@resources ||= Set.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def inherited(klass)
|
37
|
+
resources << klass
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
undef :id if method_defined?(:id)
|
42
|
+
attr_reader :attributes
|
43
|
+
private :attributes
|
44
|
+
|
45
|
+
def initialize(attributes = {})
|
46
|
+
@id = attributes[:id]
|
47
|
+
define_id_reader if @id
|
48
|
+
@attributes = Utils.hash_removing_key(attributes, :id)
|
49
|
+
define_attribute_accessors(@attributes.keys)
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_hash
|
53
|
+
attributes
|
54
|
+
end
|
55
|
+
alias_method :to_h, :to_hash
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def define_id_reader
|
60
|
+
Utils.eigenclass(self).instance_eval do
|
61
|
+
attr_reader :id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def define_attribute_accessors(keys)
|
66
|
+
Utils.eigenclass(self).instance_eval do
|
67
|
+
keys.each do |key|
|
68
|
+
define_method(key) do
|
69
|
+
attributes[key]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Delighted
|
2
|
+
class ResourceInterface
|
3
|
+
def initialize(client, resource)
|
4
|
+
@resource = resource # more helpful inspect
|
5
|
+
|
6
|
+
Utils.eigenclass(self).instance_eval do
|
7
|
+
resource.operations.each do |operation|
|
8
|
+
define_method(operation) do |*args, &block|
|
9
|
+
resource.send(operation, *args.unshift(client), &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
inspect
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Delighted
|
2
|
+
module Utils
|
3
|
+
def self.eigenclass(object)
|
4
|
+
class << object; self; end
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.hash_removing_key(hash, key)
|
8
|
+
hash.reject { |k,v| k == key }.inject({}) { |memo,(k,v)| memo[k] = v; memo }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_query(hash_or_array, namespace = nil)
|
12
|
+
hash_or_array.map { |object|
|
13
|
+
k, v = case hash_or_array
|
14
|
+
when Hash then object
|
15
|
+
when Array then [nil, object[0]]
|
16
|
+
else raise ArgumentError, "must pass Hash or Array"
|
17
|
+
end
|
18
|
+
|
19
|
+
namespaced_k = namespace ? "#{namespace}[#{k}]" : k
|
20
|
+
|
21
|
+
case v
|
22
|
+
when Hash, Array then to_query(v, namespaced_k)
|
23
|
+
else "#{CGI.escape(namespaced_k.to_s)}=#{CGI.escape(v.to_s)}"
|
24
|
+
end
|
25
|
+
}.join("&")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.symbolize_keys(object)
|
29
|
+
case object
|
30
|
+
when Hash
|
31
|
+
object.inject({}) { |memo,(k,v)|
|
32
|
+
memo[(k.to_sym rescue k)] = Hash === v ? symbolize_keys(v) : v
|
33
|
+
memo
|
34
|
+
}
|
35
|
+
when Array
|
36
|
+
object.map { |v| symbolize_keys(v) }
|
37
|
+
else
|
38
|
+
object
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Delighted::Utils.symbolize_keys([1, {'goo' => { 'bar' => 1, :gyp => ['x'] }, foo: Object.new }])
|
45
|
+
# URI.unescape Delighted::Utils.to_query(foo: 1, gyp: { sum: 1, welp: ['a','b'] })
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Delighted::ClientTest < Delighted::TestCase
|
4
|
+
def test_instantiating_client_requires_api_key
|
5
|
+
assert_raises(ArgumentError) { Delighted::Client.new }
|
6
|
+
Delighted::Client.new(:api_key => '123abc')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Delighted::MetricsTest < Delighted::TestCase
|
11
|
+
def test_retrieving_metrics
|
12
|
+
uri = URI.parse("https://api.delightedapp.com/v1/metrics")
|
13
|
+
headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json" }
|
14
|
+
response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :nps => 10 }))
|
15
|
+
mock_http_adapter.expects(:request).with(:get, uri, headers).once.returns(response)
|
16
|
+
|
17
|
+
client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
|
18
|
+
metrics = client.metrics.retrieve
|
19
|
+
assert_kind_of Delighted::Metrics, metrics
|
20
|
+
assert_equal({ :nps => 10 }, metrics.to_hash)
|
21
|
+
assert_equal 10, metrics.nps
|
22
|
+
assert_raises(NoMethodError) { metrics.id }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Delighted::PeopleTest < Delighted::TestCase
|
27
|
+
def test_creating_or_updating_a_person
|
28
|
+
uri = URI.parse("https://api.delightedapp.com/v1/people")
|
29
|
+
headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json", 'Content-Type' => 'application/json' }
|
30
|
+
data = Delighted::JSON.dump({ :email => 'foo@bar.com' })
|
31
|
+
response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :id => '123', :email => 'foo@bar.com' }))
|
32
|
+
mock_http_adapter.expects(:request).with(:post, uri, headers, data).once.returns(response)
|
33
|
+
|
34
|
+
client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
|
35
|
+
person = client.people.create(:email => 'foo@bar.com')
|
36
|
+
assert_kind_of Delighted::Person, person
|
37
|
+
assert_equal({ :email => 'foo@bar.com' }, person.to_hash)
|
38
|
+
assert_equal 'foo@bar.com', person.email
|
39
|
+
assert_equal '123', person.id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Delighted::SurveyResponseTest < Delighted::TestCase
|
44
|
+
def test_creating_a_survey_response
|
45
|
+
uri = URI.parse("https://api.delightedapp.com/v1/survey_responses")
|
46
|
+
headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json", 'Content-Type' => 'application/json' }
|
47
|
+
data = Delighted::JSON.dump({ :person => '123', :score => 10 })
|
48
|
+
response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :id => '456', :person => '123', :score => 10 }))
|
49
|
+
mock_http_adapter.expects(:request).with(:post, uri, headers, data).once.returns(response)
|
50
|
+
|
51
|
+
client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
|
52
|
+
survey_response = client.survey_responses.create(:person => '123', :score => 10)
|
53
|
+
assert_kind_of Delighted::SurveyResponse, survey_response
|
54
|
+
assert_equal({ :person => '123', :score => 10 }, survey_response.to_hash)
|
55
|
+
assert_equal '123', survey_response.person
|
56
|
+
assert_equal 10, survey_response.score
|
57
|
+
assert_equal '456', survey_response.id
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_listing_all_survey_responses
|
61
|
+
uri = URI.parse("https://api.delightedapp.com/v1/survey_responses")
|
62
|
+
headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json" }
|
63
|
+
response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump([{ :id => '123', :comment => 'One' }, { :id => '456', :comment => 'Two' }]))
|
64
|
+
mock_http_adapter.expects(:request).with(:get, uri, headers).once.returns(response)
|
65
|
+
|
66
|
+
client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
|
67
|
+
survey_responses = client.survey_responses.all
|
68
|
+
assert_kind_of Delighted::EnumerableResourceCollection, survey_responses
|
69
|
+
assert_kind_of Delighted::SurveyResponse, survey_responses[0]
|
70
|
+
assert_equal({ :comment => 'One' }, survey_responses[0].to_hash)
|
71
|
+
assert_equal 'One', survey_responses[0].comment
|
72
|
+
assert_equal '123', survey_responses[0].id
|
73
|
+
assert_kind_of Delighted::SurveyResponse, survey_responses[1]
|
74
|
+
assert_equal({ :comment => 'Two' }, survey_responses[1].to_hash)
|
75
|
+
assert_equal 'Two', survey_responses[1].comment
|
76
|
+
assert_equal '456', survey_responses[1].id
|
77
|
+
end
|
78
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: delighted
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Dodwell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: multi_json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Delighted API client for Ruby.
|
70
|
+
email:
|
71
|
+
- mark@madeofcode.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .travis.yml
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- delighted.gemspec
|
83
|
+
- lib/delighted.rb
|
84
|
+
- lib/delighted/client.rb
|
85
|
+
- lib/delighted/enumerable_resource_collection.rb
|
86
|
+
- lib/delighted/errors.rb
|
87
|
+
- lib/delighted/http_adapter.rb
|
88
|
+
- lib/delighted/http_response.rb
|
89
|
+
- lib/delighted/json.rb
|
90
|
+
- lib/delighted/operations.rb
|
91
|
+
- lib/delighted/operations/all.rb
|
92
|
+
- lib/delighted/operations/create.rb
|
93
|
+
- lib/delighted/operations/retrieve.rb
|
94
|
+
- lib/delighted/resource.rb
|
95
|
+
- lib/delighted/resource_interface.rb
|
96
|
+
- lib/delighted/resources/metrics.rb
|
97
|
+
- lib/delighted/resources/person.rb
|
98
|
+
- lib/delighted/resources/survey_responses.rb
|
99
|
+
- lib/delighted/utils.rb
|
100
|
+
- lib/delighted/version.rb
|
101
|
+
- test/delighted_test.rb
|
102
|
+
- test/test_helper.rb
|
103
|
+
homepage: https://github.com/delighted/delighted-ruby
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - '>'
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 1.3.1
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 2.0.3
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Delighted is the easiest and most beautiful way to measure customer happiness.
|
127
|
+
Are your customers delighted?
|
128
|
+
test_files:
|
129
|
+
- test/delighted_test.rb
|
130
|
+
- test/test_helper.rb
|