hephaestus 0.6.4 → 0.7.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -22
- data/README.md +169 -6
- data/bin/hephaestus +20 -3
- data/lib/Rakefile +10 -0
- data/lib/hephaestus/engine.rb +72 -0
- data/lib/hephaestus/http.rb +36 -0
- data/lib/hephaestus/middleware/malformed_request.rb +100 -0
- data/lib/hephaestus/middleware/openapi_validation.rb +89 -0
- data/lib/hephaestus/middleware/tracing_attributes.rb +50 -0
- data/lib/hephaestus/middleware.rb +7 -0
- data/lib/hephaestus/support/hephaestus/api.rb +105 -0
- data/lib/hephaestus/support/hephaestus/webmocks/browser_webmock.rb +21 -0
- data/lib/hephaestus/support/hephaestus/webmocks/slack_webmock.rb +21 -0
- data/lib/hephaestus/support/hephaestus/webmocks/yetto_webmock.rb +195 -0
- data/lib/hephaestus/support/rails.rb +35 -0
- data/lib/hephaestus/test_helper.rb +45 -0
- data/lib/hephaestus/version.rb +2 -2
- data/lib/hephaestus.rb +1 -0
- data/lib/tasks/hephaestus_tasks.rake +7 -0
- data/lib/tasks/package.rake +9 -0
- data/lib/tasks/rubocop.rake +6 -0
- data/lib/version.rb +6 -0
- data/templates/app/controllers/app_controller.rb +1 -0
- data/templates/app/controllers/application_controller.rb +2 -101
- data/templates/app/jobs/update_yetto_job.rb +1 -1
- data/templates/app/services/yetto_service.rb +2 -2
- data/templates/script/hmac_text +1 -1
- data/templates/test/jobs/update_yetto_job_test.rb +1 -1
- data/templates/test/support/webmocks/yetto_webmock.rb +5 -5
- metadata +330 -12
@@ -0,0 +1,89 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "openapi_first"
|
5
|
+
|
6
|
+
module Hephaestus
|
7
|
+
module Middleware
|
8
|
+
class OpenapiValidation
|
9
|
+
API_PATH_PREFIX = "/api/"
|
10
|
+
API_SPEC_PATH = Rails.root.join("lib/schemas/api/2023-03-06/openapi.json")
|
11
|
+
|
12
|
+
def initialize(app, ignore_path: "/settings", match_path: API_PATH_PREFIX, limit_methods_to: nil, spec: API_SPEC_PATH)
|
13
|
+
@app = app
|
14
|
+
@ignore_path = ignore_path
|
15
|
+
@match_path = match_path
|
16
|
+
@limit_methods_to = limit_methods_to
|
17
|
+
@spec = OpenapiFirst.load(spec)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
request = Rack::Request.new(env)
|
22
|
+
|
23
|
+
return @app.call(env) if request.path.include?(@ignore_path)
|
24
|
+
return @app.call(env) unless request.path.starts_with?(@match_path)
|
25
|
+
|
26
|
+
return @app.call(env) if @limit_methods_to.present? && @limit_methods_to.exclude?(request.request_method)
|
27
|
+
|
28
|
+
begin
|
29
|
+
# force content-type to JSON
|
30
|
+
env["CONTENT_TYPE"] = "application/json" if env["CONTENT_TYPE"] != "application/json"
|
31
|
+
|
32
|
+
validated_request = @spec.validate_request(request)
|
33
|
+
|
34
|
+
return @app.call(env) if validated_request.valid?
|
35
|
+
|
36
|
+
case validated_request.error
|
37
|
+
when OpenapiFirst::Schema::ValidationError
|
38
|
+
error_arr = format_arr(validated_request.error.errors.map(&:message))
|
39
|
+
Rails.logger.error(error_arr) if print_user_api_errors?
|
40
|
+
[Hephaestus::HTTP::BAD_REQUEST_I, { "Content-Type" => "application/json" }, [error_arr]]
|
41
|
+
else
|
42
|
+
case validated_request.error.type
|
43
|
+
when :not_found
|
44
|
+
[Hephaestus::HTTP::NOT_FOUND_I, { "Content-Type" => "application/json" }, [format_str("Not Found")]]
|
45
|
+
else
|
46
|
+
error_message = if validated_request.error.errors.present?
|
47
|
+
format_arr(validated_request.error.errors.map(&:message))
|
48
|
+
else
|
49
|
+
format_str(validated_request.error.message)
|
50
|
+
end
|
51
|
+
|
52
|
+
Rails.logger.error(error_message) if print_user_api_errors?
|
53
|
+
[Hephaestus::HTTP::BAD_REQUEST_I, { "Content-Type" => "application/json" }, [error_message]]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
rescue StandardError => e
|
57
|
+
raise e unless Rails.env.production?
|
58
|
+
|
59
|
+
Rails.logger.error(
|
60
|
+
"openapi.request_validation.error",
|
61
|
+
path: request.path,
|
62
|
+
method: request.env["REQUEST_METHOD"],
|
63
|
+
error_message: e.message,
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private def format_str(error)
|
69
|
+
{
|
70
|
+
errors: [
|
71
|
+
{
|
72
|
+
message: error,
|
73
|
+
},
|
74
|
+
],
|
75
|
+
}.to_json
|
76
|
+
end
|
77
|
+
|
78
|
+
private def format_arr(errors)
|
79
|
+
{
|
80
|
+
errors: errors.each_with_object([]) do |error, arr|
|
81
|
+
arr << {
|
82
|
+
message: error,
|
83
|
+
}
|
84
|
+
end,
|
85
|
+
}.to_json
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "opentelemetry"
|
5
|
+
require "active_support/parameter_filter"
|
6
|
+
|
7
|
+
module Hephaestus
|
8
|
+
module Middleware
|
9
|
+
class TracingAttributes
|
10
|
+
attr_reader :app
|
11
|
+
|
12
|
+
HTTP_REQUEST_CONTENT_LENGTH = "http.request_content_length"
|
13
|
+
HTTP_REQUEST_BODY = "http.request.body"
|
14
|
+
|
15
|
+
def initialize(app)
|
16
|
+
@app = app
|
17
|
+
@filterer = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
request = ActionDispatch::Request.new(env.dup)
|
22
|
+
|
23
|
+
OpenTelemetry::Trace.current_span.add_attributes({
|
24
|
+
"version" => Hephaestus::Engine::GIT_SHA,
|
25
|
+
HTTP_REQUEST_CONTENT_LENGTH => env["CONTENT_LENGTH"].to_i,
|
26
|
+
HTTP_REQUEST_BODY => process_tracing_body(request),
|
27
|
+
})
|
28
|
+
|
29
|
+
app.call(env)
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_tracing_body(request)
|
33
|
+
if Rails.configuration.respond_to?(:tracing_body_filters)
|
34
|
+
Rails.configuration.tracing_body_filters.each do |path, filter|
|
35
|
+
next unless request.path.starts_with?(path)
|
36
|
+
|
37
|
+
result = filter.call(request)
|
38
|
+
|
39
|
+
return result if result.is_a?(String)
|
40
|
+
|
41
|
+
return result.to_json
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
params = request.params
|
46
|
+
@filterer.filter(params).to_json
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hephaestus
|
5
|
+
module API
|
6
|
+
module TestHelpers
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
def plug(method, path, headers: {}, version: Rails.configuration.yetto_api_version, body: {}, parse: true)
|
10
|
+
prepended_path = prepend_plug_path(version, path)
|
11
|
+
|
12
|
+
http_call(method, prepended_path, headers: headers, version: version, body: body, parse: true)
|
13
|
+
end
|
14
|
+
|
15
|
+
def api(method, path, headers: {}, version: Rails.configuration.yetto_api_version, body: {}, parse: true)
|
16
|
+
prepended_path = prepend_api_path(version, path)
|
17
|
+
|
18
|
+
http_call(method, prepended_path, headers: headers, version: version, body: body, parse: true)
|
19
|
+
end
|
20
|
+
|
21
|
+
def http_call(method, path, headers: {}, version: nil, body: {}, parse: true)
|
22
|
+
# explicitly assert headers cannot be nil
|
23
|
+
if headers.nil?
|
24
|
+
send(method, path, body.to_json)
|
25
|
+
else
|
26
|
+
headers["HTTP_ACCEPT"] ||= headers.fetch("HTTP_ACCEPT", "application/json")
|
27
|
+
headers["CONTENT_TYPE"] ||= headers.fetch("CONTENT_TYPE", "application/json")
|
28
|
+
body = body.to_json if headers["CONTENT_TYPE"] == "application/json"
|
29
|
+
send(method, path, body, headers)
|
30
|
+
end
|
31
|
+
|
32
|
+
JSON.parse(last_response.body) if last_response.body.present? && parse
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_response(expected_status, expected_body = nil)
|
36
|
+
expected_status = case expected_status
|
37
|
+
when :ok, :okay
|
38
|
+
Hephaestus::HTTP::OK_I
|
39
|
+
when :created
|
40
|
+
Hephaestus::HTTP::CREATED_I
|
41
|
+
when :no_content
|
42
|
+
Hephaestus::HTTP::NO_CONTENT_I
|
43
|
+
when :redirect
|
44
|
+
Hephaestus::HTTP::FOUND_I
|
45
|
+
when :bad_request
|
46
|
+
Hephaestus::HTTP::BAD_REQUEST_I
|
47
|
+
when :unauthorized
|
48
|
+
Hephaestus::HTTP::UNAUTHORIZED_I
|
49
|
+
when :forbidden
|
50
|
+
Hephaestus::HTTP::FORBIDDEN_I
|
51
|
+
when :not_found
|
52
|
+
Hephaestus::HTTP::NOT_FOUND_I
|
53
|
+
when :not_acceptable
|
54
|
+
Hephaestus::HTTP::NOT_ACCEPTABLE_I
|
55
|
+
when :service_unavailable
|
56
|
+
Hephaestus::HTTP::SERVICE_UNAVAILABLE_I
|
57
|
+
else
|
58
|
+
raise ArgumentError, "Unknown status: #{expected_status}"
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_equal(expected_status, last_response.status)
|
62
|
+
end
|
63
|
+
|
64
|
+
def prepend_plug_path(version, path)
|
65
|
+
"/#{plug_shortname}/#{version}#{path}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def prepend_api_path(version, path)
|
69
|
+
"/api/#{version}#{path}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def headers(event, body)
|
73
|
+
case event
|
74
|
+
when :after_create
|
75
|
+
{
|
76
|
+
Hephaestus::Headers::HEADER_EVENT => "after_create",
|
77
|
+
Hephaestus::Headers::HEADER_RECORD_TYPE => "plug_installation",
|
78
|
+
}
|
79
|
+
when :after_update_plug_installation
|
80
|
+
{
|
81
|
+
Hephaestus::Headers::HEADER_EVENT => "after_update",
|
82
|
+
Hephaestus::Headers::HEADER_RECORD_TYPE => "plug_installation",
|
83
|
+
}
|
84
|
+
when :after_update_inbox
|
85
|
+
{
|
86
|
+
Hephaestus::Headers::HEADER_EVENT => "after_update",
|
87
|
+
Hephaestus::Headers::HEADER_RECORD_TYPE => "inbox",
|
88
|
+
}
|
89
|
+
when :after_update_organization
|
90
|
+
{
|
91
|
+
Hephaestus::Headers::HEADER_EVENT => "after_update",
|
92
|
+
Hephaestus::Headers::HEADER_RECORD_TYPE => "organization",
|
93
|
+
}
|
94
|
+
when :after_destroy_plug_installation
|
95
|
+
{
|
96
|
+
Hephaestus::Headers::HEADER_EVENT => "after_destroy",
|
97
|
+
Hephaestus::Headers::HEADER_RECORD_TYPE => "plug_installation",
|
98
|
+
}
|
99
|
+
else
|
100
|
+
{}
|
101
|
+
end.merge(Hephaestus::Headers::HEADER_SIGNATURE => yetto_auth_header(body))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hephaestus
|
5
|
+
module Webmocks
|
6
|
+
module BrowserWebmock
|
7
|
+
def browser_mock(status: 200)
|
8
|
+
browser_mock = Object.new
|
9
|
+
Ferrum::Browser.stubs(:new).returns(browser_mock)
|
10
|
+
browser_mock.stubs(:go_to)
|
11
|
+
browser_mock.stubs(:quit)
|
12
|
+
response_mock = Ferrum::Network::Response.new("", "")
|
13
|
+
response_mock.stubs(:wait_for_idle).returns(true)
|
14
|
+
network_response_mock = Object.new
|
15
|
+
browser_mock.stubs(:network).returns(network_response_mock)
|
16
|
+
network_response_mock.stubs(:response).returns(response_mock)
|
17
|
+
response_mock.stubs(:status).returns(status)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hephaestus
|
5
|
+
module Webmocks
|
6
|
+
module SlackWebmock
|
7
|
+
def assert_requested_send_to_slack_log
|
8
|
+
assert_requested(:post, "https://slack.com/the_log_room")
|
9
|
+
end
|
10
|
+
|
11
|
+
def stub_send_to_slack_log
|
12
|
+
stub_request(:post, "https://slack.com/the_log_room")
|
13
|
+
.to_return(
|
14
|
+
status: 200,
|
15
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
16
|
+
body: {}.to_json,
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hephaestus
|
5
|
+
module Webmocks
|
6
|
+
module YettoWebmock
|
7
|
+
def yetto_auth_header(payload, signing_secret = SIGNING_SECRET)
|
8
|
+
"sha256=#{OpenSSL::HMAC.hexdigest(Hephaestus::ValidatesFromYetto::SHA256_DIGEST, signing_secret, payload.to_json)}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_requested_post_access_token(plug_installation_id, times: 1)
|
12
|
+
assert_requested(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens", times: times)
|
13
|
+
end
|
14
|
+
|
15
|
+
def stub_post_access_token(plug_installation_id)
|
16
|
+
response = {
|
17
|
+
token: Faker::Alphanumeric.alphanumeric(number: 26).upcase,
|
18
|
+
}
|
19
|
+
|
20
|
+
stub_request(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens")
|
21
|
+
.to_return(
|
22
|
+
body: response.to_json,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_requested_get_plug_installation(plug_installation_id, times: 1)
|
27
|
+
assert_requested(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}", times:)
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_get_plug_installation(plug_installation_id, response: {}, status: 200)
|
31
|
+
stub_request(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
|
32
|
+
.to_return(
|
33
|
+
status: status,
|
34
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
35
|
+
body: response.to_json,
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_requested_update_plug_installation(plug_installation_id)
|
40
|
+
assert_requested(:patch, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_not_requested_update_plug_installation(plug_installation_id)
|
44
|
+
assert_requested(:patch, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}", times: 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
def stub_update_plug_installation(plug_installation_id, params, response: {}, status: 200)
|
48
|
+
stub_post_access_token(plug_installation_id)
|
49
|
+
|
50
|
+
response[:plug_installation] = { id: plug_installation_id }
|
51
|
+
|
52
|
+
stub_request(:patch, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
|
53
|
+
.with(
|
54
|
+
body: params,
|
55
|
+
)
|
56
|
+
.to_return(
|
57
|
+
status: status,
|
58
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
59
|
+
body: response.to_json,
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def assert_requested_create_conversation(plug_installation_id, inbox_id)
|
64
|
+
assert_requested(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/conversations")
|
65
|
+
end
|
66
|
+
|
67
|
+
def stub_create_conversation(plug_installation_id, inbox_id, payload, response: {})
|
68
|
+
stub_post_access_token(plug_installation_id)
|
69
|
+
|
70
|
+
response[:plug_installation] = { id: plug_installation_id }
|
71
|
+
|
72
|
+
stub_request(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/conversations")
|
73
|
+
.with(
|
74
|
+
body: payload,
|
75
|
+
)
|
76
|
+
.to_return(
|
77
|
+
status: 200,
|
78
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
79
|
+
body: response.to_json,
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def assert_requested_get_plug_installations(filter: "")
|
84
|
+
assert_requested(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/plug/installations?#{filter}")
|
85
|
+
end
|
86
|
+
|
87
|
+
def stub_get_plug_installations(response, status: 200, filter: "")
|
88
|
+
stub_request(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/plug/installations?#{filter}")
|
89
|
+
.to_return(
|
90
|
+
status: status,
|
91
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
92
|
+
body: response.to_json,
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def assert_requested_get_messages_in_inbox(plug_installation_id, inbox_id, filter: "")
|
97
|
+
assert_requested(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/messages?#{filter}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def stub_get_messages_in_inbox(plug_installation_id, inbox_id, response, filter: "")
|
101
|
+
stub_post_access_token(plug_installation_id)
|
102
|
+
stub_request(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/messages?#{filter}")
|
103
|
+
.to_return(
|
104
|
+
status: 200,
|
105
|
+
body: response.to_json,
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def assert_requested_get_messages_in_conversation(plug_installation_id, conversation_id, filter: "")
|
110
|
+
assert_requested(:get, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages?#{filter}")
|
111
|
+
end
|
112
|
+
|
113
|
+
def stub_get_messages_in_conversation(plug_installation_id, conversation_id, response, status: 200, filter: "")
|
114
|
+
stub_post_access_token(plug_installation_id)
|
115
|
+
|
116
|
+
stub_request(:get, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages?#{filter}")
|
117
|
+
.to_return(
|
118
|
+
status: status,
|
119
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
120
|
+
body: response.to_json,
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def stub_add_message_to_conversation(plug_installation_id, conversation_id, payload, response: {}, status: 200)
|
125
|
+
stub_post_access_token(plug_installation_id)
|
126
|
+
|
127
|
+
response[:plug_installation] = { id: plug_installation_id }
|
128
|
+
|
129
|
+
stub_request(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages")
|
130
|
+
.with(
|
131
|
+
body: payload,
|
132
|
+
)
|
133
|
+
.to_return(
|
134
|
+
status: status,
|
135
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
136
|
+
body: response.to_json,
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def assert_requested_add_message_to_conversation(plug_installation_id, conversation_id)
|
141
|
+
assert_requested(:post, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages")
|
142
|
+
end
|
143
|
+
|
144
|
+
def assert_requested_create_message(plug_installation_id, message_id)
|
145
|
+
assert_requested(:post, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}/replies")
|
146
|
+
end
|
147
|
+
|
148
|
+
def stub_create_message(plug_installation_id, message_id, payload)
|
149
|
+
stub_post_access_token(plug_installation_id)
|
150
|
+
|
151
|
+
stub_request(:post, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}/replies")
|
152
|
+
.with(
|
153
|
+
body: payload,
|
154
|
+
)
|
155
|
+
.to_return(
|
156
|
+
status: 200,
|
157
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
158
|
+
body: {}.to_json,
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
def assert_requested_update_message(plug_installation_id, message_id)
|
163
|
+
assert_requested(:patch, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}")
|
164
|
+
end
|
165
|
+
|
166
|
+
def stub_update_message(plug_installation_id, message_id, payload)
|
167
|
+
stub_post_access_token(plug_installation_id)
|
168
|
+
stub_request(:patch, "#{::Hephaestus::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}")
|
169
|
+
.with(
|
170
|
+
body: payload,
|
171
|
+
)
|
172
|
+
.to_return(
|
173
|
+
status: 200,
|
174
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
175
|
+
body: {}.to_json,
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
def assert_requested_find_message_in_conversation_by_metadata(plug_installation_id, conversation_id)
|
180
|
+
assert_requested(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages?#{filter}")
|
181
|
+
end
|
182
|
+
|
183
|
+
def stub_find_message_in_conversation(plug_installation_id, conversation_id, response, status: 200, filter: "")
|
184
|
+
stub_post_access_token(plug_installation_id)
|
185
|
+
|
186
|
+
stub_request(:get, "#{Hephaestus::YettoService::YETTO_API_VERSION_TLD}/conversations/#{conversation_id}/messages?#{filter}")
|
187
|
+
.to_return(
|
188
|
+
status: status,
|
189
|
+
headers: { content_type: "application/json; charset=utf-8" },
|
190
|
+
body: response.to_json,
|
191
|
+
)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module ActiveSupport
|
5
|
+
class TestCase
|
6
|
+
# Run tests in parallel with specified workers
|
7
|
+
parallelize(workers: :number_of_processors)
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@organization_id ||= "org_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
11
|
+
@plug_installation_id ||= "pli_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
12
|
+
@inbox_id ||= "ibx_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
13
|
+
@plug_id ||= "plg_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
14
|
+
@message_id ||= "msg_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
15
|
+
@conversation_id ||= "cnv_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def file_fixture_path(dir, name)
|
19
|
+
Rails.root.join("test", "fixtures", "files", dir, name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_expected_args(expected_args)
|
23
|
+
lambda do |job_args_arr|
|
24
|
+
job_args_arr.first.each do |actual_args|
|
25
|
+
actual_key = actual_args.first
|
26
|
+
actual_value = actual_args.second
|
27
|
+
|
28
|
+
expected_value = expected_args[actual_key]
|
29
|
+
|
30
|
+
assert_equal(expected_value, actual_value, "Expected `#{actual_key}` to be `#{expected_value.nil? ? "nil" : expected_value}`, but was `#{actual_value.nil? ? "nil" : actual_value}`")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
ENV["RAILS_ENV"] ||= "test"
|
5
|
+
|
6
|
+
require_relative File.join($LOAD_PATH.last, "..", "config", "environment.rb")
|
7
|
+
|
8
|
+
module Hephaestus
|
9
|
+
module TestHelper
|
10
|
+
require "minitest/autorun"
|
11
|
+
require "minitest/pride"
|
12
|
+
|
13
|
+
require "debug" if ENV.fetch("DEBUG", false)
|
14
|
+
|
15
|
+
if ENV["COVERAGE"] == "1"
|
16
|
+
require "simplecov"
|
17
|
+
require "simplecov-console"
|
18
|
+
|
19
|
+
SimpleCov.start("rails")
|
20
|
+
|
21
|
+
# do not crash on failure; we want a distinct job to report the coverage error
|
22
|
+
module SimpleCov
|
23
|
+
class << self
|
24
|
+
def result_exit_status(_)
|
25
|
+
SimpleCov::ExitCodes::SUCCESS
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require "webmock"
|
32
|
+
require "httpx/adapters/webmock"
|
33
|
+
require "webmock/minitest"
|
34
|
+
WebMock.enable!
|
35
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
36
|
+
|
37
|
+
require_relative "support/rails"
|
38
|
+
|
39
|
+
# Load everything else from engine's test/support
|
40
|
+
Dir[File.expand_path("support/hephaestus/**/*.rb", __dir__)].each { |rb| require(rb) }
|
41
|
+
|
42
|
+
# https://github.com/freerange/mocha#rails
|
43
|
+
require "mocha/minitest"
|
44
|
+
end
|
45
|
+
end
|
data/lib/hephaestus/version.rb
CHANGED
data/lib/hephaestus.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "rubygems/package_task"
|
5
|
+
|
6
|
+
GEMSPEC = Bundler.load_gemspec(File.join(__dir__, "..", "..", "hephaestus.gemspec")) unless defined?(GEMSPEC)
|
7
|
+
gem_path = Gem::PackageTask.new(GEMSPEC).define
|
8
|
+
desc "Package the ruby gem"
|
9
|
+
task "package" => [gem_path]
|
data/lib/version.rb
ADDED