rails functional test will not destroy - ruby-on-rails-3.1

I have a functional test that keeps failing and I'm not sure why. This is part of a forum and the test is to ensure that the author of a post is allowed to delete their own posts.
I am able to destroy the post in the console and in the browser when I try manually, I just can't figure out what is going wrong.
Here is the destroy action of the controller:
def destroy
#post = Post.find(params[:id])
if #post.player_id == current_player || current_player.admin == true # I can't delete anyone else's posts unless I am the administrator.
if #post.topic.posts_count > 1 # if topic is more than one post, delete just the post
#post.destroy
flash[:notice] = "Post was successfully destroyed."
redirect_to topic_path(#post.topic)
else # else, if the topic is only one post, delete the whole thing
#post.topic.destroy
flash[:notice] = "Topic was successfully deleted."
redirect_to forum_path(#post.forum)
end
else # You are not the admin or the topic starter
flash[:notice] = "You do not have rights to delete this post."
redirect_to topic_path(#post.topic)
end
end
Here is the posts.yml file:
one:
id: 1
body: MyText
forum_id: 1
topic_id: 1
player_id: 2
two:
id: 2
body: MyText
forum_id: 1
topic_id: 1
player_id: 2
three:
id: 3
body: MyText
forum_id: 1
topic_id: 2
player_id: 3
Here is the test that keeps failing:
test "should destroy post as author" do
sign_in players(:player2)
assert_difference('Post.count', -1) do # Line 41
delete :destroy, :id => posts(:one)
end
assert_redirected_to topic_url(assigns(:topic))
end
And here is the error I'm getting:
1) Failure: test_should_destroy_post_as_author(PostsControllerTest) [../test/functional/posts_controller_test.rb:41]:
"Post.count" didn't change by -1.
<2> expected but was <3>.
I would greatly appreciate any help with this. I feel like I'm hitting my head against a wall when I'm sure the answer is something simple that I'm missing. Thanks in advance.

I'm not sure why that particular wording is not working, but I fixed it so that when I destroy the post like I do in the console, the test passes.
Instead of: delete :destroy, :id => #post
I used: Post.destroy(#post)

Related

Rails 5 API - Modifying the 'index' response object

I have a simple index function
def index
#campaign = Campaign.find_by_id(params[:campaign_id])
#characters = #campaign.characters
render json: {
characters: #characters
}
end
This works as intended, but one of the attributes is an id that is a reference to another table. To avoid the front-end having to solve for this I would prefer the backend to respond with the correct details.
Temporarily I have handled this in the create method
def create
#campaign = Campaign.find_by_id(params[:campaign_id])
#charClass = CharClass.find_by_id(params[:character_char_class_id]).class_name
#character = #campaign.characters.new(character_params)
#character.char_class_id = params[:character_char_class_id]
if #character.save!
render status: 201, json: {
message: "Successfull added this character to the campaign!",
character_name: #character.character_name + ' the ' + #charClass,
character_class: #charClass,
character_level: #character.character_level,
character_experience: #character.character_experience,
character_gold: #character.character_gold,
character_perks: get_names(#character.character_perks),
}
else
render status: 404, json: {
message: "Something went wrong: Check line 24 of the Character Controller"
}
end
end
However, this feels wrong because Characters already knows of the Char_Class relation. (Removed useless info)
create_table "characters", force: :cascade do |t|
t.string "character_class" # I added this
t.integer "char_class_id" # This was already here
t.index ["campaign_id"], name: "index_characters_on_campaign_id"
t.index ["char_class_id"], name: "index_characters_on_char_class_id"
end
So I am able to do something like Character.first.charChass.class_name and I will get the raw text output, as you see in the create: But how could I do this within the controller (or model?)
I will be doing a flow like this for numerous models so I am thinking I won't want to keep with this method.

Handling failures in data driven testing using rspec

I am using rspec to do some data driven testing. My test reads from a csv file, grabs an entry which is inserted into the text box on the page and is then compared to expected text which is also read from the csv file. All this is working as expected, I am able to read and compare without any issues.
Below is my code:
Method for reading csv file:
def user_data
user_data = CSV.read Dir.pwd + '/user_data.csv'
descriptor = user_data.shift
descriptor = descriptor.map { |key| key.to_sym }
user_data.map { |user| Hash[ descriptor.zip(user) ] }
end
Test:
describe "Text box tests" do
before :all do
#homepage = Homepage.new
end
it "should display the correct name" do
visit('http://my test url')
sleep 2
user_data.each do |entry|
#homepage.enter_name(entry[:name])
#homepage.click_go()
sleep 2
begin
expect(page).to have_css("#firstname", text: entry[:expected_name])
end
end
end
end
The problem is with failures. If I have a failure with one of the tests (i.e the expected text is not displayed on the page) then the test stops and all subsequent entries in the csv are not tested. If I put in a rescue after the expect statement like this:
rescue Exception => error
puts error.message
Then the error is logged to the console, however at the end of my test run it says no failures.
So basically I am looking for is, in the event of a failure for my test to keep running(until all entries in the csv have been covered), but for the test run to be marked as failed. Does anyone know how I can achieve this?
Try something like this:
context "when the user is on some page" do
before(:context) { visit('http://example.org/') }
user_data.each do |entry|
it "should display the correct name: #{entry[:name]}" do
#homepage.enter_name(entry[:name])
#homepage.click_go
expect(page).to have_css("#firstname", text: entry[:expected_name])
end
end
end
You will also need to change def user_data to def self.user_data
I would advise mapping over the entries and calling the regular capybara method has_css? instead of the rspec helper method. It would look like this:
results = user_data.map do |entry|
#homepage.enter_name(entry[:name])
#homepage.click_go()
sleep 2
page.has_css?("#firstname", text: entry[:expected_name])
end
expect(results.all?) to be_truthy
if you want to keep track of which ones failed, you cann modify it a bit:
missing_entries = []
user_data.each do |entry|
#homepage.enter_name(entry[:name])
#homepage.click_go()
sleep 2
has_entry = page.has_css?("#firstname", text: entry[:expected_name])
unless has_entry
missing_entries.push entry[:expected_name]
end
end
expect(missing_entries).to be_empty

Trying to pull from API with Ruby -- how to pass variable into string?

Im trying to practice pulling APIs with Ruby. Im trying to pull videogame news from Steam.
Below is my code.
The idea is, when the program is ran, the the user is prompted to enter a game ID between 200 and 440.
Anything not in between dont exist or the numbers arent continuous.
Anyway, Im trying to pass the gameID variable into the string:
"http://api.steampowered.com/ISteamNews/GetNewsForApp/v0002/?appid=#{gameID}&count=5&maxlength=300&format=json"
The string is wrapped in a function. When I try to run the program, the error says wrong number of arguments ( 0 for 1 ).
What am i doing wrong, and what am I missing? Many thanks in advance as usual :)
*been doing nothing but asking questions so far, hope to contribute someday once I get better :)
require 'json'
require 'HTTParty'
puts "----------------------------------------------------------"
puts "Welcome to my practice"
puts "The purpose of this exercise is to use the SteamAPI"
puts "to pull videogame news from Steam"
puts "----------------------------------------------------------"
reset = true
while reset
puts "Please enter a game ID between 200 - 440"
gameID = gets.to_i
if gameID < 200
puts "--Invalid input--"
reset = true
elsif gameID > 400
puts "--Invalid input--"
reset= true
else
reset = false
end
end
puts "--------------------Loading API----------------------------"
def get_news( gameID )
string = "http://api.steampowered.com/ISteamNews/GetNewsForApp/v0002/?appid=#{gameID}&count=5&maxlength=300&format=json"
page = HTTParty.get( string )
browse = page["appnews"]["newsitems"]
browse.map do |content|
{title: content["title"], contents: content["contents"]}
end
end
def display_story( content )
puts "Title: #{content[:title]}"
puts "--------------------"
puts " #{content[:contents]}"
puts "--------------------"
end
get_news.each do |content|
display_story( content )
end
You've defined get_news to take a gameID argument, but you haven't passed it anything. At the end of your file, you need get_news(gameID).each.

Not all methods are getting called Sinatra

I am building a Ruby app using Sinatra and the Twilio api.
Over a phone call to my assigned Twilio number, the user gets prompted to record an audio message. Once that message is recored the user gets redirected to the following route where if the user dials 1 (or anything else), they should get redirected to their feed of msgs, but if the user dials 2, then the user's message gets deleted and should get redirected to a route where they can record a new message.
Here is my route:
get '/playback/handle-recording/:recordingSID' do
if params['Digits'] = '2'
delete(params['recordingSID'])
deletedMsg = "Audio deleted."
getRecord(deletedMsg)
else
getFeed()
end
end
helper methods:
helpers do
def delete(recording)
recording = client().account.recordings.get(recording)
recording.delete
end
def getFeed()
redirect '/feed'
end
def getRecord(appendMsg)
Twilio::TwiML::Response.new do |response|
if appendMsg
response.Say appendMsg
end
response.Say "Record your message."
response.Record :maxLength => '5', :trim => "trim-silence", :playBeep => "true", :action => '/playback', :method => 'get'
end.text
end
end
My issue is that whether the user lands in the "if" or the "else" the first method, getRecord(deletedMsg) is the one that gets called, and not the getFeed().
How can I fix my route so that if the user lands in the else he does get redirected to his feed page and not to the getRecords method.
Are you sure they're actually making it into the else? Ruby won't just randomly not execute what's in there for no good reason.
One thing you may want to look at is you are assigning, not comparing the params value:
if params['Digits'] = '2'
You'll want to do:
if params['Digits'] == '2'
That could definitely lead to some strange behavior in an if statement, like, for instance always executing one path.

The Wicked wizard gem ignores my steps and jumps to request_steps/wicked_finish

I'm using the wicked gem
After I hit RequestStepsController#update, I'm being redirected to /request_steps/wicked_finish. I have no idea why. Any suggestions?
If it worked as I expected it to, then the next step after updating the object would be :the_frame, as described in steps.
From the log:
Started PUT "/request_steps/77" for 127.0.0.1
Processing by RequestStepsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XXX", "request"=>{"background_information"=>"prefilled"}, "commit"=>"C
7"}
Redirected to http://localhost:3000/request_steps/wicked_finish
Started GET "/request_steps/wicked_finish" for 127.0.0.1
Processing by RequestStepsController#show as HTML
Parameters: {"id"=>"wicked_finish"}
Completed 404 Not Found in 180ms
ActiveRecord::RecordNotFound - Couldn't find Request without an ID:
This is my RequestStepsController
class RequestStepsController < ApplicationController
include Wicked::Wizard
steps :background_information,
:no_list_what_can_go_wrong,
:the_frame,
:select_group
def show
#request = Request.find(params[:request])
render_wizard
end
def update
#request = Request.find(params[:id])
#request.update_attributes(request_params)
render_wizard #request
end
def request_params
params.require(:request).permit(:title, :description, :goal,
:request_group_id,
:repository_url,
:background_information
)
end
end
This is my form:
= simple_form_for(#request, url: wizard_path(#request), method: :put, :html => { :class => 'form-inline span8 help_text' }) do |f|
(disclaimer: I did not read your complete question :))
The render_wizard method checks if it can save your #request object. If it can it will go to the next step and try to save it there.. and so on.. until the last step.
See the source code here: https://github.com/schneems/wicked/blob/master/lib/wicked/controller/concerns/render_redirect.rb#L17
To stop it from doing so you need to make sure your object can't be saved in the particular step. Something like described here: https://github.com/schneems/wicked/wiki/Building-Partial-Objects-Step-by-Step
You could also use render_step(params[:id]) instead of render_wizard.

Resources