diff --git a/.gitignore b/.gitignore index d900dee..d106f14 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ config.yml .bundle/ db/*.sqlite3 +.rvmrc diff --git a/Gemfile b/Gemfile index 1b0f62c..08ef1cf 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,13 @@ gem "rake" group :development do gem "shotgun" gem "sqlite3-ruby", "~> 1.3.3", :require => "sqlite3" + # test dependencies + gem "rack-test" + gem "assert_json" + gem "turn" + gem "shoulda-context" + gem "factory_girl", "~> 2.2.0" + gem "database_cleaner" end group :production do diff --git a/Gemfile.lock b/Gemfile.lock index abaf85a..042795b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,19 +11,28 @@ GEM arel (~> 2.0.2) tzinfo (~> 0.3.23) activesupport (3.0.6) + ansi (1.3.0) arel (2.0.9) + assert_json (0.1.1) + activesupport authlogic (2.1.6) activesupport builder (2.1.2) daemons (1.1.4) + database_cleaner (0.7.0) eventmachine (0.12.10) + factory_girl (2.2.0) + activesupport i18n (0.5.0) json (1.5.1) mysql (2.8.1) rack (1.2.2) + rack-test (0.6.0) + rack (>= 1.0) rake (0.8.7) shotgun (0.9) rack (>= 1.0) + shoulda-context (1.0.0.beta1) sinatra (1.2.3) rack (~> 1.1) tilt (>= 1.2.2, < 2.0) @@ -35,6 +44,8 @@ GEM eventmachine (>= 0.12.6) rack (>= 1.0.0) tilt (1.2.2) + turn (0.8.2) + ansi (>= 1.2.2) tzinfo (0.3.26) PLATFORMS @@ -42,11 +53,17 @@ PLATFORMS DEPENDENCIES activerecord (~> 3.0.6) + assert_json authlogic + database_cleaner + factory_girl (~> 2.2.0) json (~> 1.5.1) mysql (~> 2.8.1) + rack-test rake shotgun + shoulda-context sinatra sqlite3-ruby (~> 1.3.3) thin + turn diff --git a/Rakefile b/Rakefile index 0f4b6ef..4f9c8e2 100644 --- a/Rakefile +++ b/Rakefile @@ -4,3 +4,14 @@ require 'authlogic' require 'tasks/db' require 'tasks/permissions' +require 'rake' +require 'rake/testtask' + + +desc "Run all tests" +Rake::TestTask.new do |t| + t.libs << "test" + t.test_files = FileList['test/*_test.rb'] + t.ruby_opts = ['-r test_helper'] +end + diff --git a/database_example.yml b/database_example.yml index 8c94c7f..756a12b 100644 --- a/database_example.yml +++ b/database_example.yml @@ -1,14 +1,11 @@ -#example for mysql -#database: api -#adapter: mysql -#host: localhost -#username: db_user -#password: db_pass -#encoding: utf8 +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +test: + adapter: sqlite3 + database: db/test.sqlite3 -#example for sqlite3 -#adapter: sqlite3 -#database: db/development.sqlite3 -#pool: 5 -#timeout: 5000 diff --git a/lib/assertions.rb b/lib/assertions.rb new file mode 100644 index 0000000..28b72b0 --- /dev/null +++ b/lib/assertions.rb @@ -0,0 +1,14 @@ +module Api + module Assertions + + def assert_status(expected, response=last_response) + assert_equal expected, response.status, "Expected a #{expected} status, got #{response.status} instead" + end + + def assert_body(json_string=last_response.body, &block) + assert_json(json_string, &block) + end + + end + +end diff --git a/lib/config.rb b/lib/config.rb index f361654..bf6a038 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -14,7 +14,9 @@ def connection end end -ActiveRecord::Base.establish_connection(YAML.load_file(APP_ROOT + '/database.yml')) +db_config = YAML.load_file(APP_ROOT + '/database.yml')[settings.environment.to_s] + +ActiveRecord::Base.establish_connection(db_config) require APP_ROOT + '/lib/models.rb' require APP_ROOT + '/lib/helpers.rb' diff --git a/tasks/db.rb b/tasks/db.rb index b08b3b4..01bf7c4 100644 --- a/tasks/db.rb +++ b/tasks/db.rb @@ -1,4 +1,5 @@ -config = YAML.load_file('database.yml') +env = ENV['RACK_ENV'] || "development" +config = YAML.load_file('database.yml')[env] #code borrowed from here: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake diff --git a/tasks/permissions.rb b/tasks/permissions.rb index 698eccb..d1fcace 100644 --- a/tasks/permissions.rb +++ b/tasks/permissions.rb @@ -1,4 +1,5 @@ -config = YAML.load_file('database.yml') +env = ENV['RACK_ENV'] || "development" +config = YAML.load_file('database.yml')[env] namespace :permissions do desc "Looks up all columns from tables beginning with data_ and creates CRUD Permissions for them" diff --git a/test/base_test.rb b/test/base_test.rb new file mode 100644 index 0000000..443449a --- /dev/null +++ b/test/base_test.rb @@ -0,0 +1,12 @@ +class BaseTest < Test::Unit::TestCase + + context "GET '/'" do + setup { get '/' } + + should "return an error" do + assert_status 400 + assert_body { |json| json.element "error", "Wrong url format." } + end + end + +end diff --git a/test/district_test.rb b/test/district_test.rb new file mode 100644 index 0000000..326587f --- /dev/null +++ b/test/district_test.rb @@ -0,0 +1,27 @@ +class DistrictTest < Test::Unit::TestCase + + def setup + super + @source = '/district' + api_user.permissions = create_permissions_for(District, :read) + FactoryGirl.create(:district, :number => 1, :name => "Zentrum") + FactoryGirl.create(:district, :number => 2, :name => "West") + end + + test :get, '/districts' do + assert_status 200 + assert_equal 2, last_result["data"].size + end + + test :get, '/districts/1' do + assert_status 200 + assert_json(last_response.body) do + has "id", 1 + has "number", 1 + has "name", "Zentrum" + has "created_at" + has "updated_at" + end + end + +end diff --git a/test/factories.rb b/test/factories.rb new file mode 100644 index 0000000..de9a89a --- /dev/null +++ b/test/factories.rb @@ -0,0 +1,23 @@ +FactoryGirl.define do + + factory :user do + email "test@example.com" + #password_salt { Authlogic::Random.hex_token } + #crypted_password { Authlogic::CryptoProviders::Sha512.encrypt("test1234" + password_salt) } + single_access_token { Authlogic::Random.friendly_token } + persistence_token { Authlogic::Random.hex_token } + perishable_token { Authlogic::Random.friendly_token } + password "test" + password_confirmation "test" + end + + factory :permission do + # nothing + end + + factory :district do + sequence(:name) {|n| "district-#{n}"} + sequence(:number) + end + +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..206d95b --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,85 @@ +# add /lib to loadpath +$LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__)) + +ENV['RACK_ENV'] = 'test' + +require 'api' +require 'test/unit' +require 'assert_json' +require 'rack/test' +require 'turn' +require 'shoulda-context' +require 'assertions' +require 'factory_girl' +require 'authlogic/test_case' +require 'factories' +require 'database_cleaner' + + +DatabaseCleaner.strategy = :transaction +DatabaseCleaner.clean_with(:truncation) + + +class Test::Unit::TestCase + include Rack::Test::Methods + include AssertJson + include Api::Assertions + + def setup + DatabaseCleaner.start + end + + def teardown + DatabaseCleaner.clean + end + + def app + Sinatra::Application + end + + # + # some dslish test stuff + # + + def self.test(verb, resource, &block) + define_method :"test #{verb.to_s.upcase} to \'#{resource}\'" do + send(verb, [@source, resource].join) + instance_eval(&block) + end + + end + + # + # helper and utility functions for testing + # + + # creates and returns permissions of the given access type for all columns of the given model + def create_permissions_for(klass, access) + _, source, table = klass.table_name.split("_") + klass.column_names.map do |cname| + FactoryGirl.create(:permission, :access => access, :source => source, :table => table, :column => cname) + end + end + + # shortcut to the parsed JSON body of the last_response + def last_result + JSON.parse(last_response.body) + end + + # returns the current @user or creates one with default values via FactoryGirl + def api_user + @user ||= FactoryGirl.create(:user) + end + + # returns the api_user's api_key + def api_key + api_user && api_user.single_access_token + end + + # override rack-test's get method in order to add some default values + def get(url, opts={}) + opts[:api_key] ||= api_key + super(url, opts) + end + +end