citrulu 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --profile
data/.simplecov ADDED
@@ -0,0 +1,3 @@
1
+ SimpleCov.start do
2
+ add_filter "/spec/"
3
+ end
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "faraday" #TODO: specify version
6
+ gem "json" #TODO: specify version
7
+ gem "activemodel" #TODO: specify version
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "rspec", ">= 2.11.0"
13
+ gem "factory_girl" # TODO: specify version
14
+ gem "rdoc", "~> 3.12"
15
+ gem "bundler", ">= 1.0.0"
16
+ gem "jeweler", "~> 1.8.4"
17
+ gem "simplecov", ">= 0"
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.3)
5
+ activesupport (= 3.2.3)
6
+ builder (~> 3.0.0)
7
+ activesupport (3.2.3)
8
+ i18n (~> 0.6)
9
+ multi_json (~> 1.0)
10
+ builder (3.0.0)
11
+ diff-lcs (1.1.3)
12
+ factory_girl (2.6.4)
13
+ activesupport (>= 2.3.9)
14
+ faraday (0.8.4)
15
+ multipart-post (~> 1.1)
16
+ git (1.2.5)
17
+ i18n (0.6.0)
18
+ jeweler (1.8.4)
19
+ bundler (~> 1.0)
20
+ git (>= 1.2.5)
21
+ rake
22
+ rdoc
23
+ json (1.7.5)
24
+ multi_json (1.3.6)
25
+ multipart-post (1.1.5)
26
+ rake (0.9.2.2)
27
+ rdoc (3.12)
28
+ json (~> 1.4)
29
+ rspec (2.11.0)
30
+ rspec-core (~> 2.11.0)
31
+ rspec-expectations (~> 2.11.0)
32
+ rspec-mocks (~> 2.11.0)
33
+ rspec-core (2.11.1)
34
+ rspec-expectations (2.11.3)
35
+ diff-lcs (~> 1.1.3)
36
+ rspec-mocks (2.11.3)
37
+ simplecov (0.7.1)
38
+ multi_json (~> 1.0)
39
+ simplecov-html (~> 0.7.1)
40
+ simplecov-html (0.7.1)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ activemodel
47
+ bundler (>= 1.0.0)
48
+ factory_girl
49
+ faraday
50
+ jeweler (~> 1.8.4)
51
+ json
52
+ rdoc (~> 3.12)
53
+ rspec (>= 2.11.0)
54
+ simplecov
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 The Dextrous Web Ltd
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ Citrulu
2
+ =======
3
+ A wrapper for the [Citrulu api](https://www.citrulu.com/api)
4
+
5
+ Usage
6
+ -----
7
+ You need an account on Citrulu to use the gem. Sign up at <http://www.citrulu.com>.
8
+
9
+ You can create an API key on the '[Account Settings](https://www.citrulu.com/settings)' tab once you're signed in.
10
+
11
+ Configure your API key by adding the following to an initializer, eg. `config/initializers/citrulu_auth.rb`:
12
+
13
+ ```ruby
14
+ CITRULU_API_KEY = "abcdefgh"
15
+ ```
16
+
17
+ Contributing to the Citrulu gem
18
+ -------------------------------
19
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
20
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
21
+ * Fork the project.
22
+ * Start a feature/bugfix branch.
23
+ * Commit and push until you are happy with your contribution.
24
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
25
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
26
+
27
+ Authors
28
+ -------
29
+ Duncan Stuart (duncan@dxw.com)
30
+
31
+ Copyright
32
+ ---------
33
+ Copyright (c) 2012 The Dextrous Web Ltd. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "citrulu"
18
+ gem.homepage = "https://github.com/dxw/citrulu-api-ruby.git"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{ Wrapper for the api exposed by Citrulu }
21
+ gem.description = %Q{ Citrulu exposes an api for creating, editing and compiling test files (http://www.citrulu.com/api). This gem provides a wrapper around that api which allows you to work with TestFile objects locally. }
22
+ gem.email = ["contact@dxw.com", "duncan@dxw.com"]
23
+ gem.authors = ["Duncan Stuart"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ # require 'rdoc/task'
42
+ # Rake::RDocTask.new do |rdoc|
43
+ # version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+ #
45
+ # rdoc.rdoc_dir = 'rdoc'
46
+ # rdoc.title = "citrulu-api #{version}"
47
+ # rdoc.rdoc_files.include('README*')
48
+ # rdoc.rdoc_files.include('lib/**/*.rb')
49
+ # end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/citrulu.gemspec ADDED
@@ -0,0 +1,80 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "citrulu"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Duncan Stuart"]
12
+ s.date = "2012-10-29"
13
+ s.description = " Citrulu exposes an api for creating, editing and compiling test files (http://www.citrulu.com/api). This gem provides a wrapper around that api which allows you to work with TestFile objects locally. "
14
+ s.email = ["contact@dxw.com", "duncan@dxw.com"]
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ ".simplecov",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "citrulu.gemspec",
30
+ "lib/citrulu.rb",
31
+ "lib/citrulu/error.rb",
32
+ "lib/citrulu/test_file.rb",
33
+ "lib/faraday/raise_error.rb",
34
+ "spec/citrulu/test_file_spec.rb",
35
+ "spec/factories/test_files.rb",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = "https://github.com/dxw/citrulu-api-ruby.git"
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = "1.8.24"
42
+ s.summary = "Wrapper for the api exposed by Citrulu"
43
+
44
+ if s.respond_to? :specification_version then
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_runtime_dependency(%q<faraday>, [">= 0"])
49
+ s.add_runtime_dependency(%q<json>, [">= 0"])
50
+ s.add_runtime_dependency(%q<activemodel>, [">= 0"])
51
+ s.add_development_dependency(%q<rspec>, [">= 2.11.0"])
52
+ s.add_development_dependency(%q<factory_girl>, [">= 0"])
53
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
54
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
55
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
56
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<faraday>, [">= 0"])
59
+ s.add_dependency(%q<json>, [">= 0"])
60
+ s.add_dependency(%q<activemodel>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, [">= 2.11.0"])
62
+ s.add_dependency(%q<factory_girl>, [">= 0"])
63
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
64
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
66
+ s.add_dependency(%q<simplecov>, [">= 0"])
67
+ end
68
+ else
69
+ s.add_dependency(%q<faraday>, [">= 0"])
70
+ s.add_dependency(%q<json>, [">= 0"])
71
+ s.add_dependency(%q<activemodel>, [">= 0"])
72
+ s.add_dependency(%q<rspec>, [">= 2.11.0"])
73
+ s.add_dependency(%q<factory_girl>, [">= 0"])
74
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
75
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
76
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
77
+ s.add_dependency(%q<simplecov>, [">= 0"])
78
+ end
79
+ end
80
+
@@ -0,0 +1,13 @@
1
+ module Citrulu
2
+ # Custom error class for rescuing from all Citrulu errors
3
+ class Error < StandardError; end
4
+
5
+ # Raised when Citrulu returns the HTTP status code 404
6
+ class NotFound < Error; end
7
+
8
+ # Raised when authentication failed (401)
9
+ class AccessDenied < Error; end
10
+
11
+ # Raised when Citrulu returns the HTTP status code 500
12
+ class InternalServerError < Error; end
13
+ end
@@ -0,0 +1,181 @@
1
+ require 'json'
2
+ require 'active_model'
3
+
4
+ class TestFile
5
+ attr_accessor :name
6
+ attr_accessor :test_file_text
7
+ attr_reader :compiled_test_file_text
8
+ attr_accessor :run_tests
9
+ attr_reader :domains
10
+ attr_reader :frequency
11
+ attr_reader :id
12
+ attr_reader :tutorial_id
13
+ attr_reader :updated_at
14
+ attr_reader :created_at
15
+
16
+ attr_reader :errors
17
+
18
+ def self.attribute_method?(attribute)
19
+ [ :name,
20
+ :test_file_text,
21
+ :compiled_test_file_text,
22
+ :run_tests,
23
+ :domains,
24
+ :frequency,
25
+ :id,
26
+ :tutorial_id,
27
+ :updated_at,
28
+ :created_at,
29
+ ].include?(attribute)
30
+ end
31
+
32
+ extend ActiveModel::Naming
33
+ # Required dependency for ActiveModel::Errors
34
+
35
+ # This is for the user creating Test Files. Internally we use build (defined below)
36
+ def initialize(args={})
37
+ args.each do |attr, value|
38
+ self.public_send("#{attr}=", value)
39
+ end if args
40
+ end
41
+
42
+ # The following methods are needed in order for ActiveModel::Errors to work correctly
43
+ def read_attribute_for_validation(attr)
44
+ send(attr)
45
+ end
46
+
47
+ def self.human_attribute_name(attr, options = {})
48
+ attr
49
+ end
50
+
51
+ def self.lookup_ancestors
52
+ [self]
53
+ end
54
+
55
+
56
+ #################
57
+ # Class Methods #
58
+ #################
59
+
60
+ # GET "https://www.citrulu.com/api/v1/test_files?auth_token=abcdefg"
61
+ def self.all
62
+ response = Citrulu.connection.get "test_files"
63
+ attr_array = JSON.parse(response.body)
64
+ attr_array.map{ |attrs| build(attrs)}
65
+ end
66
+
67
+ # GET "https://www.citrulu.com/api/v1/test_files/2?auth_token=abcdefg"
68
+ def self.find(id)
69
+ response = Citrulu.connection.get "test_files/#{id}"
70
+ # parse_response(response.body)
71
+
72
+ # TEMPORARY: there's a bug in the api which means that it returns an array instead of a single hash,
73
+ # so we'll be hacky for now:
74
+ attrs = JSON.parse(response.body)
75
+ build(attrs.first)
76
+ end
77
+
78
+ # POST "https://www.citrulu.com/api/v1/test_files?name=foo&test_file_text=bar&run_tests=false&auth_token=abcdefg"
79
+ def self.create(options={})
80
+ response = Citrulu.connection.post "test_files", options
81
+ body = JSON.parse(response.body)
82
+
83
+ if response.status == 200
84
+ build(body)
85
+ else # 422 - validation errors
86
+ test_file = build(options)
87
+ test_file.add_all_errors(body["errors"])
88
+ return test_file
89
+ end
90
+ end
91
+
92
+ # PUT "https://www.citrulu.com/api/v1/test_files/2?name=foz&test_file_text=baz&run_tests=true&auth_token=abcdefg"
93
+ def self.update(id, options={})
94
+ response = Citrulu.connection.put "test_files/#{id}", options
95
+ body = JSON.parse(response.body)
96
+
97
+ if response.status == 200
98
+ build(body)
99
+ else # 422 - validation errors
100
+ test_file = find(id)
101
+ test_file.add_all_errors(body["errors"])
102
+ return test_file
103
+ end
104
+ end
105
+
106
+ # DELETE "https://www.citrulu.com/api/v1/test_files/2?auth_token=abcdefg"
107
+ # Status 204 = successful deletion
108
+ def self.delete(id)
109
+ Citrulu.connection.delete "test_files/#{id}"
110
+ end
111
+
112
+ # POST "https://www.citrulu.com/api/v1/test_files/compile/?auth_token=abcdefg"
113
+ # status: 201 = successful compilation
114
+ def self.compile(id)
115
+ response = Citrulu.connection.post "test_files/compile/#{id}"
116
+ parse_response(response.body)
117
+ end
118
+
119
+
120
+ ####################
121
+ # Instance Methods #
122
+ ####################
123
+
124
+ # Create or update the current object
125
+ def save
126
+ options = { name: name,
127
+ test_file_text: test_file_text,
128
+ run_tests: run_tests,
129
+ }
130
+ if id
131
+ self.class.update(id, options)
132
+ else
133
+ self.class.create(options)
134
+ end
135
+ end
136
+
137
+ def destroy
138
+ self.class.delete(id)
139
+ end
140
+
141
+ def compile
142
+ self.class.compile(id)
143
+ end
144
+
145
+ # TODO: Helper methods to write:
146
+ # .prepend, .append - TDD THEM!!!
147
+
148
+
149
+ ####################
150
+ # Utility Methods #
151
+ ####################
152
+
153
+ #TODO: really not sure about this...
154
+ class << self
155
+ private
156
+
157
+ def build(attrs={})
158
+ test_file = allocate
159
+ attrs.each do |k,v|
160
+ raise ArgumentError.new("Unknown attribute: #{k}") unless TestFile.attribute_method?(k.to_sym)
161
+ test_file.instance_variable_set("@#{k}", v) unless v.nil?
162
+ end
163
+ test_file.instance_variable_set("@errors", ActiveModel::Errors.new(test_file))
164
+
165
+ return test_file
166
+ end
167
+
168
+ def parse_response(json)
169
+ attrs = JSON.parse(json)
170
+ build(attrs)
171
+ end
172
+ end
173
+
174
+ def add_all_errors(error_hash)
175
+ error_hash.each do |attribute, messages|
176
+ messages.each do |message|
177
+ errors.add(attribute.to_sym, message)
178
+ end
179
+ end
180
+ end
181
+ end
data/lib/citrulu.rb ADDED
@@ -0,0 +1,19 @@
1
+ Dir[File.expand_path('../citrulu/*.rb', __FILE__)].each{|f| require f}
2
+ Dir[File.expand_path('../faraday/*.rb', __FILE__)].each{|f| require f}
3
+ require 'faraday'
4
+
5
+ module Citrulu
6
+ BASE_URL = "https://www.citrulu.com/api/v1"
7
+ # BASE_URL = "http://localhost:3000/api/v1"
8
+
9
+ def self.connection
10
+ Faraday.new(:url => BASE_URL) do |connection|
11
+ connection.request :url_encoded # form-encode POST params
12
+ connection.response :logger # log requests to STDOUT
13
+ connection.adapter Faraday.default_adapter # make requests with Net::HTTP
14
+ connection.use FaradayMiddleware::RaiseHttpException
15
+
16
+ connection.params[:auth_token] = CITRULU_API_KEY # Authenticate using the user's API key
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ # Adapted from the Instagram ruby gem:
2
+ # https://github.com/Instagram/instagram-ruby-gem/blob/master/lib/faraday/raise_http_exception.rb
3
+
4
+ require 'faraday'
5
+
6
+ module FaradayMiddleware
7
+ class RaiseHttpException < Faraday::Middleware
8
+ def call(env)
9
+ @app.call(env).on_complete do |response|
10
+ case response[:status].to_i
11
+ when 401
12
+ raise Citrulu::AccessDenied, error_message_400(response)
13
+ when 404
14
+ raise Citrulu::NotFound, error_message_400(response)
15
+ when 500
16
+ raise Citrulu::InternalServerError, error_message_500(response, "Something is technically wrong.")
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def error_message_400(response)
24
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{response[:status]}#{error_body(response[:body])}"
25
+ end
26
+
27
+ def error_body(body)
28
+ # body gets passed as a string, not sure if it is passed as something else from other spots?
29
+ if not body.nil? and not body.empty? and body.kind_of?(String)
30
+ body = ::JSON.parse(body)
31
+ end
32
+
33
+ if body.nil?
34
+ nil
35
+ elsif body['meta'] and body['meta']['error_message'] and not body['meta']['error_message'].empty?
36
+ ": #{body['meta']['error_message']}"
37
+ end
38
+ end
39
+
40
+ def error_message_500(response, body=nil)
41
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{[response[:status].to_s + ':', body].compact.join(' ')}"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,189 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'json'
3
+
4
+ describe "TestFile" do
5
+ before(:each) do
6
+ @connection = double("Connection")
7
+ Citrulu.stub(:connection).and_return(@connection)
8
+ stub_const("CITRULU_API_KEY", "Foo")
9
+ @response = double("Response")
10
+ end
11
+
12
+ FILE_JSON = { "compiled_test_file_text"=>"On http://swingoutlondon.co.uk",
13
+ "created_at"=>"2012-03-15T17:57:14Z",
14
+ "domains"=>["swingoutlondon.co.uk"],
15
+ "frequency"=>3600,
16
+ "id"=>2,
17
+ "name"=>"Swing Out London",
18
+ "run_tests"=>true,
19
+ "test_file_text"=>"On http://swingoutlondon.co.uk",
20
+ "tutorial_id"=>nil, "updated_at"=>"2012-10-16T12:58:27Z"}.to_json
21
+
22
+ def stub_file_response(method)
23
+ @response.stub(:body).and_return(FILE_JSON)
24
+ @connection.stub(method).and_return(@response)
25
+ end
26
+
27
+ # TODO: this feels like a big dirty hack...
28
+ def make_test_file(name, options={})
29
+ attrs = FactoryGirl.attributes_for(name, options)
30
+ TestFile.send(:build, attrs)
31
+ end
32
+
33
+ ################
34
+ # Constructors #
35
+ ################
36
+
37
+ describe "initialize" do
38
+ it "should fail if a supplied attribute is invalid" do
39
+ expect{ TestFile.new(:foo => "bar") }.to raise_error(NoMethodError)
40
+ end
41
+ end
42
+
43
+ describe "build" do
44
+ it "should be private" do
45
+ expect{ TestFile.build(:frequency => "1000") }.to raise_error(NoMethodError)
46
+ end
47
+ end
48
+
49
+ #################
50
+ # Class Methods #
51
+ #################
52
+
53
+ describe ".all" do
54
+ before(:each) do
55
+ response_body = [ { id: 2, name: "Swing Out London" },
56
+ { id: 29, name: "Tutorial 6: I'm broken - fix me" }
57
+ ].to_json
58
+ @response.stub(:body).and_return(response_body)
59
+ @connection.stub(:get).and_return(@response)
60
+ end
61
+ it "should return an array" do
62
+ Faraday.stub(:new).and_return @connection
63
+ TestFile.all.should be_an(Array)
64
+ end
65
+ it "should return an array of test_files" do
66
+ TestFile.all.first.should be_a(TestFile)
67
+ end
68
+ end
69
+
70
+ describe ".find" do
71
+ before(:each) do
72
+ stub_file_response(:get)
73
+ end
74
+ it "should return a test_file" do
75
+ pending "The API needs fixing - currently it's returning an array instead of a single JSON hash"
76
+ TestFile.find(1).should be_a(TestFile)
77
+ end
78
+ end
79
+
80
+ describe ".create" do
81
+ before(:each) do
82
+ stub_file_response(:post)
83
+ end
84
+ context "when the file was successfully created" do
85
+ before(:each) do
86
+ @response.stub(:status).and_return(200)
87
+ end
88
+ it "should return a test_file" do
89
+ TestFile.create.should be_a(TestFile)
90
+ end
91
+ end
92
+ context "when the file was not successfully created" do
93
+ before(:each) do
94
+ @response.stub(:status).and_return(422)
95
+ @response.stub(:body).and_return(%({"errors":{"name":["can't be blank"]}}))
96
+ end
97
+ it "should return a test_file" do
98
+ TestFile.create.should be_a(TestFile)
99
+ end
100
+ it "should add the errors onto the test file object" do
101
+ TestFile.create.errors.messages.should == { :name => ["can't be blank"] }
102
+ end
103
+ end
104
+ end
105
+
106
+ describe ".update" do
107
+ before(:each) do
108
+ stub_file_response(:put)
109
+ end
110
+ context "when the file was successfully created" do
111
+ before(:each) do
112
+ @response.stub(:status).and_return(200)
113
+ end
114
+ it "should return a test_file" do
115
+ TestFile.update(1).should be_a(TestFile)
116
+ end
117
+ end
118
+ context "when the file was not successfully created" do
119
+ before(:each) do
120
+ @response.stub(:status).and_return(422)
121
+ @response.stub(:body).and_return(%({"errors":{"name":["can't be blank"]}}))
122
+ stub_file_response(:get)
123
+ end
124
+ it "should return a test_file" do
125
+ pending "Need the API Find to be fixed before this will pass"
126
+ TestFile.update(1).should be_a(TestFile)
127
+ end
128
+ it "should add the errors onto the test file object" do
129
+ pending "Need the API Find to be fixed before this will pass"
130
+ TestFile.update(1).errors.messages.should == { :name => ["can't be blank"] }
131
+ end
132
+ end
133
+ end
134
+
135
+ describe ".delete" do
136
+ before(:each) do
137
+ @connection.stub(:delete)
138
+ end
139
+ it "should return nothing" do
140
+ TestFile.delete(1).should be_nil
141
+ end
142
+ end
143
+
144
+ describe ".compile" do
145
+ before(:each) do
146
+ stub_file_response(:post)
147
+ end
148
+ it "should return a test_file" do
149
+ TestFile.compile(1).should be_a(TestFile)
150
+ end
151
+ end
152
+
153
+ ####################
154
+ # Instance Methods #
155
+ ####################
156
+
157
+ describe "save" do
158
+ it "should create the file if it doesn't exist" do
159
+ TestFile.stub(:create)
160
+ TestFile.should_receive(:create)
161
+
162
+ TestFile.new(name: "foo", test_file_text: "bar", run_tests: true).save
163
+ end
164
+ it "should update the file if it already exists" do
165
+ TestFile.stub(:update)
166
+ TestFile.should_receive(:update)
167
+
168
+ make_test_file(:full_test_file, id: 1).save
169
+ end
170
+ end
171
+
172
+ describe "destroy" do
173
+ it "should delete the file" do
174
+ TestFile.stub(:delete)
175
+ TestFile.should_receive(:delete)
176
+
177
+ make_test_file(:full_test_file, id: 1).destroy
178
+ end
179
+ end
180
+
181
+ describe "compile" do
182
+ it "should compile the file" do
183
+ TestFile.stub(:compile)
184
+ TestFile.should_receive(:compile)
185
+
186
+ make_test_file(:full_test_file, id: 1).compile
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,22 @@
1
+ FactoryGirl.define do
2
+ factory :test_file do
3
+ sequence(:name) { |n| "my first test file#{n}" }
4
+ test_file_text "On http://example.com\n I should see foo"
5
+ run_tests true
6
+
7
+ factory :full_test_file do
8
+ domains ["example.com"]
9
+ frequency 3600
10
+ updated_at "2012-06-06T13:33:20Z"
11
+ created_at "2012-09-24T12:43:15Z"
12
+
13
+ factory :compiled_test_file do
14
+ compiled_test_file_text "On http://example.com\n I should see foo"
15
+ end
16
+
17
+ factory :tutorial_test_file do
18
+ tutorial_id 1
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'simplecov'
5
+ require 'factory_girl'
6
+ require 'citrulu'
7
+
8
+ # Requires supporting files with custom matchers and macros, etc,
9
+ # in ./support/ and its subdirectories.
10
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+ config.after do
14
+ FactoryGirl.reload
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,215 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: citrulu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Duncan Stuart
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: activemodel
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.11.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.11.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: factory_girl
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rdoc
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '3.12'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '3.12'
110
+ - !ruby/object:Gem::Dependency
111
+ name: bundler
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.0.0
126
+ - !ruby/object:Gem::Dependency
127
+ name: jeweler
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: 1.8.4
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: 1.8.4
142
+ - !ruby/object:Gem::Dependency
143
+ name: simplecov
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ description: ! ' Citrulu exposes an api for creating, editing and compiling test files
159
+ (http://www.citrulu.com/api). This gem provides a wrapper around that api which
160
+ allows you to work with TestFile objects locally. '
161
+ email:
162
+ - contact@dxw.com
163
+ - duncan@dxw.com
164
+ executables: []
165
+ extensions: []
166
+ extra_rdoc_files:
167
+ - LICENSE.txt
168
+ - README.md
169
+ files:
170
+ - .document
171
+ - .rspec
172
+ - .simplecov
173
+ - Gemfile
174
+ - Gemfile.lock
175
+ - LICENSE.txt
176
+ - README.md
177
+ - Rakefile
178
+ - VERSION
179
+ - citrulu.gemspec
180
+ - lib/citrulu.rb
181
+ - lib/citrulu/error.rb
182
+ - lib/citrulu/test_file.rb
183
+ - lib/faraday/raise_error.rb
184
+ - spec/citrulu/test_file_spec.rb
185
+ - spec/factories/test_files.rb
186
+ - spec/spec_helper.rb
187
+ homepage: https://github.com/dxw/citrulu-api-ruby.git
188
+ licenses:
189
+ - MIT
190
+ post_install_message:
191
+ rdoc_options: []
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ none: false
196
+ requirements:
197
+ - - ! '>='
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ segments:
201
+ - 0
202
+ hash: 1427762494516547865
203
+ required_rubygems_version: !ruby/object:Gem::Requirement
204
+ none: false
205
+ requirements:
206
+ - - ! '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ requirements: []
210
+ rubyforge_project:
211
+ rubygems_version: 1.8.24
212
+ signing_key:
213
+ specification_version: 3
214
+ summary: Wrapper for the api exposed by Citrulu
215
+ test_files: []