qmetrics 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae3049cafee32758f34d294bb86246b8f9cc7bdd
4
+ data.tar.gz: ba4d97cca904ded5689436d108ce7375e08649c7
5
+ SHA512:
6
+ metadata.gz: 02b65c3c6472a6958b21289462241211c8fac893d7cebdffdd85a383321a1141dfb3a52f80eabd409603337d804cdfb1e299f67d40d0c870cdbc63abf00ebaef
7
+ data.tar.gz: 56b07f2d90f474895da16e6fa24fef75c24dd85c856473db5ddfd55c21389b5dd27197984850bc337ad1e47c307fef35f2aaaef4297e5218e3500aaf93a7dd83
@@ -0,0 +1,17 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /spec/support/*.yml
11
+ *.bundle
12
+ *.so
13
+ *.swp
14
+ *.swo
15
+ *.o
16
+ *.a
17
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1 @@
1
+ Qmetrics
@@ -0,0 +1 @@
1
+ ruby-2.1.3
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Kevin Collette
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.
@@ -0,0 +1,141 @@
1
+ # Qmetrics
2
+
3
+ Qmetrics is a gem that wraps the Queuemetrics JSON API with Ruby!
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'qmetrics'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install qmetrics
20
+
21
+ ## Usage
22
+
23
+ Note that this gem is unfinished! Things still need to be tweaked and tested.
24
+
25
+ ```ruby
26
+ api = Qmetrics::API.new(server: 192.168.1.101, port: 80, user: "foo", pass: "bar")
27
+ api.stats(queue: [4343], from: Time.now-86400, to: Time.now)
28
+
29
+ p api.stats.all_calls.result
30
+ #=> #<Qmetrics::Response:0x007feac2bdada8 @status="OK", @description="", @time_elapsed="109ms", @qmetrics_version="14.06.2", @result={:all_calls=>{"All calls:"=>"&nbsp;", "N. calls answered by operators:"=>"1,477", "Average call length:"=>"387.1 s.", "Min call length:"=>"0:00", "Max call length:"=>"1:22:45", "Total call length:"=>"158.8 H", "Average call waiting time:"=>"20.8 s.", "Min waiting time:"=>"0:01", "Max waiting time:"=>"7:54", "Total waiting time:"=>"8.6 H", "Average initial position"=>"1.5", "Min initial position"=>"1", "Max initial position"=>"7", "Coverage"=>"99.9%"}}
31
+ ```
32
+
33
+ ## Supported Methods
34
+
35
+ ### Stats
36
+
37
+ - all_calls
38
+ - calls_within
39
+ - agents_on_queue
40
+ - service_level_agreement
41
+ - disconnection_causes
42
+ - transfers
43
+ - answered_calls_by_queue
44
+ - answered_calls_by_direction
45
+ - stints
46
+ - initial_queue_positions
47
+ - ivr_selections
48
+ - dnis
49
+ - music_on_hold_by_agent
50
+ - report_header
51
+ - answered_calls_details
52
+ - ivr_details
53
+ - all_unanswered_calls
54
+ - unanswered_calls_within
55
+ - disconnection_causes
56
+ - unanswered_by_queue
57
+ - unanswered_outbound_calls
58
+ - unanswered_by_length
59
+ - inclusive_sla
60
+ - unanswered_by_key_press
61
+ - unanswered_stints
62
+ - all_calls_by_stints
63
+ - all_calls_initial_queue_position
64
+ - lost_calls_ivr_selections
65
+ - all_calls_ivr_selections
66
+ - lost_calls_dnis
67
+ - all_calls_dnis
68
+ - call_overview
69
+ - inclusive_answered_sla
70
+ - unanswered_calls_details
71
+ - area_code_report
72
+ - answered_calls_by_area
73
+ - inbound_acd_call_attempts
74
+ - acd_attempts_by_queue
75
+ - acd_attempts_by_terminal
76
+ - answered_call_distribution_by_day
77
+ - answered_call_wait_time_per_day
78
+ - unanswered_call_wait_time_per_day
79
+ - sales_per_day
80
+ - schedule_adherence_per_day
81
+ - queue_length_per_day
82
+ - inclusive_sla_per_day
83
+ - traffic_analysis_per_day
84
+ - answered_call_distribution_per_hour
85
+ - answered_call_wait_time_per_hour
86
+ - unanswered_call_wait_time_per_hour
87
+ - sales_per_hour
88
+ - schedule_adherence_per_hour
89
+ - queue_length_per_hour
90
+ - inclusive_sla_per_hour
91
+ - traffic_analysis_per_hour
92
+ - answered_call_distribution_per_day_of_week
93
+ - answered_call_wait_time_per_day_of_week
94
+ - unanswered_call_wait_time_per_day_of_week
95
+ - sales_per_day_of_week
96
+ - schedule_adherence_per_day_of_week
97
+ - queue_length_per_day_of_week
98
+ - inclusive_sla_per_day_of_week
99
+ - traffic_analysis_per_day_of_week
100
+ - agent_session_detail
101
+ - session_and_pause_durations
102
+ - agent_availability
103
+ - answered_calls
104
+ - answered_calls_by_custom_group
105
+ - answered_calls_by_location
106
+ - answered_calls_by_service_group
107
+ - agent_performance_by_acd_group
108
+ - agent_occupancy_report
109
+ - agent_payable_time_by_hour
110
+ - agent_billable_time_by_hour
111
+ - detail_of_agent_pauses
112
+ - outcomes
113
+ - call_results_by_outcomes
114
+ - billable_activities
115
+ - non_billable_activities
116
+ - detailed_agent_report
117
+ - outcomes_per_agent
118
+ - ivr_traversals
119
+ - ivr_timing
120
+ - ivr_goals
121
+
122
+ ### Realtime
123
+
124
+ - queues_in_use
125
+ - calls_being_processed
126
+ - agents_logged_in
127
+ - wallboard_top_panel
128
+ - wall_calls_being_processed
129
+ - visitor_calls_processed
130
+ - calls_taken
131
+ - calls_lost
132
+ - raw_agent_panel
133
+ - raw_calls_panel
134
+
135
+ ## Contributing
136
+
137
+ 1. Fork it ( https://github.com/[my-github-username]/Qmetrics/fork )
138
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
139
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
140
+ 4. Push to the branch (`git push origin my-new-feature`)
141
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,14 @@
1
+ #dependencies
2
+ require 'httparty'
3
+
4
+ #lib
5
+ require "qmetrics/version"
6
+ require "qmetrics/api"
7
+ require "qmetrics/caller"
8
+ require "qmetrics/stats"
9
+ require "qmetrics/realtime"
10
+ require "qmetrics/response"
11
+
12
+ module Qmetrics
13
+
14
+ end
@@ -0,0 +1,45 @@
1
+ module Qmetrics
2
+ class HTTPStatusError < StandardError
3
+ end
4
+
5
+ class API
6
+
7
+ def initialize(server: , port: , user: , pass: )
8
+ @base_route = "http://#{server}:#{port}/queuemetrics"
9
+ @auth = { basic_auth: { username: user, password: pass } }
10
+ end
11
+
12
+ def call(api_method,options={})
13
+ check_status(HTTParty.get("#{@base_route}/#{api_method}",
14
+ options.merge(@auth)))
15
+ end
16
+
17
+ def stats(**args)
18
+ if args.empty?
19
+ @stats
20
+ else
21
+ @stats = Qmetrics::Stats.new(args.merge({api: self}))
22
+ end
23
+ end
24
+
25
+ def realtime(**args)
26
+ if args.empty?
27
+ @realtime
28
+ else
29
+ @realtime = Qmetrics::Realtime.new(args.merge({api: self}))
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def check_status(r)
36
+ if r.response.code == "200"
37
+ r.parsed_response
38
+ else
39
+ raise(HTTPStatusError, r.response.code)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,63 @@
1
+ module Qmetrics
2
+ class Caller
3
+
4
+ class << self
5
+ attr_reader :api_methods
6
+ end
7
+
8
+ def initialize(queues: , api: )
9
+ @queues = queues
10
+ @api = api
11
+ clear_blocks
12
+ end
13
+
14
+ def get(*args)
15
+ clear_blocks
16
+ args.each do |k|
17
+ @blocks.push(api_methods[k.to_sym]) if call_exists?(k.to_sym)
18
+ end
19
+ execute
20
+ end
21
+
22
+ # url encoded '|' to '%7C'
23
+ def to_s
24
+ "/jsonStatsApi.do?queues=#{@queues.join('%7C')}"
25
+ end
26
+
27
+ def self.load_api_methods(file)
28
+ @api_methods ||= load_yml(file)
29
+ end
30
+
31
+ def api_methods
32
+ self.class.api_methods
33
+ end
34
+
35
+ private
36
+
37
+ def self.load_yml(file)
38
+ YAML.load_file(File.join(File.dirname(__FILE__),file))
39
+ end
40
+
41
+ def self.generate_api_methods
42
+ api_methods.each do |k, v|
43
+ define_method(k.to_sym) do
44
+ @blocks = [v]
45
+ execute
46
+ end
47
+ end
48
+ end
49
+
50
+ def execute
51
+ Qmetrics::Response.new(@api.call(to_s),api_methods)
52
+ end
53
+
54
+ def call_exists?(call)
55
+ api_methods.keys.include? call
56
+ end
57
+
58
+ def clear_blocks
59
+ @blocks = []
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,12 @@
1
+ module Qmetrics
2
+ class Realtime < Caller
3
+ load_api_methods("realtime_methods.yml")
4
+ generate_api_methods
5
+
6
+ def to_s
7
+ "/QmRealtime" + super +
8
+ @blocks.map {|b| "&block=#{b}"}.join
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ :queues_in_use: "RealtimeDO.RTRiassunto"
3
+ :calls_being_processed: "RealtimeDO.RTCallsBeingProc"
4
+ :agents_logged_in: "RealtimeDO.RTAgentsLoggedIn"
5
+ :wallboard_top_panel: "RealtimeDO.WallRiassunto"
6
+ :wall_calls_being_processed: "RealtimeDO.WallCallsBeingProc"
7
+ :visitor_calls_processed: "RealtimeDO.VisitorCallsProc"
8
+ :calls_taken: "RealtimeDO.VisitorTodaysOk"
9
+ :calls_lost: "RealtimeDO.VisitorTodaysKo"
10
+ :raw_agent_panel: "RealtimeDO.RtAgentsRaw"
11
+ :raw_calls_panel: "RealtimeDO.RtCallsRaw"
12
+
13
+
@@ -0,0 +1,65 @@
1
+ module Qmetrics
2
+ class Response
3
+ attr_reader :status, :description, :time_elapsed, :qmetrics_version, :result
4
+
5
+ def initialize(qmetrics_result,api_methods)
6
+ @api_methods = api_methods
7
+ @status = qmetrics_result["result"][0][1]
8
+ @description = qmetrics_result["result"][1][1]
9
+ @time_elapsed = "#{qmetrics_result["result"][2][1]}ms"
10
+ @qmetrics_version = qmetrics_result["result"][3][1]
11
+
12
+ qmetrics_result.delete("result")
13
+ @result = zip_results(qmetrics_result)
14
+ end
15
+
16
+ private
17
+
18
+ def zip_results(qmetrics_result)
19
+ @result = {}
20
+ qmetrics_result.each do |k, v|
21
+ @result[translate_method_name(k)] = zip_arrs(v)
22
+ end
23
+ @result
24
+ end
25
+
26
+ def translate_method_name(java_method_name)
27
+ @api_methods.invert[java_method_name]
28
+ end
29
+
30
+ def zip_arrs(r)
31
+ r.first.size > 2 ? clean_output(zip_keys_and_values(r)) : hashify_pairs(r)
32
+ end
33
+
34
+ def zip_keys_and_values(results)
35
+ h = purge_entities_arr(results.first)
36
+ results[1..results.size].inject([]) do |a, v|
37
+ a.push(Hash[h.zip(purge_entities_arr(v))])
38
+ end
39
+ end
40
+
41
+ def clean_output(output)
42
+ output.map { |n| n.select { |k, v| !(junk_data?(k) && junk_data?(v)) } }
43
+ end
44
+
45
+ def hashify_pairs(results)
46
+ results.inject({}) do |a, v|
47
+ a.merge(purge_entities(v.first) => purge_entities(v.last))
48
+ end
49
+ end
50
+
51
+ def purge_entities_arr(values)
52
+ values.map {|n| purge_entities(n) }
53
+ end
54
+
55
+ def purge_entities(value)
56
+ ['&nbsp;', '&lt;'].each{|t| value.gsub!(t,"")}
57
+ value.strip
58
+ end
59
+
60
+ def junk_data?(value)
61
+ ["...","","-"].include? value
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,20 @@
1
+ module Qmetrics
2
+ class Stats < Caller
3
+ load_api_methods("stats_methods.yml")
4
+ generate_api_methods
5
+
6
+ def initialize(from: , to: , **args)
7
+ super(args)
8
+ @from = from
9
+ @to = to
10
+ end
11
+
12
+ def to_s
13
+ "/QmStats" + super +
14
+ "&from=#{@from.strftime("%F.%H:%M:%S")}" \
15
+ "&to=#{@to.strftime("%F.%H:%M:%S")}" +
16
+ @blocks.map {|b| "&block=#{b}"}.join
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,86 @@
1
+ ---
2
+ :all_calls: "OkDO.RiassAllCalls"
3
+ :calls_within: "OkDO.RiassFullyWithin"
4
+ :agents_on_queue: "OkDO.AgentsOnQueue"
5
+ :service_level_agreement: "OkDO.ServiceLevelAgreement"
6
+ :disconnection_causes: "OkDO.DisconnectionCauses"
7
+ :transfers: "OkDO.Transfers"
8
+ :answered_calls_by_queue: "OkDO.AnsweredcallsByQueue"
9
+ :answered_calls_by_direction: "OkDO.AnsweredcallsByDirection"
10
+ :stints: "OkDO.StintsOk"
11
+ :initial_queue_positions: "OkDO.QPosOk"
12
+ :ivr_selections: "OkDO.IvrOk"
13
+ :dnis: "OkDO.DnisOk"
14
+ :music_on_hold_by_agent: "OkDO.MOHOk"
15
+ :report_header: "OkDO.HDRRpt"
16
+ :answered_calls_details: "DetailsDO.CallsOK"
17
+ :ivr_details: "DetailsDO.CallsIVR"
18
+ :all_unanswered_calls: "KoDO.ReportKoAll"
19
+ :unanswered_calls_within: "KoDO.ReportKoFully"
20
+ :disconnection_causes: "KoDO.DiscCauses"
21
+ :unanswered_by_queue: "KoDO.UnansByQueue"
22
+ :unanswered_outbound_calls: "KoDO.OutboundKo"
23
+ :unanswered_by_length: "KoDO.UnansByLen"
24
+ :inclusive_sla: "KoDO.InclusiveSLA"
25
+ :unanswered_by_key_press: "KoDO.ReportKoKeyPress"
26
+ :unanswered_stints: "KoDo.StintsKo"
27
+ :all_calls_by_stints: "KoDO.StintsOkKo"
28
+ :all_calls_initial_queue_position: "KoDO.QPosOkKo"
29
+ :lost_calls_ivr_selections: "KoDO.IvrKo"
30
+ :all_calls_ivr_selections: "KoDO.IvrOkKo"
31
+ :lost_calls_dnis: "KoDO.DnisKo"
32
+ :all_calls_dnis: "KoDO.DnisOkKo"
33
+ :call_overview: "KoDO.OverviewOkKo"
34
+ :inclusive_answered_sla: "KoDO.InclusiveAnswSLA"
35
+ :unanswered_calls_details: "DetailsDO.CallsKO"
36
+ :area_code_report: "AreaAnDO.Setup"
37
+ :answered_calls_by_area: "AreaAnDO.CallsKO"
38
+ :inbound_acd_call_attempts: "DistrDO.ReportAcd"
39
+ :acd_attempts_by_queue: "DistrDO.AcdByQueue"
40
+ :acd_attempts_by_terminal: "DistrDO.AcdByTerminals"
41
+ :answered_call_distribution_by_day: "CallDistrDO.AnsDistrPerDay"
42
+ :answered_call_wait_time_per_day: "CallDistrDO.AnsWaitPerDay"
43
+ :unanswered_call_wait_time_per_day: "CallDistrDO.UnansWaitPerDay"
44
+ :sales_per_day: "CallDistrDO.SalesPerDay"
45
+ :schedule_adherence_per_day: "CallDistrDO.StaffPerDay"
46
+ :queue_length_per_day: "CallDistrDO.QPosPerDay"
47
+ :inclusive_sla_per_day: "CallDistrDO.InclSlaPerDay"
48
+ :traffic_analysis_per_day: "CallDistrDO.TrafficAnPerDay"
49
+ :answered_call_distribution_per_hour: "CallDistrDO.AnsDistrPerHr"
50
+ :answered_call_wait_time_per_hour: "CallDistrDO.AnsWaitPerHr"
51
+ :unanswered_call_wait_time_per_hour: "CallDistrDO.UnansWaitPerHr"
52
+ :sales_per_hour: "CallDistrDO.SalesPerHr"
53
+ :schedule_adherence_per_hour: "CallDistrDO.StaffPerHr"
54
+ :queue_length_per_hour: "CallDistrDO.QPosPerHr"
55
+ :inclusive_sla_per_hour: "CallDistrDO.InclSlaPerHr"
56
+ :traffic_analysis_per_hour: "CallDistrDO.TrafficAnPerHr"
57
+ :answered_call_distribution_per_day_of_week: "CallDistrDO.AnsDistrPerDOW"
58
+ :answered_call_wait_time_per_day_of_week: "CallDistrDO.AnsWaitPerDOW"
59
+ :unanswered_call_wait_time_per_day_of_week: "CalldistrDO.UnansWaitPerDOW"
60
+ :sales_per_day_of_week: "CallDistrDO.SalesPerDOW"
61
+ :schedule_adherence_per_day_of_week: "CallDistrDO.StaffPerDOW"
62
+ :queue_length_per_day_of_week: "CallDistrDO.QPosPerDOW"
63
+ :inclusive_sla_per_day_of_week: "CallDistrDO.InclSlaPerDOW"
64
+ :traffic_analysis_per_day_of_week: "CallDistrDO.TrafficAnPerDOW"
65
+ :agent_session_detail: "AgentsDO.ReportAgents"
66
+ :session_and_pause_durations: "AgentsDO.SessionPauseDur"
67
+ :agent_availability: "AgentsDO.AgentAvail"
68
+ :answered_calls: "AgentsDO.AnsCallsQueues"
69
+ :answered_calls_by_custom_group: "AgentsDO.AnsCallsCG"
70
+ :answered_calls_by_location: "AgentsDO.AnsCallsLocation"
71
+ :answered_calls_by_service_group: "AgentsDO.AnsCallsSG"
72
+ :agent_performance_by_acd_group: "AgentsDO.PerformanceAcdGroups"
73
+ :agent_occupancy_report: "AgentsDO.AgentOccupancy"
74
+ :agent_payable_time_by_hour: "AgentsDO.AgentPayableTimeByHour"
75
+ :agent_billable_time_by_hour: "AgentsDO.AgentBillableTimeByHour"
76
+ :detail_of_agent_pauses: "DetailsDO.AgentPauses"
77
+ :outcomes: "OutcomesDO.GeneralRep"
78
+ :call_results_by_outcomes: "OutcomesDO.CallResByOutcome"
79
+ :billable_activities: "OutcomesDO.ActivBillable"
80
+ :non_billable_activities: "OutcomesDO.ActivNotBillable"
81
+ :detailed_agent_report: "OutcomesDO.AgentReportDetailed"
82
+ :outcomes_per_agent: "OutcomesDO.AgentOutcomes"
83
+ :ivr_traversals: "IvrDO.IvrReport"
84
+ :ivr_timing: "IvrDO.IvrTiming"
85
+ :ivr_goals: "IvrDO.IvrGoals"
86
+
@@ -0,0 +1,3 @@
1
+ module Qmetrics
2
+ VERSION = "0.1.3"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qmetrics/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "qmetrics"
8
+ spec.version = Qmetrics::VERSION
9
+ spec.authors = ["Kevin Collette"]
10
+ spec.email = ["kevcollette@gmail.com"]
11
+ spec.summary = %q{A gem that wraps the Queuemetrics JSON API with Ruby}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.2.0"
24
+ spec.add_runtime_dependency "httparty", "~> 0.13.3"
25
+ end
@@ -0,0 +1,53 @@
1
+ describe Qmetrics::API do
2
+
3
+ let(:api) { Qmetrics::API.new(@api_config.to_h) }
4
+
5
+ before :all do
6
+ @api_config = APIConfig.new
7
+ end
8
+
9
+ describe "#new" do
10
+ it "should return a new Qmetrics::API object" do
11
+ expect(api).to be_a(Qmetrics::API)
12
+ end
13
+ end
14
+
15
+ describe "#call" do
16
+ context "it is passed invalid auth credentials" do
17
+
18
+ it "should throw an exception" do
19
+ api_config = {server: @api_config.server,
20
+ port: @api_config.port,
21
+ user: "foo", pass: "bar" }
22
+ wrong_api = Qmetrics::API.new(api_config.to_h)
23
+ expect{wrong_api.call("agent/jsonEditorApi.do")}.to raise_exception("501")
24
+ end
25
+ end
26
+
27
+ context "it is passed an invalid api method" do
28
+ it "should throw an exception" do
29
+ expect{api.call("agt/jsonEditorApi.do")}.to raise_exception("500")
30
+ end
31
+ end
32
+
33
+ context "it is passed a valid Queuemetrics api method" do
34
+ it "should return an array" do
35
+ expect(api.call("agent/jsonEditorApi.do")).to be_an(Array)
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ describe "#stats" do
42
+ let(:q_stats) { { queues: [1],
43
+ from: Time.now-86400,
44
+ to: Time.now } }
45
+
46
+ it "should return a Qmetrics::Stats object" do
47
+ expect(api.stats(q_stats)).to be_an_instance_of(Qmetrics::Stats)
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
@@ -0,0 +1,5 @@
1
+ realtime_config = RealtimeConfig.new
2
+
3
+ describe Qmetrics::Realtime do
4
+ it_behaves_like 'a Qmetrics::Caller', realtime_config
5
+ end
@@ -0,0 +1,64 @@
1
+ describe Qmetrics::Response do
2
+
3
+ let(:api) { Qmetrics::API.new(@api_config.to_h)}
4
+ let(:stats) { api.stats(@stats_config.to_h) }
5
+ let(:response) { stats.get(:stints,:answered_calls,:all_calls) }
6
+
7
+ before :all do
8
+ @api_config = APIConfig.new
9
+ @stats_config = StatsConfig.new
10
+ end
11
+
12
+ describe "#result" do
13
+ it "should respond" do
14
+ expect{response.result}.not_to raise_exception
15
+ end
16
+
17
+ context "The result is for multiple agents" do
18
+ let(:result) { stats.answered_calls.result }
19
+
20
+ it "should be an Array of Hashes" do
21
+ expect(result[:answered_calls]).to be_an(Array)
22
+ expect(result[:answered_calls].first).to be_a(Hash)
23
+ end
24
+
25
+ end
26
+
27
+ context "The result is for all agents" do
28
+ let(:result) { stats.all_calls.result }
29
+
30
+ it "should be a Hash" do
31
+ expect(result[:all_calls]).to be_a(Hash)
32
+ end
33
+
34
+ end
35
+
36
+ it "should remove HTML character entities from output" do
37
+ result = stats.agent_payable_time_by_hour.result
38
+ result[:agent_payable_time_by_hour].each do |n|
39
+ n.each do |k,v|
40
+ expect(k).to_not include("&nbsp;")
41
+ expect(v).to_not include("&nbsp;")
42
+ expect(k).to_not include("&lt;")
43
+ expect(v).to_not include("&lt;")
44
+ end
45
+ end
46
+ end
47
+
48
+ it "should remove superflous key-value pairs" do
49
+ result = stats.unanswered_calls_details.result
50
+ junk = ["...","-",""]
51
+ result[:unanswered_calls_details].each do |n|
52
+ n.each do |k,v|
53
+ if junk.include?(k)
54
+ expect(junk).not_to include(v)
55
+ elsif junk.include?(v)
56
+ expect(junk).not_to include(k)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,7 @@
1
+ require 'support/shared_examples_for_caller'
2
+
3
+ stats_config = StatsConfig.new
4
+
5
+ describe Qmetrics::Stats do
6
+ it_behaves_like 'a Qmetrics::Caller', stats_config
7
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qmetrics do
4
+ it "should define its version" do
5
+ expect(Qmetrics::VERSION).not_to be_nil
6
+ end
7
+ end
8
+
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec'
4
+ require 'yaml'
5
+ require 'qmetrics'
6
+
7
+ Dir["./spec/support/**/*.rb"].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ config.order = 'random'
12
+ end
@@ -0,0 +1,17 @@
1
+ class APIConfig
2
+ attr_reader :server, :port, :user, :pass
3
+
4
+ def initialize
5
+ @api_config = YAML.load_file(File.join(File.dirname(__FILE__),
6
+ "api_config.yml"))
7
+ @server = @api_config[:server]
8
+ @port = @api_config[:port]
9
+ @user = @api_config[:user]
10
+ @pass = @api_config[:pass]
11
+ end
12
+
13
+ def to_h
14
+ @api_config
15
+ end
16
+
17
+ end
@@ -0,0 +1,18 @@
1
+ class RealtimeConfig
2
+ attr_reader :queues
3
+
4
+ def initialize
5
+ @realtime_config = YAML.load_file(File.join(File.dirname(__FILE__),
6
+ "realtime_config.yml"))
7
+ @api_config = APIConfig.new
8
+ @queues = @realtime_config[:queues]
9
+ @api = Qmetrics::API.new(@api_config.to_h)
10
+ end
11
+
12
+ def to_h
13
+ @realtime_config[:api] = @api
14
+ @realtime_config
15
+ end
16
+
17
+ end
18
+
@@ -0,0 +1,46 @@
1
+ RSpec.shared_examples 'a Qmetrics::Caller' do |config_obj|
2
+
3
+ caller = described_class.new(config_obj.to_h)
4
+
5
+ describe "#api_methods" do
6
+ it "should exist" do
7
+ expect{caller.api_methods}.not_to raise_exception
8
+ end
9
+ end
10
+
11
+ caller.api_methods.each do |k, v|
12
+ describe "##{k}" do
13
+ before :all do
14
+ @response = caller.public_send(k)
15
+ end
16
+
17
+ let(:response) { @response.dup }
18
+
19
+ it "should return an API Response" do
20
+ expect(response).to be_a(Qmetrics::Response)
21
+ end
22
+
23
+ it "should return a response with the API call's key" do
24
+ expect(response.result).to have_key(k)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "#get" do
30
+ let(:method) { caller.api_methods.first.first }
31
+ let(:method2) { caller.api_methods.take(2).last.first }
32
+ let(:response) { caller.get(method, method2) }
33
+ it "should return responses for all api methods passed to it." do
34
+ expect(response).to be_a(Qmetrics::Response)
35
+ expect(response.result).to have_key(method)
36
+ expect(response.result).to have_key(method2)
37
+ end
38
+ end
39
+
40
+ describe "#to_s" do
41
+ it "should return a string" do
42
+ expect(caller.to_s).to be_a(String)
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,22 @@
1
+ class StatsConfig
2
+ attr_reader :queues, :from, :to
3
+
4
+ def initialize
5
+ @stats_config = YAML.load_file(File.join(File.dirname(__FILE__),
6
+ "stats_config.yml"))
7
+ @api_config = APIConfig.new
8
+ @queues = @stats_config[:queues]
9
+ @from = Time.parse(@stats_config[:from])
10
+ @to = Time.parse(@stats_config[:to])
11
+ @api = Qmetrics::API.new(@api_config.to_h)
12
+ end
13
+
14
+ def to_h
15
+ @stats_config[:from] = @from
16
+ @stats_config[:to] = @to
17
+ @stats_config[:api] = @api
18
+ @stats_config
19
+ end
20
+
21
+ end
22
+
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qmetrics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Collette
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.13.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.13.3
69
+ description: ''
70
+ email:
71
+ - kevcollette@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".ruby-gemset"
79
+ - ".ruby-version"
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - lib/qmetrics.rb
85
+ - lib/qmetrics/api.rb
86
+ - lib/qmetrics/caller.rb
87
+ - lib/qmetrics/realtime.rb
88
+ - lib/qmetrics/realtime_methods.yml
89
+ - lib/qmetrics/response.rb
90
+ - lib/qmetrics/stats.rb
91
+ - lib/qmetrics/stats_methods.yml
92
+ - lib/qmetrics/version.rb
93
+ - qmetrics.gemspec
94
+ - spec/lib/qmetrics/api_spec.rb
95
+ - spec/lib/qmetrics/realtime_spec.rb
96
+ - spec/lib/qmetrics/response_spec.rb
97
+ - spec/lib/qmetrics/stats_spec.rb
98
+ - spec/lib/qmetrics/version_spec.rb
99
+ - spec/spec_helper.rb
100
+ - spec/support/api_config.rb
101
+ - spec/support/realtime_config.rb
102
+ - spec/support/shared_examples_for_caller.rb
103
+ - spec/support/stats_config.rb
104
+ homepage: ''
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: A gem that wraps the Queuemetrics JSON API with Ruby
128
+ test_files:
129
+ - spec/lib/qmetrics/api_spec.rb
130
+ - spec/lib/qmetrics/realtime_spec.rb
131
+ - spec/lib/qmetrics/response_spec.rb
132
+ - spec/lib/qmetrics/stats_spec.rb
133
+ - spec/lib/qmetrics/version_spec.rb
134
+ - spec/spec_helper.rb
135
+ - spec/support/api_config.rb
136
+ - spec/support/realtime_config.rb
137
+ - spec/support/shared_examples_for_caller.rb
138
+ - spec/support/stats_config.rb