hephaestus 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +13 -0
  4. data/LICENSE.txt +9 -0
  5. data/README.md +19 -0
  6. data/bin/hephaestus +55 -0
  7. data/lib/hephaestus/actions/strip_comments_action.rb +263 -0
  8. data/lib/hephaestus/actions.rb +116 -0
  9. data/lib/hephaestus/app_builder.rb +168 -0
  10. data/lib/hephaestus/exit_on_failure.rb +22 -0
  11. data/lib/hephaestus/generators/app_generator.rb +158 -0
  12. data/lib/hephaestus/generators/base.rb +65 -0
  13. data/lib/hephaestus/generators/config_generator.rb +102 -0
  14. data/lib/hephaestus/generators/core_generator.rb +50 -0
  15. data/lib/hephaestus/generators/deployment_generator.rb +18 -0
  16. data/lib/hephaestus/generators/lib_generator.rb +16 -0
  17. data/lib/hephaestus/generators/license_generator.rb +16 -0
  18. data/lib/hephaestus/generators/rubocop_generator.rb +18 -0
  19. data/lib/hephaestus/generators/sorbet_generator.rb +16 -0
  20. data/lib/hephaestus/version.rb +11 -0
  21. data/lib/hephaestus.rb +21 -0
  22. data/templates/Gemfile.erb +121 -0
  23. data/templates/Procfile.debug +2 -0
  24. data/templates/Procfile.dev +2 -0
  25. data/templates/README.md.erb +1 -0
  26. data/templates/app/controllers/application_controller.rb +107 -0
  27. data/templates/app/controllers/concerns/authable.rb +32 -0
  28. data/templates/app/controllers/root_controller.rb +11 -0
  29. data/templates/app/controllers/settings_controller.rb +7 -0
  30. data/templates/app/controllers/staff_controller.rb +15 -0
  31. data/templates/app/controllers/yetto_controller.rb +30 -0
  32. data/templates/app/jobs/application_job.rb +10 -0
  33. data/templates/app/jobs/update_yetto_job.rb +27 -0
  34. data/templates/app/lib/body_parameter/yetto_parameters.rb +8 -0
  35. data/templates/app/lib/body_parameter.rb +6 -0
  36. data/templates/app/lib/constants/app.rb +8 -0
  37. data/templates/app/lib/headers/yetto.rb +17 -0
  38. data/templates/app/lib/headers.rb +5 -0
  39. data/templates/app/lib/path_parameter/yetto_parameters.rb +25 -0
  40. data/templates/app/lib/path_parameter.rb +8 -0
  41. data/templates/app/lib/plug_app/http.rb +34 -0
  42. data/templates/app/lib/plug_app/middleware/malformed_request.rb +110 -0
  43. data/templates/app/lib/plug_app/middleware/not_found.rb +41 -0
  44. data/templates/app/lib/plug_app/middleware/openapi_validation.rb +54 -0
  45. data/templates/app/lib/plug_app/middleware/tracing_attributes.rb +42 -0
  46. data/templates/app/lib/query_parameter.rb +6 -0
  47. data/templates/app/serializers/error_serializer.rb +16 -0
  48. data/templates/app/services/yetto_service.rb +61 -0
  49. data/templates/app/views/settings/index.json.jbuilder +15 -0
  50. data/templates/config/initializers/cors.rb +18 -0
  51. data/templates/config/initializers/environment.rb +30 -0
  52. data/templates/config/initializers/filter_parameter_logging.rb +22 -0
  53. data/templates/config/initializers/inflections.rb +20 -0
  54. data/templates/config/initializers/lograge.rb +25 -0
  55. data/templates/config/initializers/open_telemetry.rb +27 -0
  56. data/templates/config/initializers/sidekiq.rb +11 -0
  57. data/templates/config/initializers/slack_webhook_logger.rb +17 -0
  58. data/templates/config/sidekiq.yml +18 -0
  59. data/templates/hephaestus_gitignore +296 -0
  60. data/templates/lib/plug_app/schemas/api/2023-03-06/components/parameters/headers/yetto.json +42 -0
  61. data/templates/lib/plug_app/schemas/api/2023-03-06/components/parameters/plugInstallation.json +12 -0
  62. data/templates/lib/plug_app/schemas/api/2023-03-06/components/schemas/plug.json +9 -0
  63. data/templates/lib/plug_app/schemas/api/2023-03-06/components/schemas/responses.json +64 -0
  64. data/templates/lib/plug_app/schemas/api/2023-03-06/components/schemas/yetto.json +1 -0
  65. data/templates/lib/plug_app/schemas/api/2023-03-06/openapi.json +27 -0
  66. data/templates/lib/plug_app/schemas/api/2023-03-06/paths/plug.json +91 -0
  67. data/templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/after_create_message.json +41 -0
  68. data/templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/after_create_plug_installation.json +41 -0
  69. data/templates/lib/tasks/test_tasks.rake +10 -0
  70. data/templates/script/ci +7 -0
  71. data/templates/script/hmac_text +22 -0
  72. data/templates/script/licenses +51 -0
  73. data/templates/script/ngrok +5 -0
  74. data/templates/script/security_checks/brakeman +5 -0
  75. data/templates/script/security_checks/bundle-audit +5 -0
  76. data/templates/script/server +5 -0
  77. data/templates/script/server-debug +5 -0
  78. data/templates/script/test +5 -0
  79. data/templates/script/typecheck +42 -0
  80. data/templates/sorbet/custom.rbi +14 -0
  81. data/templates/test/controllers/root_controller_test.rb +12 -0
  82. data/templates/test/controllers/settings_controller_test.rb +27 -0
  83. data/templates/test/controllers/yetto_controller_test.rb +130 -0
  84. data/templates/test/jobs/update_yetto_job_test.rb +41 -0
  85. data/templates/test/support/api.rb +74 -0
  86. data/templates/test/support/rails.rb +39 -0
  87. data/templates/test/support/webmocks/slack_webmock.rb +24 -0
  88. data/templates/test/support/webmocks/yetto.rb +94 -0
  89. data/templates/test/support/webmocks.rb +5 -0
  90. data/templates/test/test_helper.rb +24 -0
  91. metadata +209 -0
@@ -0,0 +1,64 @@
1
+ {
2
+ "202": {
3
+ "type": "object",
4
+ "required": [
5
+ "message"
6
+ ],
7
+ "properties": {
8
+ "message": {
9
+ "type": "string",
10
+ "value": "Accepted"
11
+ }
12
+ }
13
+ },
14
+ "204": {
15
+ "type": "object",
16
+ "required": [
17
+ "message"
18
+ ],
19
+ "properties": {
20
+ "message": {
21
+ "type": "string",
22
+ "value": "No Content"
23
+ }
24
+ }
25
+ },
26
+ "400": {
27
+ "type": "object",
28
+ "required": [
29
+ "errors"
30
+ ],
31
+ "properties": {
32
+ "errors": {
33
+ "type": "array",
34
+ "items": {
35
+ "type": "object",
36
+ "properties": {
37
+ "message": {
38
+ "type": "string"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "404": {
46
+ "type": "object",
47
+ "required": [
48
+ "errors"
49
+ ],
50
+ "properties": {
51
+ "errors": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "object",
55
+ "properties": {
56
+ "message": {
57
+ "type": "string"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "${APP} Plug API",
5
+ "description": "An OpenAPI definition for the ${APP} Plug REST API.",
6
+ "version": "2023-03-06",
7
+ "termsOfService": "https://yetto.app/terms/",
8
+ "license": {
9
+ "name": "Apache 2.0",
10
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
11
+ }
12
+ },
13
+ "servers": [
14
+ {
15
+ "url": "https://yetto.app/2023-03-06",
16
+ "description": "Production basepath"
17
+ }
18
+ ],
19
+ "paths": {
20
+ "/api/2023-03-06/after_create/plug_installation": {
21
+ "$ref": "paths/yetto/after_create_plug_installation.json"
22
+ },
23
+ "/api/2023-03-06/after_create/message": {
24
+ "$ref": "paths/yetto/after_create_message.json"
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "post": {
3
+ "tags": [
4
+ "Inbound",
5
+ "${APP}"
6
+ ],
7
+ "description": "This represents something",
8
+ "operationId": "Post a Yetto message",
9
+ "parameters": [
10
+ {
11
+ "$ref": "../components/parameters/plugInstallation.json#/plugInstallationId"
12
+ }
13
+ ],
14
+ "requestBody": {
15
+ "required": true,
16
+ "content": {
17
+ "application/json": {
18
+ "schema": {
19
+ "$ref": "../components/schemas/plug.json#/something"
20
+ }
21
+ },
22
+ "example": {
23
+ "message": {
24
+ "text_content": "Hello _World_",
25
+ "is_public": true,
26
+ "metadata": {
27
+ "author": {
28
+ "name": "John Doe"
29
+ }
30
+ }
31
+ },
32
+ "creator": {
33
+ "id": "usr_1234567890"
34
+ }
35
+ }
36
+ }
37
+ },
38
+ "responses": {
39
+ "202": {
40
+ "description": "Accepted",
41
+ "content": {
42
+ "application/json": {
43
+ "schema": {
44
+ "$ref": "../components/schemas/responses.json#/202"
45
+ }
46
+ }
47
+ }
48
+ },
49
+ "204": {
50
+ "description": "No Content",
51
+ "content": {
52
+ "application/json": {
53
+ "schema": {
54
+ "$ref": "../components/schemas/responses.json#/204"
55
+ }
56
+ }
57
+ }
58
+ },
59
+ "400": {
60
+ "description": "Bad Request",
61
+ "content": {
62
+ "application/json": {
63
+ "schema": {
64
+ "$ref": "../components/schemas/responses.json#/400"
65
+ }
66
+ }
67
+ }
68
+ },
69
+ "403": {
70
+ "description": "Forbidden",
71
+ "content": {
72
+ "application/json": {
73
+ "schema": {
74
+ "$ref": "../components/schemas/responses.json#/403"
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "503": {
80
+ "description": "Service Unavailable",
81
+ "content": {
82
+ "application/json": {
83
+ "schema": {
84
+ "$ref": "../components/schemas/responses.json#/502"
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "post": {
3
+ "tags": [
4
+ "Yetto"
5
+ ],
6
+ "description": "After a message is created in Yetto, this delivers it.",
7
+ "operationId": "Create a new email",
8
+ "responses": {
9
+ "204": {
10
+ "description": "No Content",
11
+ "content": {
12
+ "application/json": {
13
+ "schema": {
14
+ "$ref": "../../components/schemas/responses.json#/204"
15
+ }
16
+ }
17
+ }
18
+ },
19
+ "400": {
20
+ "description": "Bad Request",
21
+ "content": {
22
+ "application/json": {
23
+ "schema": {
24
+ "$ref": "../../components/schemas/responses.json#/400"
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "404": {
30
+ "description": "Not Found",
31
+ "content": {
32
+ "application/json": {
33
+ "schema": {
34
+ "$ref": "../../components/schemas/responses.json#/404"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "post": {
3
+ "tags": [
4
+ "Yetto"
5
+ ],
6
+ "description": "After a plug installation is created, this executes",
7
+ "operationId": "Post a thing",
8
+ "responses": {
9
+ "204": {
10
+ "description": "No Content",
11
+ "content": {
12
+ "application/json": {
13
+ "schema": {
14
+ "$ref": "../../components/schemas/responses.json#/204"
15
+ }
16
+ }
17
+ }
18
+ },
19
+ "400": {
20
+ "description": "Bad Request",
21
+ "content": {
22
+ "application/json": {
23
+ "schema": {
24
+ "$ref": "../../components/schemas/responses.json#/400"
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "404": {
30
+ "description": "Not Found",
31
+ "content": {
32
+ "application/json": {
33
+ "schema": {
34
+ "$ref": "../../components/schemas/responses.json#/404"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,10 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "rake/testtask"
5
+
6
+ if Rails.env.development? || Rails.env.test?
7
+ require "rubocop/rake_task"
8
+
9
+ RuboCop::RakeTask.new(:rubocop)
10
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ export CI=true
6
+
7
+ script/test
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rails runner
2
+ # frozen_string_literal: true
3
+
4
+ require "optparse"
5
+ require "debug" if ENV.fetch("DEBUG", false)
6
+
7
+ options = {}
8
+ OptionParser.new do |opts|
9
+ opts.banner = "Usage: hmac_text [options]"
10
+
11
+ opts.on("-l", "--load PATH", "Load file from path") { |v| options[:load_path] = v }
12
+ opts.on("-p", "--parse STRING", "Parses string directly") { |v| options[:parse_string] = v }
13
+ end.parse!
14
+
15
+ body = if options[:load_path].present?
16
+ File.read(options[:load_path])
17
+ elsif options[:parse_string].present?
18
+ options[:parse_string]
19
+ end
20
+
21
+ puts "Parsing `#{body}` into HMAC"
22
+ puts OpenSSL::HMAC.hexdigest(Authable::SHA256_DIGEST, YETTO_PLUG_APP_TOKEN, body)
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ function usage() {
6
+ echo "Usage:"
7
+ echo "$0 [options]"
8
+ echo ""
9
+ echo " Options:"
10
+ echo " -u/--update Update license information"
11
+ echo " -v/--verify Verify license information"
12
+ echo " -g/--generate Generate CSV license data"
13
+ echo " -h/--help Display this help message"
14
+ echo ""
15
+ exit 1
16
+ }
17
+
18
+ while [ "$1" != "" ]; do
19
+ case $1 in
20
+ -v | --verify)
21
+ echo "Verifying dependency licenses ..."
22
+ bin/bundle exec licensed env -c .licensed.yml
23
+ bin/bundle exec licensed list -c .licensed.yml
24
+ bin/bundle exec licensed status -c .licensed.yml
25
+ RET=$?
26
+ if [ $RET -ne 0 ]; then
27
+ echo
28
+ echo "*** When fixed, please run 'script/licenses -c' to update the license cache. ***"
29
+ echo
30
+ fi
31
+
32
+ exit $RET
33
+ ;;
34
+ -u | --update)
35
+ echo "Caching dependency licenses ..."
36
+ bin/bundle exec licensed cache -c .licensed.yml
37
+ ;;
38
+ -g | --generate)
39
+ echo "Generating CSV licenses ..."
40
+ bin/bundle exec rake licenses:generate
41
+ ;;
42
+ -h | --help)
43
+ usage
44
+ ;;
45
+ *)
46
+ usage
47
+ exit 1
48
+ ;;
49
+ esac
50
+ shift
51
+ done
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ ngrok http --region=us --hostname=plug-app.ngrok.io 6661
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bundle exec brakeman --color -o /dev/stdout -o security-results.json
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bundle exec bundle-audit check --update
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bin/foreman start -f Procfile.dev
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bin/foreman start -f Procfile.debug
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bin/rails test "$@"
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ function usage() {
6
+ echo "Usage:"
7
+ echo "$0 [options]"
8
+ echo ""
9
+ echo " Options:"
10
+ echo " -u/--update Update tapioca RBI files"
11
+ echo " -v/--verify Verify tapioca RBI files"
12
+ echo " -h/--help Display this help message"
13
+ echo ""
14
+ exit 1
15
+ }
16
+
17
+ while [ "$1" != "" ]; do
18
+ case $1 in
19
+ -u | --update)
20
+ echo "Updating Tapioca RBI files ..."
21
+ bin/tapioca gem
22
+ echo "Updating Tapioca DSL files ..."
23
+ bin/tapioca dsl
24
+ echo "Updating Tapioca TODO files ..."
25
+ bin/tapioca todo
26
+ ;;
27
+ -v | --verify)
28
+ echo "Verify gem RBIs are up-to-date ..."
29
+ bin/tapioca gem --verify
30
+ echo "Verify duplicates in shims ..."
31
+ bin/tapioca check-shims
32
+ ;;
33
+ -h | --help)
34
+ usage
35
+ ;;
36
+ *)
37
+ usage
38
+ exit 1
39
+ ;;
40
+ esac
41
+ shift
42
+ done
@@ -0,0 +1,14 @@
1
+ # typed: strong
2
+ # Custom, artisanal RBIs for stuff sorbet and tapioca aren't able to understand (yet?)
3
+ #
4
+ # It's likely that some of these could be corrected by adding a `sig` to the appropriate location(s)
5
+
6
+ module Authable
7
+ sig { returns(ActionDispatch::Request) }
8
+ def request; end
9
+ sig { returns(ActionDispatch::Response) }
10
+ def response; end
11
+
12
+ sig { void}
13
+ def bad_request; end
14
+ end
@@ -0,0 +1,12 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "test_helper"
5
+
6
+ class RootControllerTest < ActionDispatch::IntegrationTest
7
+ test "GET / 200s" do
8
+ get "/"
9
+
10
+ assert_response :ok
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "test_helper"
5
+
6
+ class SettingsControllerTest < ActionDispatch::IntegrationTest
7
+ include API::TestHelpers
8
+
9
+ include Webmocks::Yetto
10
+
11
+ test "GET /settings without asking for JSON fails" do
12
+ api(:get, "/settings", headers: nil)
13
+
14
+ assert_response :not_acceptable
15
+ end
16
+
17
+ test "GET /settings asking for JSON works" do
18
+ settings_json = api(:get, "/settings")
19
+
20
+ assert_response :ok
21
+
22
+ settings = settings_json["settings"]
23
+
24
+ assert_equal "2023-03-06", settings_json["version"]
25
+ assert_equal 3, settings.length
26
+ end
27
+ end
@@ -0,0 +1,130 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "test_helper"
5
+
6
+ class YettoControllerTest < ActionDispatch::IntegrationTest
7
+ include API::TestHelpers
8
+
9
+ include Webmocks::Yetto
10
+
11
+ def setup
12
+ super
13
+ @after_create_plug_installation = {
14
+ plug_installation: {
15
+ id: @plug_installation_id,
16
+ settings: {
17
+ from_name: "it me",
18
+ from_email: "new@from.company",
19
+ reply_to_email: "new@from.company",
20
+ },
21
+ },
22
+ organization: {
23
+ id: @organization_id,
24
+ },
25
+ plug: {
26
+ id: @plug_id,
27
+ },
28
+ inbox: {
29
+ id: @inbox_id,
30
+ },
31
+ }
32
+
33
+ @after_create_message = {
34
+ plug_installation: {
35
+ id: @plug_installation_id,
36
+ settings: {},
37
+ credentials: {},
38
+ },
39
+ message: {
40
+ id: @message_id,
41
+ text_content: "blern",
42
+ html_content: "<p>blern</p>",
43
+ metadata: {},
44
+ conversation: {
45
+ id: @conversation_id,
46
+ title: "Hey there?",
47
+ metadata: {
48
+ "in-reply-to" => "123",
49
+ },
50
+ },
51
+ },
52
+ inbox: {
53
+ id: @inbox_id,
54
+ organization: {
55
+ id: @organization_id,
56
+ status: "active",
57
+ },
58
+ },
59
+ }
60
+ end
61
+
62
+ def headers(body)
63
+ {
64
+ Headers::Yetto::HEADER_EVENT => "after_create",
65
+ Headers::Yetto::HEADER_RECORD_TYPE => "plug_installation",
66
+ Headers::Yetto::HEADER_SIGNATURE => yetto_auth_header(body),
67
+ }
68
+ end
69
+
70
+ test "it handles null headers" do
71
+ api(:post, "/after_create/plug_installation", headers: nil)
72
+
73
+ assert_response :bad_request
74
+ end
75
+
76
+ test "it handles missing headers" do
77
+ api(:post, "/after_create/plug_installation", headers: {})
78
+
79
+ assert_response :bad_request
80
+ end
81
+
82
+ test "it handles incorrect headers" do
83
+ api(:post, "/after_create/plug_installation", headers: { "X-Yetto-Signature" => "Basic jabroni:lies" })
84
+
85
+ assert_response :bad_request
86
+
87
+ api(:post, "/after_create/plug_installation", headers: { "X-Yetto-Signature" => "sha256=123456" })
88
+
89
+ assert_response :bad_request
90
+ end
91
+
92
+ test "it handles missing body" do
93
+ body = {}
94
+ api(:post, "/after_create/plug_installation", headers: headers(body), body: body)
95
+
96
+ assert_response :bad_request
97
+ end
98
+
99
+ test "it handles wrong event" do
100
+ body = @after_create_plug_installation
101
+ api(:post, "/bloop/plug_installation", headers: headers(body), body: body)
102
+
103
+ assert_response :not_found
104
+ end
105
+
106
+ test "it handles wrong record type" do
107
+ body = @after_create_plug_installation
108
+
109
+ api(:post, "/after_create/plug_instunk", headers: headers(body), body: body)
110
+
111
+ assert_response :not_found
112
+ end
113
+
114
+ test "it handles wrong signature type" do
115
+ body = @after_create_plug_installation
116
+ headers_with_one_body = headers(body)
117
+ # body different than headers
118
+ body_two = {
119
+ plug: {
120
+ id: "plg_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}",
121
+ },
122
+ inbox: {
123
+ id: "inbx_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}",
124
+ },
125
+ }
126
+ api(:post, "/after_create/plug_installation", headers: headers_with_one_body, body: body_two)
127
+
128
+ assert_response :bad_request
129
+ end
130
+ end
@@ -0,0 +1,41 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "test_helper"
5
+
6
+ class UpdateYettoJobTest < ActiveJob::TestCase
7
+ include Webmocks::Yetto
8
+
9
+ def setup
10
+ super
11
+
12
+ @update_installation_body = {
13
+ plug_installation: {
14
+ credentials: {},
15
+ settings: {},
16
+ },
17
+ }
18
+
19
+ @installation_params = {
20
+ type: "installation",
21
+ inbox: {
22
+ id: @inbox_id,
23
+ },
24
+ organization: {
25
+ id: @organization_id,
26
+ },
27
+ }
28
+
29
+ @installation_params[:plug_installation] = @update_installation_body[:plug_installation].dup
30
+ @installation_params[:plug_installation][:id] = @plug_installation_id
31
+ end
32
+
33
+ test "does nothing if type is not supported" do
34
+ params = {
35
+ type: "not_supported",
36
+ }
37
+ assert_no_enqueued_jobs do
38
+ UpdateYettoJob.perform_now(params)
39
+ end
40
+ end
41
+ end