From c8450e044f3455fb548c495096ddd3f6884aa032 Mon Sep 17 00:00:00 2001 From: Dmitri Garbuzov Date: Fri, 30 Jul 2010 21:17:25 -0400 Subject: [PATCH] Added rspec integration tests --- app/controllers/questions_controller.rb | 2 +- spec/integration/choices_spec.rb | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spec/integration/densities_spec.rb | 8 ++++++++ spec/integration/prompts_spec.rb | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spec/integration/questions_spec.rb | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spec/integration/visitors_spec.rb | 4 ++++ spec/models/question_spec.rb | 5 ++++- spec/support/db_support.rb | 10 ++++++++++ spec/support/integration_support.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 634 insertions(+), 2 deletions(-) create mode 100644 spec/integration/densities_spec.rb create mode 100644 spec/support/db_support.rb create mode 100644 spec/support/integration_support.rb diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 213dd11..529f147 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -117,7 +117,7 @@ class QuestionsController < InheritedResources::Base @question = current_user.questions.find(params[:id]) - puts "redis key is::::: #{redis_key}" + # puts "redis key is::::: #{redis_key}" @question.send_later :export_and_delete, type, :response_type => response_type, :redis_key => redis_key, :delete_at => 3.days.from_now diff --git a/spec/integration/choices_spec.rb b/spec/integration/choices_spec.rb index e44943a..7cccd6e 100644 --- a/spec/integration/choices_spec.rb +++ b/spec/integration/choices_spec.rb @@ -1,4 +1,199 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "Choices" do + include IntegrationSupport + + describe "POST 'create'" do + before(:each) do + @question = Factory.create(:aoi_question, :site => @api_user) + @visitor = Factory.create(:visitor, :site => @api_user) + end + + describe "succeeds and returns a new choice" do + + specify "given no optional arguments"# do @params = nil end + + specify "given only data" do + @params = { :choice => { :data => "hey"} } + end + + specify "given only the visitor identifier" do + @params = { :choice => { :visitor_identifier => @visitor.identifier } } + end + + after do + post_auth question_choices_path(@question, :format => 'xml'), @params + response.should be_success + response.should have_tag "choice" + end + end + + it "correctly sets the supplied attributes" do + @params = { + :choice => { + :visitor_identifier => @visitor.identifier, + :data => "foo", + :local_identifier => "bar" } } + + post_auth question_choices_path(@question, :format => 'xml'), @params + + response.should be_success + response.should have_tag "choice creator-id", @visitor.id.to_s + response.should have_tag "choice data", "foo" + response.should have_tag "choice local-identifier", "bar" + end + end + + describe "PUT 'flag'" do + before do + @question = Factory.create(:aoi_question, :site => @api_user) + @choice = Factory.create(:choice, :question => @question) + @choice.activate! + end + + it "should return the deactivated choice given no arguments" do + put_auth flag_question_choice_path(@question, @choice, :format => 'xml') + + response.should be_success + response.should have_tag "choice active", "false" + end + + it "should return the deactivated choice given an explanation" do + put_auth flag_question_choice_path(@question, @choice, :format => 'xml'), :explanation => "foo" + + response.should be_success + response.should have_tag "choice active", "false" + end + + context "when trying to flag another site's choices" do + before do + # this is ugly + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + put_auth flag_question_choice_path(@question, @choice, :format => 'xml'), :explanation => "foo" + response.should_not be_success + end + + after { @api_user = @orig_user } + end + end + + describe "GET 'index'" do + before(:each) do + @question = Factory.create(:aoi_question, :site => @api_user, :choices => [], :prompts => []) + 5.times{ Factory.create(:choice, :question => @question).deactivate! } + 5.times{ Factory.create(:choice, :question => @question).activate! } + end + + it "should return all active choices given no optional parameters" do + get_auth question_choices_path(@question, :format => 'xml') + + response.should be_success + response.should have_tag "choices choice", 5 + end + + it "should return all choices if include_inactive is set" do + get_auth question_choices_path(@question, :format => 'xml'), :include_inactive => true + + response.should be_success + response.should have_tag "choices choice", 10 + response.should have_tag "choices choice active", "false" + end + + + it "should return 3 choices when limt is set to 3" do + get_auth question_choices_path(@question, :format => 'xml'), :limit => 3 + + response.should be_success + response.should have_tag "choices choice", 3 + end + + it "should return the remaining choices when offset is provided" do + get_auth question_choices_path(@question, :format => 'xml'), :offset => 2, :limit => 4 + + response.should be_success + response.should have_tag "choices choice", 3 + end + + context "when trying to access another site's choices" do + before do + @other_user = Factory(:email_confirmed_user) + @other_question = Factory.create(:aoi_question, :site => @other_user) + 5.times{ Factory.create(:choice, :question => @other_question) } + end + + it "should fail" do + pending("user scope") do + get_auth question_choices_path(@question, :format => 'xml'), :offset => 2, :limit => 4 + response.should_not be_success + end + end + end + + end + + describe "GET 'show'" do + before do + @question = Factory.create(:aoi_question, :site => @api_user) + @choice = Factory.create(:choice, :question => @question) + end + + it "should return a choice" do + get_auth question_choice_path(@question, @choice, :format => 'xml') + + response.should be_success + response.should have_tag "choice", 1 + end + + context "when requesting a choice from another site" do + before do + @other_user = Factory(:email_confirmed_user) + @other_question = Factory.create(:aoi_question, :site => @other_user) + @other_choice = Factory.create(:choice, :question => @other_question) + end + + it "should fail" do + pending("user scope") do + get_auth question_choice_path(@other_question, @other_choice, :format => 'xml') + response.should_not be_success + end + end + end + + end + + describe "PUT 'update'" do + before do + @question = Factory.create(:aoi_question, :site => @api_user) + @choice = Factory.create(:choice, :question => @question) + @choice.activate! + end + + it "should succeed given valid attributes" do + params = { :choice => { :data => "foo" } } + put_auth question_choice_path(@question, @choice, :format => 'xml'), params + response.should be_success + end + + context "when updatng another site's choice" do + before do + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + pending("user scope") do + params = { :choice => { :data => "foo" } } + put_auth question_choice_path(@question, @choice, :format => 'xml'), params + response.should_not be_success + end + end + + after { @api_user = @orig_user } + end + end + end diff --git a/spec/integration/densities_spec.rb b/spec/integration/densities_spec.rb new file mode 100644 index 0000000..3e5167b --- /dev/null +++ b/spec/integration/densities_spec.rb @@ -0,0 +1,8 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe "Densities" do + include IntegrationSupport + + describe "index" + +end diff --git a/spec/integration/prompts_spec.rb b/spec/integration/prompts_spec.rb index 7bd9389..3eac043 100644 --- a/spec/integration/prompts_spec.rb +++ b/spec/integration/prompts_spec.rb @@ -1,4 +1,170 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +# to do: figure out future-prompts +# clean up repeated code + describe "Prompts" do + include IntegrationSupport + + describe "GET 'show'" do + before do + @question = Factory.create(:aoi_question, :site => @api_user) + @prompt = @question.prompts.first + end + + it "returns a prompt object" do + get_auth question_prompt_path(@question, @prompt, :format => 'xml') + response.should be_success + response.should have_tag "prompt", 1 + end + end + + describe "POST 'skip'" do + before do + @visitor = Factory.create(:visitor, :site => @api_user, :identifier => "foo") + @question = Factory.create(:aoi_question, + :site => @api_user, + :choices => [], + :prompts => []) + 3.times{ Factory.create(:choice, :question => @question).activate! } + info = @question.reload.get_optional_information(:with_appearance => true, + :with_prompt => true, + :visitor_identifier => @visitor.identifier ) + @appearance_id = info[:appearance_id] + @prompt_id = info[:picked_prompt_id] + end + + it "should return a new skip object given no optional parameters" do + post_auth skip_question_prompt_path(@question.id, @prompt_id, :format => 'xml') + response.should be_success + response.should have_tag "skip", 1 + end + + it "should correctly set the optional attributes of the skip object" do + pending("shouldn\'t this set appearance_id?") do + params = { + :skip => { + :visitor_identifier => @visitor.identifier, + :skip_reason => "bar", + :appearance_lookup => @appearance_id, + :time_viewed => 47 } } + post_auth skip_question_prompt_path(@question, @prompt_id, :format => 'xml'), params + response.should be_success + response.should have_tag "skip", 1 + response.should have_tag "skip appearance-id", @appearance_id.to_s + response.should have_tag "skip skip-reason", "bar" + response.should have_tag "skip time-viewed", "47" + response.should have_tag "skip skipper-id", @visitor.id.to_s + end + end + + it "should return a prompt object if next_prompt is set" do + params = { + :next_prompt => { + :visitor_identifier => @visitor.identifier, + :with_appearance => true, + :algorithm => "catchup", + :with_visitor_stats => true } } + post_auth skip_question_prompt_path(@question, @prompt_id, :format => 'xml'), params + response.should be_success + response.should have_tag "prompt", 1 + response.should have_tag "prompt appearance_id", /.+/ + response.should have_tag "prompt visitor_votes", /\d+/ + response.should have_tag "prompt visitor_ideas", /\d+/ + end + + context "when trying to skip another site's questions" do + before do + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + post_auth skip_question_prompt_path(@question.id, @prompt_id, :format => 'xml') + response.should_not be_success + end + + after { @api_user = @orig_user } + end + end + + describe "POST 'vote'" do + before do + # dry this up + @visitor = Factory.create(:visitor, :site => @api_user, :identifier => "foo") + @question = Factory.create(:aoi_question, + :site => @api_user, + :choices => [], + :prompts => []) + 3.times{ Factory.create(:choice, :question => @question).activate! } + info = @question.reload.get_optional_information(:with_appearance => true, + :with_prompt => true, + :visitor_identifier => @visitor.identifier ) + @appearance_id = info[:appearance_id] + @prompt_id = info[:picked_prompt_id] + end + + it "should fail without the required 'direction' parameter" do + post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml') + response.should_not be_success + end + + it "should return a new vote object given no optional parameters" do + params = { :vote => { :direction => "left" } } + post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml'), params + response.should be_success + response.should have_tag "vote", 1 + end + + it "should correctly set the optional attributes of the vote object" do + pending("also has nil appearance id") do + params = { + :vote => { + :visitor_identifier => @visitor.identifier, + :direction => "right", + :appearance_lookup => @appearance_id, + :time_viewed => 47 } } + post_auth vote_question_prompt_path(@question, @prompt_id, :format => 'xml'), params + response.should be_success + response.should have_tag "vote", 1 + response.should have_tag "vote appearance-id", @appearance_id.to_s + response.should have_tag "vote time-viewed", "47" + response.should have_tag "vote voter-id", @visitor.id.to_s + end + end + + # copy-paste from vote --> shared behavior? + it "should return a prompt object if next_prompt is set" do + params = { + :vote => { + :direction => "left" }, + :next_prompt => { + :visitor_identifier => @visitor.identifier, + :with_appearance => true, + :algorithm => "catchup", + :with_visitor_stats => true } } + post_auth vote_question_prompt_path(@question, @prompt_id, :format => 'xml'), params + response.should be_success + response.should have_tag "prompt", 1 + response.should have_tag "prompt appearance_id", /.+/ + response.should have_tag "prompt visitor_votes", /\d+/ + response.should have_tag "prompt visitor_ideas", /\d+/ + end + + context "when trying to vote on another site's questions" do + before do + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + params = { :vote => { :direction => "left" } } + post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml'), params + response.should_not be_success + end + + after { @api_user = @orig_user } + end + + end end diff --git a/spec/integration/questions_spec.rb b/spec/integration/questions_spec.rb index 95bc4c0..a3a9e69 100644 --- a/spec/integration/questions_spec.rb +++ b/spec/integration/questions_spec.rb @@ -1,4 +1,208 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "Questions" do + include IntegrationSupport + before do + 3.times{ Factory.create(:aoi_question, :site => @api_user) } + end + + describe "GET 'index'" do + it "should return an array of questions" do + get_auth questions_path(:format => 'xml') + response.body.should have_tag("questions question", 3) + response.should be_success + end + + it "should not return the questions of other api users" do + pending ("doesn't scope to the level of the user") do + other_user = Factory(:email_confirmed_user) + Factory.create(:aoi_question, :site => other_user) + get_auth questions_path + response.should be_success + response.body.should_not have_tag("question") + end + end + end + + describe "GET 'new'" do + it "should return an empty question object" do + get_auth new_question_path(:format => 'xml') + response.should be_success + response.body.should have_tag "question", 1 + response.body.should have_tag "question name", "" + response.body.should have_tag "question creator-id", "" + response.body.should have_tag "question created-at", "" + end + end + + describe "POST 'create'" do + before { @visitor = Factory.create(:visitor, :site => @api_user) } + + it "should fail when required parameters are omitted" do + post_auth questions_path(:format => 'xml') + response.should_not be_success + end + + it "should return a question object given no optional parameters" do + pending("choice count doesn't reflect # seed ideas") do + params = { :question => { :visitor_identifier => @visitor.identifier, :ideas => "foo\r\nbar\r\nbaz" } } + + post_auth questions_path(:format => 'xml'), params + + response.should be_success + response.should have_tag "question", 1 + response.should have_tag "question creator-id", @visitor.id.to_s + response.should have_tag "question choices-count", 3 + end + end + + it "should correctly set optional attributes" do + params = { + :question => { + :visitor_identifier => @visitor.identifier, + :ideas => "foo\r\nbar\r\nbaz", + :name => "foo", + :local_identifier => "bar", + :information => "baz" } } + + post_auth questions_path(:format => 'xml'), params + response.should be_success + response.should have_tag "question", 1 + response.should have_tag "question creator-id", @visitor.id.to_s + # response.should have_tag "question choices-count", 3 + response.should have_tag "question name", "foo" + response.should have_tag "question local-identifier", "bar" + response.should have_tag "question information", "baz" + end + end + + describe "POST 'export'" do + before { @question = Factory.create(:aoi_question, :site => @api_user) } + + it "should fail without any of the required parameters" do + post_auth export_question_path(@question, :format => 'xml') + response.should be_success + response.body.should =~ /Error/ + end + + it "should fail given invalid parameters" do + params = { :type => "ideas", :response_type => "foo", :redisk_key => "bar" } + post_auth export_question_path(@question, :format => 'xml') + response.should be_success + response.body.should =~ /Error/ + end + + it "should succeed given valid parameters" do + params = { :type => "ideas", :response_type => "redis", :redis_key => "foo" } + post_auth export_question_path(@question, :format => 'xml'), params + response.should be_success + response.body.should =~ /Ok!/ + end + end + + describe "GET 'show'" do + before { @question = Factory.create(:aoi_question, :site => @api_user) } + + it "should succeed given no optional parameters" do + get_auth question_path(@question, :format => 'xml') + response.should be_success + response.should have_tag "question", 1 + response.should have_tag "question id", @question.id.to_s + end + + it "should correctly set optional parameters" do + @visitor = Factory.create(:visitor, :site => @api_user) + params = { + :visitor_identifier => @visitor.identifier, + :with_prompt => true, + :with_appearance => true, + :with_visitor_stats => true } + get_auth question_path(@question, :format => 'xml'), params + response.should be_success + response.should have_tag "question", 1 + response.should have_tag "question id", @question.id.to_s + response.should have_tag "question picked_prompt_id" + response.should have_tag "question appearance_id" + response.should have_tag "question visitor_votes" + response.should have_tag "question visitor_ideas" + end + + it "should fail if 'with_prompt' is set but 'visitor_identifier' not provided" do + pending("figure out argument dependencies") do + params = { :with_prompt => true } + get_auth question_path(@question, :format => 'xml'), params + response.should_not be_success + end + end + + context "GET 'show' trying to view others sites' questions" + before do + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + pending("user scope") do + get_auth question_path(@question, :format => 'xml') + response.should_not be_success + end + end + + after { @api_user = @orig_user } + end + + describe "PUT 'update'" do + before { @question = Factory.create(:aoi_question, :site => @api_user) } + + it "should succeed give valid attributes" do + params = { + :question => { + :active => false, + :information => "foo", + :name => "bar", + :local_identifier => "baz" } } + put_auth question_path(@question, :format => 'xml'), params + response.should be_success + end + + it "should not be able to change the site id" do + pending("needs attr_protected") do + original_site_id = @question.site_id + params = { :question => { :site_id => -1 } } + put_auth question_path(@question, :format => 'xml'), params + @question.reload.site_id.should == original_site_id + end + end + + it "should ignore protected attributes" do + params = { :question => { :votes_count => 999 } } + put_auth question_path(@question, :format => 'xml'), params + response.should be_success + @question.reload.site_id.should_not == 999 + end + + context "when updatng another site's question" do + before do + @orig_user = @api_user + @api_user = Factory(:email_confirmed_user) + end + + it "should fail" do + pending("user scope") do + params = { :question => { :name => "foo" } } + put_auth question_path(@question, :format => 'xml'), params + response.should_not be_success + end + end + + after { @api_user = @orig_user } + end + end + + describe "GET 'all_object_info_totals_by_date'" do + end + + describe "GET 'object_info_totals_by_date'" do + end + end diff --git a/spec/integration/visitors_spec.rb b/spec/integration/visitors_spec.rb index 8b1911e..5e718fe 100644 --- a/spec/integration/visitors_spec.rb +++ b/spec/integration/visitors_spec.rb @@ -1,4 +1,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "Visitors" do + include IntegrationSupport + + describe "index" + end diff --git a/spec/models/question_spec.rb b/spec/models/question_spec.rb index 91c5089..4a119cf 100644 --- a/spec/models/question_spec.rb +++ b/spec/models/question_spec.rb @@ -1,7 +1,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Question do - + include DBSupport + it {should belong_to :creator} it {should belong_to :site} it {should have_many :choices} @@ -292,6 +293,7 @@ describe Question do prompt.left_choice.deactivate! @catchup_q.choose_prompt.should_not == prompt1 end + after(:all) { truncate_all } end context "exporting data" do @@ -416,6 +418,7 @@ describe Question do end + after(:all) { truncate_all } end end diff --git a/spec/support/db_support.rb b/spec/support/db_support.rb new file mode 100644 index 0000000..81181e0 --- /dev/null +++ b/spec/support/db_support.rb @@ -0,0 +1,10 @@ +module DBSupport + + # this is useful after a before :all block fills the db with stuff + def truncate_all + (ActiveRecord::Base.connection.tables - ["schema_migrations"]).each do |table| + ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table};") + end + end + +end diff --git a/spec/support/integration_support.rb b/spec/support/integration_support.rb new file mode 100644 index 0000000..e808aa2 --- /dev/null +++ b/spec/support/integration_support.rb @@ -0,0 +1,42 @@ +module IntegrationSupport + + # todo: make automatically included in integration tests + Spec::Runner.configure do |config| + config.before(:each, :type => :integration) do + @api_user = Factory(:email_confirmed_user) + end + end + + def get_auth(path, parameters = {}, headers = {}) + auth_wrap(:get, path, parameters, headers) + end + + def put_auth(path, parameters = {}, headers = {}) + auth_wrap(:put, path, parameters, headers) + end + + def post_auth(path, parameters = {}, headers = {} ) + auth_wrap(:post, path, parameters, headers) + end + + def delete_auth(path, parameters = {}, headers = {}) + auth_wrap(:delete, path, parameters, headers) + end + + def head_auth(path, parameters = {}, headers = {}) + auth_wrap(:head, path, parameters, headers) + end + + private + def auth_wrap(method, path, parameters, headers) + return nil unless [:get, :put, :post, :delete, :head].include? method + + auth = ActionController::HttpAuthentication::Basic.encode_credentials(@api_user.email, @api_user.password) + headers.merge!(:authorization => auth) + # headers.merge!(:content_type => "application/xml", :authorization => auth) + # parameters.merge!(:format => 'xml') + + send(method, path, parameters, headers) + end +end + -- libgit2 0.21.2