RSpec - A JSON text must at least contain two octets - ruby-on-rails

Two failing specs after upgrading rspec-rails (2.5.2 -> 3.8.1) and capybara (2.18.0 -> 3.10.1):
Not really sure what's going on here. Looks like text in the expectation is being truncated?!?
let(:story_attributes) do
{
title: 'Edited title',
description: 'Edited location',
start_year: '2001',
start_month: 'December',
start_day: '5',
end_year: '2001',
end_month: 'October',
end_day: '10',
is_range: true,
cover_image: {
url: 'http://placehold.it/edited.png'
}
}
end
...
within 'section.story-cover' do
expect(page).to have_text 'Edited title'
expect(page).to have_text 'Edited location'
expect(page).to have_text 'December 5th - October 10th, 2001'
end
In first failed example (below) "Edited location" is being truncated.
In second example expect(page).to have_text 'Edited title Edited location' where only "Edited title\nEdited locat" is found.
Then there's this "JSON text must at least contain two octets" issue which may or may not be related but this used to pass before upgrading rspec-rails & capybara.ds
Thoughts?
RSpec Failures:
1) Story editing published edit story
Failure/Error: JSON.parse(response.body)
JSON::ParserError:
A JSON text must at least contain two octets!
# ./app/services/converter/image_service.rb:36:in `post_to_filepicker'
# ./app/services/converter/image_service.rb:18:in `convert_format'
# ./app/services/converter/image_service.rb:11:in `block in convert'
# ./app/services/converter/image_service.rb:10:in `each'
# ./app/services/converter/image_service.rb:10:in `convert'
# ./app/models/images/image.rb:5:in `convert'
# ./app/models/images/image.rb:20:in `enqueue_conversion'
# ./app/services/story/updating_service.rb:14:in `update'
# ./app/controllers/stories_controller.rb:58:in `update'
# ------------------
# --- Caused by: ---
# Capybara::ExpectationNotMet:
# expected to find text "Edited location" in "Edited title\nLyla HoegerEditedDecember 5th - October 10th, 2001Download"
# ./spec/features/stories/editing_spec.rb:86:in `block (4 levels) in <top (required)>'
2) Story editing private private story should be read after editing
Failure/Error: JSON.parse(response.body)
JSON::ParserError:
A JSON text must at least contain two octets!
# ./app/services/converter/image_service.rb:36:in `post_to_filepicker'
# ./app/services/converter/image_service.rb:18:in `convert_format'
# ./app/services/converter/image_service.rb:11:in `block in convert'
# ./app/services/converter/image_service.rb:10:in `each'
# ./app/services/converter/image_service.rb:10:in `convert'
# ./app/models/images/image.rb:5:in `convert'
# ./app/models/images/image.rb:20:in `enqueue_conversion'
# ./app/services/story/updating_service.rb:14:in `update'
# ./app/controllers/stories_controller.rb:58:in `update'
# ------------------
# --- Caused by: ---
# Capybara::ExpectationNotMet:
# expected to find text "Edited title Edited location" in "Edited title\nEdited locat"
# ./spec/features/stories/editing_spec.rb:115:in `block (4 levels) in <top (required)>'

One of the big changes between Capybara 2.x and 3.x was that in Capybara 3.x text is returned as closely to what is displayed as possible. This means that line feeds are now included in the returned text when they would display to the user - https://github.com/teamcapybara/capybara/blob/master/UPGRADING.md. You either need to change your expected text to "Edited title\nEdited location" at spec/features/stories/editing_spec.rb:115 or if you don't care about the linefeeds you can use the :normalize_ws option => expect(page).to have_text("Edited title Edited location", normalize_ws: true)

Related

RSpec Timecop failures around Date appear to be timezone related

We have some tests (specs) that are failing around Date/Time. Guessing it's a UTC issue but not sure why these specs passed last time project was touched (~8-months ago)!?!
#spec/features/comments/creation_spec.rb
feature 'Comment creation', type: :feature, js: true do
include CommentsPageHelpers
...
let!(:current_date) { Date.parse('2017-01-03') }
...
background do
Timecop.freeze(current_date)
...
end
after do
Timecop.return
end
shared_examples 'added comment' do |position:, text:|
scenario 'adds single comment' do
...
expect(page).to have_text 'January 3rd, 2017'
end
end
end
View (Angular template) #app/views/templates/comment.html.slim
.comment
...
{{ comment.createdAt | moment: 'MMMM Do, YYYY' }}
#RSpec Failure
Comment creation for image behaves like added comment adds single comment
Failure/Error: expect(page).to have_text 'January 3rd, 2017'
expected to find text "January 3rd, 2017" in "John Snow First comment message January 2nd, 2017Remove"
Shared Example Group: "added comment" called from ./spec/features/comments/creation_spec.rb:76
# ./spec/features/comments/creation_spec.rb:42:in `block (4 levels) in <top (required)>'
# ./spec/features/comments/creation_spec.rb:39:in `block (3 levels) in <top (required)>'
Changing the let! line to the two lines below seems to have fixed things. Don't know what else it might break or if it will break for devs in other timezones?!?
Time.zone = 'Pacific Time (US & Canada)'
let!(:current_date) { Time.parse('2017-01-03').in_time_zone }

Poltergeits doesn't working well in rspec tests

I have the following feature tests passing:
require 'rails_helper'
describe "Create a quetsion", type: :feature do
let(:question) { build(:question) }
before do
login_as create(:user, :teacher)
exercise = create(:exercise)
visit new_exercise_question_url(exercise.id)
end
context "whit valid attributes" do
subject do
fill_in "question_score", with: question.score
fill_in "question_description", with: question.description
click_on "Criar"
end
it "create the question" do
expect{ subject }.to change(Question, :count).by(1)
expect(page).to have_current_path(question_path(Question.first.id))
end
end
context "whit invalid attributes" do
subject do
click_on "Criar"
end
it "doesn't create the exercise" do
expect{ subject }.to change(Question, :count).by(0)
expect(page).to have_selector("div.alert.alert-danger")
end
end
end
That works fine, unless I add js: true. In this case, I have the following errors:
1) Create a quetsion whit valid attributes create the question
Failure/Error: fill_in "question_score", with: question.score
Capybara::ElementNotFound:
Unable to find field "question_score"
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/finders.rb:44:in `block in find'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/base.rb:85:in `synchronize'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/finders.rb:33:in `find'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/actions.rb:85:in `fill_in'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:735:in `block (2 levels) in <class:Session>'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/dsl.rb:52:in `block (2 levels) in <module:DSL>'
# ./spec/features/create_a_question_spec.rb:14:in `block (3 levels) in <top (required)>'
# ./spec/features/create_a_question_spec.rb:20:in `block (4 levels) in <top (required)>'
# ./spec/features/create_a_question_spec.rb:20:in `block (3 levels) in <top (required)>'
2) Create a quetsion whit invalid attributes doesn't create the exercise
Got 0 failures and 2 other errors:
2.1) Failure/Error: visit new_exercise_question_url(exercise.id)
Capybara::Poltergeist::StatusFailError:
Request to 'http://www.example.com/exercises/1/questions/new' failed to reach server, check DNS and/or server status
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:376:in `command'
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:35:in `visit'
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/driver.rb:97:in `visit'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:240:in `visit'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/dsl.rb:52:in `block (2 levels) in <module:DSL>'
# ./spec/features/create_a_question_spec.rb:8:in `block (2 levels) in <top (required)>'
2.2) Failure/Error: #socket.send(command.id, command.message, receive_timeout) or raise DeadClient.new(command.message)
Capybara::Poltergeist::DeadClient:
PhantomJS client died while processing {"id":"2928bf26-2dd8-45d7-8822-41b2923fd40d","name":"reset","args":[]}
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/server.rb:38:in `send'
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:369:in `command'
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:224:in `reset'
# /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/driver.rb:183:in `reset!'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:109:in `reset!'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `block in reset_sessions!'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reverse_each'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reset_sessions!'
# /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/rspec.rb:21:in `block (2 levels) in <top (required)>'
I checked, whit js: true my page html isn't written too (instead the desired HTML, I only receive <html><head></head><body></body></html>).
I added poltergeist gem to test javascritp, and configured it in my rspec rails_helper.rb file:
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
PhantomJS is already instaled and available in my $PATH. I'm completelly out of ideas, what can be happening here?
There are a number of potential issues here.
If you have set Capybara.server = :puma, make sure you're not running puma 3.7.0 which has a bug in it that will be fixed when 3.7.1 is released. For now use 3.6.9
If this is the first time you're setting up js tests make sure you have setup and correctly configured DatabaseCleaner so that you are no running in transaction mode for js: true tests. See https://github.com/teamcapybara/capybara#transactions-and-database-setup and https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example for the recommended configuration
Once you have #1 and #2 worked out then you'll need to look at your tests and deal with the fact that after a click/click_on type action you need to check for a visible page change to ensure the action has completed before you move on. This is because clicks happen but the actions those clicks trigger can occur asynchronously. In your current example that means you would need something like
...
click_on "Criar"
expect(page).to have_text("Question created!") #whatever message is shown when the action has completed, or check the page etc.
Without something like that the change check will fail because it will check the count before the actual actually occurs.
Default to _path helpers rather than _url helpers when there's no need for a specific host name (99.9% of the time). This lets Capybara fill_in the correct host/port for the server being run. To visit _url helpers there are a number of configuration parameters that need to be carefully set.
Note: It's generally not best practice to be checking database counts in feature tests, they should generally be limited to checking on visible page changes.

JSONAPI testing with rspec and Airborne

Hello i have problem with testing JSONAPI with rspec and airborne.
GET model below
https://i.stack.imgur.com/Cyf75.png
Im testing it this way https://i.stack.imgur.com/Y9rHt.png
Rspec output:
Failures:
1) GET on /contacts should validate types
Failure/Error: expect_json('books.0', title: 'The Great Escape')
Airborne::PathError:
Expected NilClass
to be an object with property 0
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:21:in `rescue in block in get_by_path'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:18:in `block in get_by_path'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:9:in `each'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:9:in `each_with_index'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:9:in `get_by_path'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/request_expectations.rb:137:in `call_with_path'
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/request_expectations.rb:18:in `expect_json'
# ./book_resource.rb:10:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `[]' for nil:NilClass
# /home/robert/.rvm/gems/ruby-2.4.0/gems/airborne-0.2.5/lib/airborne/path_matcher.rb:57:in `process_json'
Finished in 0.03121 seconds (files took 0.17681 seconds to load)
1 example, 1 failure
Your API response doesn't have the key books. Instead, it is returning the response as { "data": [ ... ] }.
So, in your tests, you need to specify expect_json('data.0', ...), instead of expect_json('books.0', ...).
Hope that should resolve this issue.
Already solve with:
describe Api::UsersController do
describe 'GET on /users' do
before do
FactoryGirl.create('user', name: 'Jack McClure')
FactoryGirl.create('user', name: 'Johny Reaper')
FactoryGirl.create('user', name: 'Niko Bellic')
end
it 'should return valid user' do
get :index, format: 'json'
expect_json('data.0.attributes', name: "Jack McClure")
expect_json('data.2.attributes', name: 'Niko Bellic')
end
end

Rails Rspec IntegrationTest Capybara

I have started to test my app via Rspec (Capybara). This is how I am doing it:
require 'rails_helper'
RSpec.describe "Homepages", type: :request do
describe "GET / without login" , js: true do
before(:all) do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
it "works!" do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Because of env namely "TEST-ENV" I have to create an employee at first.
the problem is, if I run 'rake spec:requests', I get this errors:
1) Homepages GET / without login works!
Got 0 failures and 2 other errors:
1.1) Failure/Error:
def initialize(template, original_exception)
super(original_exception.message)
#template, #original_exception = template, original_exception
#sub_templates = nil
set_backtrace(original_exception.backtrace)
end
ArgumentError:
wrong number of arguments (1 for 2)
#/.rvm/gems/ruby-2.1.1/gems/actionview-4.2.7/lib/action_view/template/error.rb:64:in `initialize'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `exception'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `raise'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `rescue in raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:125:in `raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:113:in `reset!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `block in reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reverse_each'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/rspec.rb:21:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Capybara::CapybaraError:
# Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:126:in `raise_server_error!'
I'm not sure but I think better if type = feature
Sample
require "rails_helper"
RSpec.feature "Homepages", type: :feature do
before do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
context "GET / without login" do
scenario "works!", js: true do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Please make sure your input name is correct by inspect element to get the input name
I think
fill_in "loginname", with: "username"
maybe be
fill_in "user[loginname]", with: "username"
As others have stated, Capybara tests should be of type 'feature' not 'request', however that's not the primary cause of your error. Your apps code is raising an exception during template rendering, and then you're running into a bug in the current version of Capybara with handling exceptions whose initializers take multiple parameters. As long as you're not using jRuby you can lock your Capybara version to 2.10.0 and you should see the correct error your app is raising. If you are using jRuby, or if you prefer to not lock to an older version, you can specify to use the master branch of Capybara
gem 'capybara', github: 'teamcapybara/capybara'
which has the bug fixed.
As a side-note, you've tagged this question with capybara-webkit when you're not actually using the capybara-webkit driver (since it only supports up to Capybara 2.7.1 currently), so you might want to change the tag to just capybara.

Why i am getting these errors while using rspec to test models in ruby and rails?

1) RfidT is not valid without device_mac
Failure/Error: expect(obj2.errors[:device_mac]).to include ("not valid without device_mac!")
expected [] to include "not valid without device_mac!"
# ./spec/models/rfid_t_spec.rb:20:in `block (2 levels) in <top (required)>'
2) RfidT duplicate values of epc are not allowed
Failure/Error: expect(obj3.errors[:epc]).to include("duplicate values of epc are not allowed!")
expected [] to include "duplicate values of epc are not allowed!"
# ./spec/models/rfid_t_spec.rb:27:in `block (2 levels) in <top (required)>'
3) RfidT is not valid without first_seen
Failure/Error: expect(obj4.errors[:first_seen]).to include("cannot be Blank!")
expected ["can't be blank"] to include "cannot be Blank!"
# ./spec/models/rfid_t_spec.rb:33:in `block (2 levels) in <top (required)>'
4) RfidT is not valid without last_seen
Failure/Error: expect(obj5.errors[:last_seen]).to include("cannot be Blank!")
expected ["can't be blank"] to include "cannot be Blank!"
# ./spec/models/rfid_t_spec.rb:39:in `block (2 levels) in <top (required)>'
Finished in 0.16685 seconds (files took 6.45 seconds to load)
6 examples, 4 failures
But when i am using to_not in place of to in spec file then i am not getting any error .Please tell me what is meaning of this and what is the diffrence between to and to_not in ruby and rails.
my spec file generating no error is:
require 'rails_helper'
RSpec.describe RfidT, type: :model do
it "is valid without epc,device_mac,first_seen,last_seen,count" do
obj=RfidT.new(epc:"abc",device_mac:"pqrs",first_seen:10,last_seen:20,count:200)
expect(obj).to be_valid
end
it "is not valid without epc" do
obj1=RfidT.new(epc:nil)
obj1.valid?
#expect(obj1.errors[:epc]).to include("cannot be Blank!")
expect(obj1).to_not be_valid
end
it"is not valid without device_mac " do
obj2=RfidT.new(device_mac:nil)
obj2.valid?
expect(obj2.errors[:device_mac]).to_not include ("not valid without device_mac!")
end
it" duplicate values of epc are not allowed" do
RfidT.create(epc:"abc",device_mac:"pqrs",first_seen:10,last_seen:20,count:200)
obj3=RfidT.new(epc:"abc",device_mac:"pqrs",first_seen:10,last_seen:20,count:200)
obj3.valid?
expect(obj3.errors[:epc]).to_not include("duplicate values of epc are not allowed!")
end
it "is not valid without first_seen " do
obj4=RfidT.new(first_seen:nil)
obj4.valid?
expect(obj4.errors[:first_seen]).not_to include("cannot be Blank!")
end
it "is not valid without last_seen " do
obj5=RfidT.new(last_seen:nil)
obj5.valid?
expect(obj5.errors[:last_seen]).to_not include("cannot be Blank!")
end
end
to checks that the matcher (the thing that follows) matches, for example
expect(obj).to be_valid
Checks that obj.valid? is truthy. If it isn't the example will be mark as failed.
to_not is the opposite: it checks that the matcher doesn't match. In the above example it will mark the example as failed if obj.valid? is truthy.
Unless your code raises an exception, one of to or to_not will pass, because they are opposites of each other.
Your rspec output is telling you that your validations are not enforcing the constraints you want them to.

Resources