1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# frozen_string_literal: true
module QA
module Vendor
module Smocker
class SmockerApi
include Scenario::Actable
include Support::API
DEFAULT_MOCK = <<~YAML
- request:
method: POST
path: /default
response:
headers:
Content-Type: application/json
body: '{}'
YAML
def initialize(host:, public_port: 8080, admin_port: 8081, tls: false)
@host = host
@public_port = public_port
@admin_port = admin_port
@scheme = tls ? "https" : "http"
end
# @return [String] Base url of mock endpoint
def base_url
@base_url ||= "#{scheme}://#{host}:#{public_port}"
end
# @return [String] Url of admin endpoint
def admin_url
@admin_url ||= "#{scheme}://#{host}:#{admin_port}"
end
# @param endpoint [String] path for mock endpoint
# @return [String] url for mock endpoint
def url(endpoint = 'default')
"#{base_url}/#{endpoint}"
end
# Waits for the smocker server to be ready
#
# @param wait [Integer] wait duration for smocker readiness
def wait_for_ready(wait: 10)
Support::Waiter.wait_until(max_duration: wait, reload_page: false, raise_on_failure: true) do
ready?
end
end
# Is smocker server ready for interaction?
#
# @return [Boolean]
def ready?
QA::Runtime::Logger.debug 'Checking Smocker readiness'
get("#{admin_url}/version")
true
# rescuing StandardError because RestClient::ExceptionWithResponse isn't propagating
rescue StandardError => e
QA::Runtime::Logger.debug "Smocker not ready yet \n #{e}"
false
end
# Clears mocks and history
#
# @param force [Boolean] remove locked mocks?
# @return [Boolean] reset was successful?
def reset(force: true)
response = post("#{admin_url}/reset?force=#{force}", {}.to_json)
parse_body(response)['message'] == 'Reset successful'
end
# Fetches an active session id from a name
#
# @param name [String] the name of the session
# @return [String] the unique session id
def get_session_id(name)
sessions = parse_body get("#{admin_url}/sessions/summary")
current = sessions.find do |session|
session[:name] == name
end
current&.dig(:id)
end
# Registers a mock to Smocker
# If a session name is provided, the mock will register to that session
# https://smocker.dev/technical-documentation/mock-definition.html
#
# @param yaml [String] the yaml representing the mock
# @param session [String] the session name for the mock
def register(yaml = DEFAULT_MOCK, session: nil)
query_params = build_params(session: session)
url = "#{admin_url}/mocks?#{query_params}"
headers = { 'Content-Type' => 'application/x-yaml' }
response = post(url, yaml, headers: headers)
parse_body(response)
end
# Fetches call history for a mock
#
# @param session_name [String] the session name for the mock
# @return [Array<HistoryResponse>]
def history(session_name = nil)
query_params = session_name ? build_params(session: get_session_id(session_name)) : ''
response = get("#{admin_url}/history?#{query_params}")
body = parse_body(response)
raise body[:message] unless body.is_a?(Array)
body.map do |entry|
HistoryResponse.new(entry)
end
end
private
attr_reader :host, :public_port, :admin_port, :scheme
def build_params(**args)
args.each_with_object([]) do |(k, v), memo|
memo << "#{k}=#{v}" if v
end.join("&")
end
end
end
end
end
|