newslettre 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Feature: Managing Recipients for Newsletters
2
+ Background:
3
+ Given there is no Newsletter named 'Superior Soy Beans Discount!'
4
+ And there is no 'Junk-food addicts' Recipient List
5
+ And there is no identity named 'Bourne'
6
+ @sendgrid_adding_recipients
7
+ Scenario: Adding a Recipient List to a Newsletter
8
+ Given I add the 'Bourne' Identity
9
+ And I add a Newsletter named 'Superior Soy Beans Discount!' written by 'Bourne'
10
+ And I add a Recipient List named 'Junk-food addicts'
11
+ When I add 'Junk-food addicts' to 'Superior Soy Beans Discount!'
12
+ Then 'Junk-food addicts' will be notified when 'Superior Soy Beans Discount!' is delivered
13
+ @sendgrid_removing_recipients
14
+ Scenario: Removing a Recipient List from a Newsletter
15
+ Given I add the 'Bourne' Identity
16
+ And I add a Newsletter named 'Superior Soy Beans Discount!' written by 'Bourne'
17
+ And I add a Recipient List named 'Junk-food addicts'
18
+ And I add 'Junk-food addicts' to 'Superior Soy Beans Discount!'
19
+ When I remove 'Junk-food addicts' from 'Superior Soy Beans Discount!'
20
+ Then no one will be notified when 'Superior Soy Beans Discount!' is delivered
@@ -0,0 +1,63 @@
1
+ Given /^there is no Newsletter named '([^']+)'$/ do |name|
2
+ begin
3
+ Newslettre::Letter.new(newslettre).delete name
4
+ rescue Newslettre::Client::ClientFailure
5
+ nil
6
+ end
7
+ end
8
+
9
+ Given /^there is no '([^']+)' Recipient List$/ do |list|
10
+ begin
11
+ Newslettre::Lists.new(newslettre).delete list
12
+ rescue Newslettre::Client::ClientFailure
13
+ nil
14
+ end
15
+ end
16
+
17
+ Given /^there is no identity named '([^']+)'$/ do |identity|
18
+ begin
19
+ Newslettre::Identity.new(newslettre).delete identity
20
+ rescue Newslettre::Client::ClientFailure
21
+ nil
22
+ end
23
+ end
24
+
25
+ Given /^I add the '([^']+)' Identity$/ do |identity|
26
+ Newslettre::Identity.new(newslettre).add identity, NEWSLETTRE_CONFIG['identity']
27
+ end
28
+
29
+ Given /^I add a Newsletter named '([^']+)' written by '([^']+)'$/ do |name, identity|
30
+ Newslettre::Letter.new(newslettre).add name,
31
+ :identity => identity,
32
+ :subject => name,
33
+ :text => "Super Cool!",
34
+ :html => "<h1>meow</h1>"
35
+ end
36
+
37
+ Given /^I add a Recipient List named '([^']+)'$/ do |list|
38
+ Newslettre::Lists.new(newslettre).add list
39
+ end
40
+
41
+ When /^I add '([^']+)' to '([^']+)'$/ do |list, name|
42
+ recipients = Newslettre::Letter::Recipients.new name, newslettre
43
+
44
+ recipients.add list
45
+ end
46
+
47
+ When /^I remove '([^']+)' from '([^']+)'$/ do |list, name|
48
+ recipients = Newslettre::Letter::Recipients.new name, newslettre
49
+
50
+ recipients.delete list
51
+ end
52
+
53
+ Then /^'([^']+)' will be notified when '([^']+)' is delivered$/ do |list, name|
54
+ recipients = Newslettre::Letter::Recipients.new name, newslettre
55
+ lists = recipients.get
56
+ lists.should =~ [{ "list" => list }]
57
+ end
58
+
59
+ Then /^no one will be notified when '([^']+)' is delivered$/ do |name|
60
+ recipients = Newslettre::Letter::Recipients.new name, newslettre
61
+ lists = recipients.get
62
+ lists.should be_empty
63
+ end
@@ -0,0 +1,25 @@
1
+ NEWSLETTRE_CONFIG = YAML.load_file File.dirname(__FILE__) + "/../../config/newslettre.yml"
2
+
3
+ require 'vcr'
4
+ require 'newslettre'
5
+
6
+ VCR.config do |c|
7
+ c.stub_with :webmock
8
+ c.cassette_library_dir = 'features/cassettes'
9
+ c.filter_sensitive_data('<<USERNAME>>') { NEWSLETTRE_CONFIG['sendgrid']['username'] }
10
+ c.filter_sensitive_data('<<PASSWORD>>') { NEWSLETTRE_CONFIG['sendgrid']['password'] }
11
+ c.default_cassette_options = { :record => :once }
12
+ end
13
+
14
+ VCR.cucumber_tags do |t|
15
+ t.tags '@sendgrid_adding_recipients', '@sendgrid_removing_recipients'
16
+ end
17
+
18
+ class OuterWorld
19
+ def newslettre
20
+ @newslettre ||= Newslettre::Client.new(:email => NEWSLETTRE_CONFIG['sendgrid']['username'],
21
+ :password => NEWSLETTRE_CONFIG['sendgrid']['password'])
22
+ end
23
+ end
24
+
25
+ World { OuterWorld.new }
@@ -0,0 +1,9 @@
1
+ require 'httparty'
2
+
3
+ module Newslettre
4
+ autoload :Client, 'newslettre/client'
5
+ autoload :APIModule, 'newslettre/api_module'
6
+ autoload :Letter, 'newslettre/letter'
7
+ autoload :Identity, 'newslettre/identity'
8
+ autoload :Lists, 'newslettre/lists'
9
+ end
@@ -0,0 +1,17 @@
1
+ class Newslettre::APIModule
2
+ attr_reader :client
3
+
4
+ def initialize client
5
+ @client = client
6
+ end
7
+
8
+ protected
9
+
10
+ def api_prefix
11
+ "/#{self.class.name.split(/::/).last.downcase}"
12
+ end
13
+
14
+ def request method, data = {}
15
+ self.client.send method, data, { :prefix => api_prefix }
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ class Newslettre::Client
2
+ include HTTParty
3
+ format :json
4
+ attr_reader :email, :password, :format
5
+
6
+
7
+ def initialize options = {}
8
+ self.class.base_uri "https://sendgrid.com/api/newsletter"
9
+ @email = options.delete :email
10
+ @password = options.delete :password
11
+ @format = "json"
12
+ end
13
+
14
+
15
+ def url
16
+ @url ||= self.class.default_options[:base_uri]
17
+ end
18
+
19
+ %w{get list add delete edit}.each do |m|
20
+ define_method m do |*args|
21
+ params, options = args
22
+ params ||= {}
23
+ options ||= {}
24
+ response = self.class.post url_for(m, options), :query => params.merge(credentials)
25
+ raise ClientFailure if response.code > 399 and response.code < 500
26
+ raise EndpointFailure if response.code > 499
27
+ response
28
+ end
29
+ end
30
+
31
+ alias_method :post, :add
32
+ alias_method :put, :edit
33
+
34
+ class ClientFailure < StandardError; end
35
+ class EndpointFailure < StandardError; end
36
+
37
+ protected
38
+
39
+ def credentials
40
+ {
41
+ :api_user => email,
42
+ :api_key => password
43
+ }
44
+ end
45
+
46
+ def url_for path, options = {}
47
+ "#{options[:prefix]}/#{path}.#{format}"
48
+ end
49
+ end
@@ -0,0 +1,21 @@
1
+ class Newslettre::Identity < Newslettre::APIModule
2
+ def list
3
+ request 'list'
4
+ end
5
+
6
+ def get id
7
+ request 'get', :identity => id
8
+ end
9
+
10
+ def add id, data = {}
11
+ request 'add', data.merge(:identity => id)
12
+ end
13
+
14
+ def edit id, data = {}
15
+ request 'edit', data.merge(:identity => id)
16
+ end
17
+
18
+ def delete id
19
+ request 'delete', :identity => id
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ class Newslettre::Letter < Newslettre::APIModule
2
+ def list
3
+ request 'list'
4
+ end
5
+
6
+ def add name, data = {}
7
+ request 'add', data.merge(:name => name)
8
+ end
9
+
10
+ def get name
11
+ request 'get', :name => name
12
+ end
13
+
14
+ def delete name
15
+ request 'delete', :name => name
16
+ end
17
+
18
+ def edit name, data = {}
19
+ request 'edit', data
20
+ end
21
+
22
+ class Recipients < Newslettre::APIModule
23
+ attr_reader :letter
24
+
25
+ def initialize letter, client
26
+ @letter = letter
27
+ @client = client
28
+ end
29
+
30
+ def add list
31
+ request 'add', { :list => list, :name => letter }
32
+ end
33
+
34
+ def get
35
+ request 'get', { :name => letter }
36
+ end
37
+
38
+ def delete list
39
+ request 'delete', { :list => list, :name => letter }
40
+ end
41
+ end
42
+
43
+ protected
44
+
45
+ def api_prefix
46
+ nil
47
+ end
48
+ end
@@ -0,0 +1,49 @@
1
+ class Newslettre::Lists < Newslettre::APIModule
2
+ def add list, data = {}
3
+ request 'add', data.merge(:list => list)
4
+ end
5
+
6
+ def get list = nil
7
+ if list.nil?
8
+ request 'get'
9
+ else
10
+ request('get', :list => list).first
11
+ end
12
+ end
13
+ alias_method :list, :get
14
+
15
+ def edit list, data = {}
16
+ request 'edit', data.merge(:list => list)
17
+ end
18
+
19
+ def delete list
20
+ request 'delete', :list => list
21
+ end
22
+
23
+ class Email < Newslettre::APIModule
24
+ attr_reader :list
25
+
26
+ def initialize list, client
27
+ @client = client
28
+ @list = list
29
+ end
30
+
31
+ def add *recipients
32
+ request 'add', :list => list, :data => recipients.map{|r| JSON.dump(r) }
33
+ end
34
+
35
+ def get *recipients
36
+ request 'get', :list => list, :email => recipients
37
+ end
38
+
39
+ def delete *recipients
40
+ request 'delete', :list => list, :email => recipients
41
+ end
42
+
43
+ protected
44
+
45
+ def api_prefix
46
+ "/lists/email"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Newslettre
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "newslettre/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "newslettre"
7
+ s.version = Newslettre::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Lennart Melzer"]
10
+ s.email = ["l@melzer.it"]
11
+ s.homepage = ""
12
+ s.summary = %q{Sendgrid Newsletter API Client}
13
+ s.description = %q{Create and Manage Newsletters using the Sendgrid API}
14
+
15
+ s.rubyforge_project = "newslettre"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "httparty", "~> 0.8"
23
+
24
+ s.add_development_dependency "rake", "~> 0.9"
25
+ s.add_development_dependency "rspec", "~> 2"
26
+ s.add_development_dependency "webmock", "~> 1.7"
27
+ s.add_development_dependency "vcr", "~> 1.11"
28
+ s.add_development_dependency "cucumber", "~> 1"
29
+ end
@@ -0,0 +1,24 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :post
5
+ uri: https://sendgrid.com:443/api/newsletter/identity/list.json?api_key=<<PASSWORD>>&api_user=<<USERNAME>>
6
+ body: !!null
7
+ headers: !!null
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ server:
14
+ - nginx/0.7.65
15
+ date:
16
+ - Tue, 20 Sep 2011 14:26:55 GMT
17
+ content-type:
18
+ - text/html
19
+ transfer-encoding:
20
+ - chunked
21
+ connection:
22
+ - keep-alive
23
+ body: ! '[{"identity": "da9febf06480f7bb88264fc907f75995"}]'
24
+ http_version: '1.1'
@@ -0,0 +1,72 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :post
5
+ uri: https://sendgrid.com:443/api/newsletter/identity/add.json?address=Oranienstra%C3%9Fe%206&api_key=<<PASSWORD>>&api_user=<<USERNAME>>&city=Berlin&country=DE&email=<<USERNAME>>&identity=test-identity&name=Mathias%20Fiedler&state=B&zip=10997
6
+ body: !!null
7
+ headers: !!null
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ server:
14
+ - nginx/0.7.65
15
+ date:
16
+ - Tue, 20 Sep 2011 14:26:56 GMT
17
+ content-type:
18
+ - text/html
19
+ transfer-encoding:
20
+ - chunked
21
+ connection:
22
+ - keep-alive
23
+ body: ! '{"message": "success"}'
24
+ http_version: '1.1'
25
+ - !ruby/struct:VCR::HTTPInteraction
26
+ request: !ruby/struct:VCR::Request
27
+ method: :post
28
+ uri: https://sendgrid.com:443/api/newsletter/identity/get.json?api_key=<<PASSWORD>>&api_user=<<USERNAME>>&identity=test-identity
29
+ body: !!null
30
+ headers: !!null
31
+ response: !ruby/struct:VCR::Response
32
+ status: !ruby/struct:VCR::ResponseStatus
33
+ code: 200
34
+ message: OK
35
+ headers:
36
+ server:
37
+ - nginx/0.7.65
38
+ date:
39
+ - Tue, 20 Sep 2011 14:26:57 GMT
40
+ content-type:
41
+ - text/html
42
+ transfer-encoding:
43
+ - chunked
44
+ connection:
45
+ - keep-alive
46
+ body: ! '{"city": "Berlin", "name": "Mathias Fiedler", "zip": "10997", "country":
47
+ "DE", "state": "B", "address": "Oranienstra\u00dfe 6", "email": "<<USERNAME>>",
48
+ "identity": "test-identity"}'
49
+ http_version: '1.1'
50
+ - !ruby/struct:VCR::HTTPInteraction
51
+ request: !ruby/struct:VCR::Request
52
+ method: :post
53
+ uri: https://sendgrid.com:443/api/newsletter/identity/delete.json?api_key=<<PASSWORD>>&api_user=<<USERNAME>>&identity=test-identity
54
+ body: !!null
55
+ headers: !!null
56
+ response: !ruby/struct:VCR::Response
57
+ status: !ruby/struct:VCR::ResponseStatus
58
+ code: 200
59
+ message: OK
60
+ headers:
61
+ server:
62
+ - nginx/0.7.65
63
+ date:
64
+ - Tue, 20 Sep 2011 14:26:58 GMT
65
+ content-type:
66
+ - text/html
67
+ transfer-encoding:
68
+ - chunked
69
+ connection:
70
+ - keep-alive
71
+ body: ! '{"message": "success"}'
72
+ http_version: '1.1'