Skip to content

Commit

Permalink
test mailchimp plugin (#893) (#914) (#928)
Browse files Browse the repository at this point in the history
Co-authored-by: Pralish Kayastha <50227291+Pralish@users.noreply.github.com>
  • Loading branch information
donrestarone and Pralish authored Jul 15, 2022
1 parent c70610b commit fb19f2b
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 1 deletion.
27 changes: 27 additions & 0 deletions test/fixtures/api_namespaces.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,31 @@ namespace_with_all_types:
"null": null
}
requires_authentication: false
namespace_type: create-read-update-delete

mailchimp:
name: mailchimp_namespace
slug: mailchimp_namespace
version: 1
properties: {
'first_name': 'Violet',
'last_name': 'Rails',
'email': 'violet@rails.com',
'contact': '',
'synced_to_mailchimp': false
}
requires_authentication: false
namespace_type: create-read-update-delete

mailchimp_logger:
name: mailchimp/logger
slug: mailchimp_logger
version: 1
properties: {
'status': '',
'response': {},
'timstamp': '',
'api_resource': ''
}
requires_authentication: false
namespace_type: create-read-update-delete
9 changes: 9 additions & 0 deletions test/fixtures/api_resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,12 @@ plugin_subdomain_message_event:
"body": "<h1>Hello</h1>"
}
}
mailchimp:
api_namespace: mailchimp
properties: {
'first_name': 'Violet',
'last_name': 'Rails',
'email': 'violet@rails.com',
'contact': '555-777',
'synced_to_mailchimp': false
}
78 changes: 77 additions & 1 deletion test/fixtures/external_api_clients.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,80 @@ vacuum_job:
end
end
# at the end of the file we have to implicitly return the class
VacuumJob
VacuumJob
mailchimp_plugin:
api_namespace: mailchimp
slug: mailchimp-plugin
label: MailChimp
enabled: true
metadata: {
'API_KEY': 'testkey',
'SERVER_PREFIX': 'us9',
'LIST_ID': 'valid_list_id',
}
model_definition: |
class SyncToMailchimp
def initialize(parameters)
@external_api_client = parameters[:external_api_client]
@api_key = @external_api_client.metadata["API_KEY"]
@unsynced_api_resources = @external_api_client.api_namespace.api_resources.where("properties @> ?", {synced_to_mailchimp: false}.to_json)
@mailchimp_uri = "https://#{@external_api_client.metadata['SERVER_PREFIX']}.api.mailchimp.com/3.0/lists/#{@external_api_client.metadata['LIST_ID']}/members?skip_merge_validation=true"
@custom_merge_fields_map = @external_api_client.metadata['CUSTOM_MERGE_FIELDS_MAP'] || {}
@attr_to_exclude = (@external_api_client.metadata['ATTR_TO_EXCLUDE'] || []) + @custom_merge_fields_map.keys + ['synced_to_mailchimp']
@logger_namespace = ApiNamespace.find_by(slug: @external_api_client.metadata["LOGGER_NAMESPACE"]) if @external_api_client.metadata["LOGGER_NAMESPACE"]
end
def start
@unsynced_api_resources.each do |api_resource|
begin
merge_fields = api_resource.properties.except(*@attr_to_exclude).transform_keys(&:upcase).transform_values(&:to_s)
@custom_merge_fields_map.each do |key, value|
merge_fields[value.upcase] = api_resource.properties[key].to_s if value
end
response = HTTParty.post(@mailchimp_uri,
body: {
email_address: api_resource.properties["email"],
status: "subscribed",
merge_fields: merge_fields,
tags: @external_api_client.metadata['TAGS'] || []
}.to_json,
headers: {
'Content-Type': 'application/json',
'Authorization': "Basic #{@api_key}"
}
)
if response.success?
api_resource.properties["synced_to_mailchimp"] = true
api_resource.save
end
@logger_namespace.api_resources.create!(
properties: {
api_resource: api_resource.id,
status: response.success? ? "success" : "error",
response: JSON.parse(response.body),
timestamp: Time.zone.now
}
) if @logger_namespace
rescue StandardError => e
@logger_namespace.api_resources.create!(
properties: {
api_resource: api_resource.id,
status: "error",
response: { detail: e.message},
timestamp: Time.zone.now
}
) if @logger_namespace
end
end
end
end
# at the end of the file we have to implicitly return the class
SyncToMailchimp
139 changes: 139 additions & 0 deletions test/plugins/mailchimp_plugin_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
require "test_helper"

class MailchimpPluginTest < ActiveSupport::TestCase
setup do
@mailchimp_plugin = external_api_clients(:mailchimp_plugin)
@api_namespace = api_namespaces(:mailchimp)
@api_resource = api_resources(:mailchimp)
@logger_namespace = api_namespaces(:mailchimp_logger)
@mailchimp_api_uri = "https://#{@mailchimp_plugin.metadata['SERVER_PREFIX']}.api.mailchimp.com/3.0/lists/#{@mailchimp_plugin.metadata['LIST_ID']}/members?skip_merge_validation=true"
@request_headers = { 'Authorization': "Basic #{@mailchimp_plugin.metadata['API_KEY']}", 'Content-Type': 'application/json' }
Sidekiq::Testing.fake!
end

test "should send api request to mailchimp" do
metadata = @mailchimp_plugin.metadata

request_body = {
"email_address": @api_resource.properties['email'],
"status": "subscribed",
# synced_to_mailchimp property should be excluded by deafult
# merge fields keys should be uppercase properties keys
# tags should be an empty array if TAGS metadata is not defined
"merge_fields": {"EMAIL": @api_resource.properties['email'], "FIRST_NAME": @api_resource.properties['first_name'], "LAST_NAME": @api_resource.properties['last_name'], "CONTACT": @api_resource.properties['contact']},
"tags": []
}

response_body = {
"id" => "123adc",
"email" => "violet@rails.com"
}

mailchimp_request = stub_request(:post, @mailchimp_api_uri)
.with(body: request_body, headers: @request_headers)
.to_return(status: 200, body: response_body.to_json)

assert_changes -> { @api_resource.reload.properties['synced_to_mailchimp'] }, from: false, to: true do
# should not create log if LOGGER_NAMESPACE metadata is not defined
assert_no_difference "@logger_namespace.api_resources.count" do
perform_enqueued_jobs do
@mailchimp_plugin.run
Sidekiq::Worker.drain_all
end
end
end

assert_requested mailchimp_request
end

test "should send api request to mailchimp for all unsynced api resources" do
ApiResource.create(api_namespace_id: @api_namespace.id, properties: {'first_name': 'first_name', 'email': 'some_email@some_domain.com', 'synced_to_mailchimp': false})
ApiResource.create(api_namespace_id: @api_namespace.id, properties: {'first_name': 'some_name', 'email': 'second@some_domain.com', 'synced_to_mailchimp': true})

mailchimp_request = stub_request(:post, @mailchimp_api_uri).to_return(status: 200, body: {id: 'some_id'}.to_json)
expected_count = @api_namespace.api_resources.where("properties @> ?", {synced_to_mailchimp: false}.to_json).count

perform_enqueued_jobs do
@mailchimp_plugin.run
Sidekiq::Worker.drain_all
end

assert_requested mailchimp_request, times: expected_count
end

test "optional metadata" do
metadata = @mailchimp_plugin.metadata

# optional metadata
metadata['LOGGER_NAMESPACE'] = 'mailchimp_logger'
metadata['ATTR_TO_EXCLUDE'] = ['first_name']
metadata['TAGS'] = ['some_tag']
metadata['CUSTOM_MERGE_FIELDS_MAP'] = {'contact': 'PHONE'}

@mailchimp_plugin.update(metadata: metadata)

request_body = {
"email_address": @api_resource.properties['email'],
"status": "subscribed",
# synced_to_mailchimp property should be excluded by deafult
# excluded attributes [ATTR_TO_EXCLUDE] should not be present in the merge fields
# custom_merge_fields should replace default merge field name if CUSTOM_MERGE_FIELDS_MAP is defined eg. CONTACT is replaced by PHONE
"merge_fields": {"EMAIL": @api_resource.properties['email'], "LAST_NAME": @api_resource.properties['last_name'], "PHONE": @api_resource.properties['contact']},
"tags": ['some_tag']
}

response_body = {
"id" => "123adc",
"email" => "violet@rails.com"
}

mailchimp_request = stub_request(:post, @mailchimp_api_uri).with(body: request_body, headers: @request_headers).to_return(status: 200, body: response_body.to_json)

assert_changes -> { @api_resource.reload.properties['synced_to_mailchimp'] }, from: false, to: true do
# should create log if LOGGER_NAMESPACE metadata is defined
assert_difference "@logger_namespace.api_resources.count", +1 do
perform_enqueued_jobs do
@mailchimp_plugin.run
Sidekiq::Worker.drain_all
end
end
end

log = @logger_namespace.api_resources.last.properties

assert_equal log['status'], 'success'
assert_equal log['api_resource'], @api_resource.id
assert_equal log['response'], response_body

assert_requested mailchimp_request
end

test "error response: should create log with error status" do
metadata = @mailchimp_plugin.metadata
metadata['LOGGER_NAMESPACE'] = 'mailchimp_logger'

@mailchimp_plugin.update(metadata: metadata)

response_body = { "message" => "error message" }

mailchimp_request = stub_request(:post, @mailchimp_api_uri).to_return(status: 400, body: response_body.to_json)

assert_no_changes @api_resource.reload.properties['synced_to_mailchimp'] do
# should create log if LOGGER_NAMESPACE metadata is defined
assert_difference "@logger_namespace.api_resources.count", +1 do
perform_enqueued_jobs do
@mailchimp_plugin.run
Sidekiq::Worker.drain_all
end
end
end

log = @logger_namespace.api_resources.last.properties

assert_equal log['status'], 'error'
assert_equal log['api_resource'], @api_resource.id
assert_equal log['response'], response_body

assert_requested mailchimp_request
end
end

0 comments on commit fb19f2b

Please sign in to comment.