Question

I have an email helper extension I have written for my application. I use settings I have defined on the application like so:

set :mailgun_options, JSON.parse(File.open('config/mailer.json').read)[ENV['RACK_ENV']]

which reads configuration settings from a json file into the global Sinatra settings.

I then have my email helper which references these settings to create connections and what not.

require 'sinatra/base'
require 'faraday'

module Sinatra
    module EmailHelper
        def connect opts={}
            connection =  Faraday.new(:url => settings.mailgun_options['mailgun_url']) do |faraday|
                if settings.mailgun_options['test']
                    faraday.adapter :test do |stubs|
                        stubs.post(settings.mailgun_options['domain'] + '/messages') {[ 200, {}, 'success' ]}
                    end
                else
                    faraday.request :url_encoded
                    faraday.adapter Faraday.default_adapter
                end
            end

            connection.basic_auth('api', settings.mailgun_options['key'])
            return connection
        end

        def send_email params={}
            connect.post((settings.mailgun_options['domain'] + '/messages'), params)
        end

        def send_password_reset_email email
            template = File.open( File.expand_path( '../../helpers/email_helper/templates/password_reset.erb', __FILE__ ), 'r' ).read

            send_email({
                :from => 'REscour <noreply@' + settings.mailgun_options['domain'] + '>',
                :to => email,
                :subject => 'REscour.com Password Reset',
                :text => ERB.new(template).result(binding)
            })
        end
    end
end

So, when I am trying to write my specs to test the "connect" method, I get the following error:

undefined local variable or method `settings' for #<Class:0x007faaf9c9bd18>

My spec code is as follows:

module Sinatra
    describe EmailHelper
        let(:dummy_class) { Class.new { extend EmailHelper } }

        it 'should connect to mailgun\'s api' do
            app.set :mailgun_options, ::JSON.parse(File.open('config/mailer.json').read)['test']
            puts dummy_class.connect
        end
    end
end

I'm not sure how to interact with the global Sinatra settings from my specs to have the local "settings" variable be defined during execution of the helper code.

I could have the architecture of my application wrong here for all I know. Does anyone have any experience in writing Sinatra extensions using the global settings and write specs for them?

Was it helpful?

Solution

The spec you've written seems to want to be a unit test, because you've not run the extension the way it would be used in an app. In the specs, try something like:

describe "connect" do
  let(:app) { Sinatra.new do
                helpers Sinatra::EmailHelper

                configure do
                  :mailgun_options, ::JSON.parse(File.open('config/mailer.json')
                end

                get "/" do
                  connect
                end
              end
            }
   # now write specs for the `connect` helper
 end

Using an anonymous class (Sinatra.new do…) lets you quickly set up an app that's convenient for a small test, but there are other ways too.

In the extension, you need to add:

helpers EmailHelper

as per the example in the docs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top