# frozen_string_literal: true module RSpec module Rails module Api module DSL # These methods will be available in examples (i.e.: 'for_code') module Example def visit(example, path_params: {}, payload: {}, headers: {}) # rubocop:disable Metrics/AbcSize raise 'Missing context. Call visit with for_code context.' unless example status_code = prepare_status_code example.class.description request_params = prepare_request_params example.class.module_parent.description, path_params, payload, headers send(request_params[:action], request_params[:url], params: request_params[:params].to_json, headers: request_params[:headers]) check_response(response, status_code) set_request_example example.class.metadata[:rrad], request_params, status_code, response.body end def defined(entity) current_resource = self.class.metadata[:rrad].current_resource raise '@current_resource is unset' unless current_resource entities = self.class.metadata[:rrad].resources[current_resource][:entities] out = entities[entity] raise "Unkown entity '#{entity}' in resource '#{current_resource}'" unless out out.expand_with(entities) end private def check_response(response, expected_code) expect(response.status).to eq expected_code expect(response.headers['Content-Type']).to eq 'application/json; charset=utf-8' if expected_code != 204 end def set_request_example(rrad_metadata, request_params, status_code = nil, response = nil) rrad_metadata.add_request_example(url: request_params[:example_url], action: request_params[:action], status_code: status_code, response: response, path_params: request_params[:path_params], params: request_params[:params]) end def prepare_request_params(description, request_params = {}, payload = {}, request_headers = {}) example_params = description.split ' ' { action: example_params[0].downcase, url: prepare_request_url(example_params[1], request_params), example_url: example_params[1], params: payload, headers: prepare_request_headers(request_headers), } end # Replace path params by values def prepare_request_url(url, request_params) url.gsub(/(?::(\w*))/) do |e| symbol = e.sub(':', '').to_sym if request_params.key?(symbol) request_params[symbol] elsif respond_to?(symbol) send(symbol) else puts "! Define #{symbol} (let(:#{symbol}){ value }) or pass it to 'visit'" end end end def prepare_request_headers(headers = {}) { 'Accept' => 'application/json', 'Content-Type' => 'application/json', }.merge headers end def prepare_status_code(description) code_match = /-> (\d+) - .*/.match description raise 'Please provide a numerical code for the "for_code" block' unless code_match code_match[1].to_i end end end end end end