summaryrefslogtreecommitdiff
path: root/qa/qa/vendor/smocker
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/vendor/smocker')
-rw-r--r--qa/qa/vendor/smocker/event_payload.rb49
-rw-r--r--qa/qa/vendor/smocker/history_response.rb52
-rw-r--r--qa/qa/vendor/smocker/smocker_api.rb140
3 files changed, 241 insertions, 0 deletions
diff --git a/qa/qa/vendor/smocker/event_payload.rb b/qa/qa/vendor/smocker/event_payload.rb
new file mode 100644
index 00000000000..4bf154b76c2
--- /dev/null
+++ b/qa/qa/vendor/smocker/event_payload.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Smocker
+ class EventPayload
+ def initialize(hook_data)
+ @hook_data = hook_data
+ end
+
+ def raw
+ @hook_data
+ end
+
+ def event
+ raw[:object_kind]&.to_sym
+ end
+
+ def project_name
+ raw.dig(:project, :name)
+ end
+
+ def mr?
+ event == :merge_request
+ end
+
+ def issue?
+ event == :issue
+ end
+
+ def note?
+ event == :note
+ end
+
+ def push?
+ event == :push
+ end
+
+ def tag?
+ event == :tag
+ end
+
+ def wiki?
+ event == :wiki_page
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/smocker/history_response.rb b/qa/qa/vendor/smocker/history_response.rb
new file mode 100644
index 00000000000..53d5759ef8b
--- /dev/null
+++ b/qa/qa/vendor/smocker/history_response.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require_relative './event_payload'
+require 'time'
+
+module QA
+ module Vendor
+ module Smocker
+ class HistoryResponse
+ attr_reader :payload
+
+ def initialize(payload)
+ @payload = payload
+ end
+
+ # Smocker context including call counter
+ def context
+ payload[:context]
+ end
+
+ # Smocker request data
+ def request
+ payload[:request]
+ end
+
+ # @return [EventPayload] the request body as a webhook event
+ def as_hook_event
+ body = request&.dig(:body)
+ EventPayload.new body if body
+ end
+
+ # @return [Time] Time request was recieved
+ def received
+ date = request&.dig(:date)
+ Time.parse date if date
+ end
+
+ # Find time elapsed since <target>
+ #
+ # @param target [Time] target time
+ # @return [Integer] seconds elapsed since <target>
+ def elapsed(target)
+ (received.to_f - target.to_f).round if received
+ end
+
+ def response
+ payload[:response]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/smocker/smocker_api.rb b/qa/qa/vendor/smocker/smocker_api.rb
new file mode 100644
index 00000000000..3f595b58886
--- /dev/null
+++ b/qa/qa/vendor/smocker/smocker_api.rb
@@ -0,0 +1,140 @@
+# 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
+
+ # @param wait [Integer] seconds to wait for server
+ # @yieldparam [SmockerApi] the api object ready for interaction
+ def self.init(**wait_args)
+ if @container.nil?
+ @container = Service::DockerRun::Smocker.new
+ @container.register!
+ @container.wait_for_running
+ end
+
+ yield new(@container, **wait_args)
+ end
+
+ def self.teardown!
+ @container&.remove!
+ end
+
+ def initialize(container, **wait_args)
+ @container = container
+ wait_for_ready(**wait_args)
+ end
+
+ # @return [String] Base url of mock endpoint
+ def base_url
+ @container.base_url
+ end
+
+ # @return [String] Url of admin endpoint
+ def admin_url
+ @container.admin_url
+ 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
+
+ def build_params(**args)
+ args.each_with_object([]) do |(k, v), memo|
+ memo << "#{k}=#{v}" if v
+ end.join("&")
+ end
+ end
+ end
+ end
+end