qmetrics 0.1.3

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.
@@ -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