Patch :update / post :update aborted when testing AMS - active-model-serializers

As I was trying to test out Active Model Serializers, I encountered an issue when attempting to do a patch :update or post :update on ActionController::TestCase. This is the abort output:
deovandski#deovandski-VirtualBox:~/Fakktion$ rake test
rake aborted!
SyntaxError: /home/deovandski/Fakktion/test/controllers/api/v1/genres_controller_test.rb:46: syntax error, unexpected '\n', expecting =>
/home/deovandski/Fakktion/test/controllers/api/v1/genres_controller_test.rb:54: syntax error, unexpected keyword_do_block, expecting keyword_end
/home/deovandski/Fakktion/test/controllers/api/v1/genres_controller_test.rb:58: syntax error, unexpected keyword_end, expecting end-of-input
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:244:in `rescue in load_dependency'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:237:in `load_dependency'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:274:in `require'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:114:in `block (3 levels) in define'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:114:in `each'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:114:in `block (2 levels) in define'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:113:in `each'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:113:in `block in define'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/sub_test_task.rb:20:in `invoke_rake_task'
/home/deovandski/.rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/test_unit/testing.rake:8:in `block in <top (required)>'
Tasks: TOP => test:run
(See full trace by running task with --trace)
Below is the Genres Controller Test with only the test case in question. Setup, Teardown and all other tests can be found through this link.
require 'test_helper'
class Api::V1::GenresControllerTest < ActionController::TestCase
test "API - Update a genre" do
genre = Genre.find_by name: 'test'
genre.name = "mikuchan"
patch :update, id: genre.id, ActiveModel::SerializableResource.new(genre).as_json
genreUpdated = Genre.find_by name: 'mikuchan'
assert_response :success, genreUpdated
end
end
The root seems to be patch :update line from above as the abort states an unexpected /n when it was expecting an =>. However, when I removed id: genre.id, the following error showed up instead:
Api::V1::GenresControllerTest#test_API_-_Update_a_genre:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"api/v1/genres", :data=>{:id=>"980190963", :type=>"genres", :attributes=>{:name=>"mikuchan", :eligibility_counter=>"0", :posts_count=>"0"}, :relationships=>{:posts=>{:data=>[]}}}}
test/controllers/api/v1/genres_controller_test.rb:46:in `block in <class:GenresControllerTest>'
The above output looks like a correct payload, so the problem seems syntax related. However, the only other way that I found was using genre.save which is not what I am looking for since this procedure only uses ActiveRecord...
With that, what is correct approach for testing post :update on AMS? Also, does the procedure change if I am using :json_api as the adapter?

It was a matter of syntax as the appropriated syntax is:
tempResource = ActiveModel::SerializableResource.new(resource).serializable_hash
post :update, tempResource.merge(id: resource)
This is an example testing for CREATE, SHOW, PATCH and DELETE for a resource:
require 'test_helper'
class Api::V1::GenresControllerTest < ActionController::TestCase
# Called before every test
setup do
#request.headers["Content-Type"] = "application/json; charset=utf-8"
#testGenre = Genre.new(name: 'TEST', eligibility_counter: 0, posts_count: 0)
#testGenre.save
end
# Called after test
def teardown
#testGenre = nil
#apiGenre = nil
#genreSerialized = nil
end
test "Genres - API - Get Index" do
get :index
assert_response_schema('genres/index.json')
end
test "Genres - API - Serializer Validation" do
sampleSenre = Genre.new
serializer = ActiveModel::Serializer.serializer_for(sampleSenre)
assert_equal GenreSerializer, serializer
end
test "Genres - API - Create 200" do
apiGenre = Genre.new(name: 'luka', eligibility_counter: 0, posts_count: 0)
assert_difference('Genre.count', +1) do
post :create, ActiveModel::SerializableResource.new(apiGenre).as_json
end
end
test "Genres - API - Create 422" do
post :create, ActiveModel::SerializableResource.new(#testGenre).as_json
assert_response(422)
end
test "Genres - API - SHOW 200" do
get :show, id: #testGenre
assert_response_schema('genres/show.json')
end
test "Genres - API - UPDATE 200" do
genre = Genre.find_by name: 'test'
genre.name = "mikuchan"
tempGenre = ActiveModel::SerializableResource.new(genre).serializable_hash
post :update, tempGenre.merge(id: genre)
genreUpdated = Genre.find_by name: 'mikuchan'
assert_response :success, genreUpdated
end
test "Genres - API - UPDATE 422" do
genre = Genre.find_by name: 'test'
genre1 = Genre.find_by name: 'movie'
genre.name = "mikuchan"
genre1.name = "mikuchan"
tempGenre = ActiveModel::SerializableResource.new(genre).serializable_hash
tempGenre1 = ActiveModel::SerializableResource.new(genre1).serializable_hash
post :update, tempGenre.merge(id: genre)
post :update, tempGenre1.merge(id: genre1)
assert_response(422)
end
test "Genres - API - DELETE 200" do
assert_difference('Genre.count', -1) do
delete :destroy, id: #testGenre
end
end
test "Genres - API - DELETE 422" do
genre = Genre.find_by name: 'song'
post = Post.first
post.genre = genre
post.save
delete :destroy, id: genre
assert_response(422)
end
end

Related

Jest toEqual is failing and I don't know why

I'm running the tests for a package I'd like to help contribute to. However, when running the tests, which I'd assume should work, I'm getting a myriad of failing tests with this kind of output.
● PagingType › should create the correct filter graphql schema
expect(received).toEqual(expected) // deep equality
- Expected - 20
+ Received + 20
- type Query {
+ type Query {
- test(input: Paging!): Int!
+ test(input: Paging!): Int!
- }
-
+ }
+
- input Paging {
+ input Paging {
- """Paginate before opaque cursor"""
+ """Paginate before opaque cursor"""
- before: ConnectionCursor
-
+ before: ConnectionCursor
+
- """Paginate after opaque cursor"""
+ """Paginate after opaque cursor"""
- after: ConnectionCursor
-
+ after: ConnectionCursor
+
- """Paginate first"""
+ """Paginate first"""
- first: Int
-
+ first: Int
+
- """Paginate last"""
+ """Paginate last"""
- last: Int
+ last: Int
- }
-
+ }
+
- """Cursor for paging through collections"""
+ """Cursor for paging through collections"""
- scalar ConnectionCursor
+ scalar ConnectionCursor
↵
22 | const sf = await getOrCreateSchemaFactory();
23 | const schema = await sf.create(resolvers);
> 24 | return expect(printSchema(schema)).toEqual(sdl);
| ^
25 | };
26 |
27 | export const aggregateArgsTypeSDL = readGraphql(resolve(__dirname, './aggregate-args-type.graphql'));
at Object.<anonymous>.exports.expectSDL (packages/query-graphql/__tests__/__fixtures__/index.ts:24:38)
It seems like "toEqual" just isn't working correctly, because there seems to be nothing actually wrong between the two text outputs.
This is another set of example outputs of a console.log of the strings being compared. The failures are also happening with objects too.
type Query {
updateTest(input: UpdateOne!): Int!
}
input UpdateOne {
"""The id of the record to update"""
id: ID!
"""The update to apply."""
update: FakeUpdateOneType!
}
input FakeUpdateOneType {
name: String!
}
type Query {
updateTest(input: UpdateOne!): Int!
}
input UpdateOne {
"""The id of the record to update"""
id: ID!
"""The update to apply."""
update: FakeUpdateOneType!
}
input FakeUpdateOneType {
name: String!
}
Does anyone have an idea what might be wrong/is happening?
Ok. As it seems, it's a Windows/ Git issue.
This is the text with JSON.stringify
console.log
"type Query {\n updateTest(input: UpdateOne!): Int!\n}\n\ninput UpdateOne {\n \"\"\"The id of the record to update\"\"\"\n id: ID!\n\n \"\"\"The update to apply.\"\"\"\n update: FakeUpdateOneType!\n}\n\ninput FakeUpdateOneType {\n name: String!\n}\n"
at Object.<anonymous>.exports.expectSDL (packages/query-graphql/__tests__/__fixtures__/index.ts:22:11)
console.log
"type Query {\r\n updateTest(input: UpdateOne!): Int!\r\n}\r\n\r\ninput UpdateOne {\r\n \"\"\"The id of the record to update\"\"\"\r\n id: ID!\r\n\r\n \"\"\"The update to apply.\"\"\"\r\n update: FakeUpdateOneType!\r\n}\r\n\r\ninput FakeUpdateOneType {\r\n name: String!\r\n}\r\n"
If Git for Windows isn't set up correctly, it will add /r/n as line breaks when cloning a repo. If the project was developed in anything other than Windows, then text comparisons with toEqual that have line breaks in them will fail. Too bad Jest doesn't say something like "mismatched line breaks" or show the escaped characters.
To fix this, I installed Git for Windows (I needed to upgrade anyway) with this option, which sets core.autocrlf to "input".

How to retry a request until i get a valid dynamically generated value in response using karate dsl

I am sending a request to fetch the API ID from backend but because my backend is slow it doesn't give back the ID in one go and that's making my test case fail in the first try. Though it passes if I try again, but that's not ideally it should work. I tried putting a sleep, but that doesn't look promising either.
My test case is :
Given URL storeURL
And param query =
When method get
Then status 200
call read('Sleep.feature')
def APIIDStr = response.list[0].id
print 'APIID from Store is: ', APIIDStr
Can i do something here so that if APIIDStr is empty in the first go , it tries to fetch again until it gets a valid value?
Yes. Please refer to the documentation on how to implement polling using JavaScript: https://github.com/intuit/karate#polling
function(x) {
while (true) {
var result = karate.call('get.feature');
var greeting = result.response;
karate.log('poll response', greeting);
if (greeting.id == x) {
karate.log('condition satisfied, exiting');
return;
}
karate.log('sleeping');
// uncomment / modify the sleep time as per your wish
// java.lang.Thread.sleep(1000);
}
}
EDIT - also see: https://stackoverflow.com/a/55823180/143475
The follow code can correctly run now:
Feature:
Background:
* url 'url'
Scenario:
* def input =
"""
{
'form': {},
'query': {},
}
"""
* path '/rest/n/test'
* params input.query
* form fields input.form
* method post
* status 200
* math response contains { result: 1 }
* eval if (response.result != 1) karate.call('delete-user.feature'))
So, I hope hope retryPost method which can retry-post the scenario (it can auto check status).
or:
...
* eval if (responseStatus == 5xx) retryPost/retryGet/retryPut
* eval if (response.result != 1) retryPost/retryGet/retryPut
Here retryPost/retryGet/retryPut only re-run the section code.
for example:
Feature:
Background:
* url 'url'
Scenario:
# section 1
...
* method post
* eval if () retryPost # only re-run section 1
# section 2
...
* method post
*eval if () retryPost # only re-run section 2
Thanks a lot!

"cancel" variable in groovy script not working in Jenkins Email-ext plugin

I'm having an issue where I want to cancel sending an email when a job gets into the FIXED state from the UNSTABLE state. So if a job was failing but got fixed, I want to send the message. But if a job is unstable (tests not passing) and gets fixed, don't send the email. It might be that a job is marked UNSTABLE after it has been in FAILURE state. When it goes to SUCCESS (i.e. it is fixed) I want an email in that case. You can see the cases in the code below.
My problem is that when I set the variable cancel to true by definition[1] it should cancel the email, but it doesn't. The email gets sent every time. Of course I'm using triggers for "Failure", "Still failing" and "Fixed".
Jenkins version: 1.533. Email-ext version: 2.37.2.2
// The goal of this script is to block sending the 'FIXED' message
// when the status goes from 'UNSTABLE' to 'SUCCESS'
//
// These are the cases (where F=FAILURE, U=UNSTABLE, S=SUCCESS)
// S - S : no msg (previous state: S, current state: S)
// F - S : msg
// S - U ... U - S : no msg <-- this is the one we need to avoid sending an email
// F - U ... U - S : msg
logger.println("Entering pre-send script")
// variable definitions
def keepGoing= true
def cancelEmail = false
// object to current job
job = hudson.model.Hudson.instance.getItem("incr-build-master")
// current build number
buildNumber = build.getNumber()
logger.println("Current build number: " + buildNumber)
// if the build failed or is unstable don't to anything,
// the specific triggers should take care of the messages
if (build.result.toString().equals("SUCCESS"))
{
logger.println("Build is successful. Procesing...")
while( keepGoing )
{
// get the number of the next past build
pastBuild = job.getBuildByNumber(--buildNumber)
buildResult = pastBuild.result.toString()
switch ( buildResult )
{
case "SUCCESS":
// if the previous non-unstable build was successful
// don't send a 'FIXED' message
cancelEmail = true
keepGoing = false
logger.println("Cancel sending email")
break
case "FAILURE":
// here we exit, but we will send the 'FIXED' message
keepGoing = false
logger.println("Send email")
break
case "UNSTABLE":
// let us keep looking until we find a previous build
// that is either 'SUCCESS' or 'FAILURE*
logger.println("Build " + buildNumber + " is unstable")
break
default:
logger.println("Error in script: result string is wrong - " + buildResult)
return
}
}
}
logger.println("Emailed canceled?: " + cancelEmail)
cancel=cancelEmail
logger.println("Exiting pre-send script")
[1] from the Help icon: "You may also cancel sending the email by setting the boolean variable "cancel" to true."
I encountered the same problem and found solution in a couple of days.
"cancel" only works when it is used in the last line of code.
This will cancel the build:
changed = false
files = 5
cancel = true
This will not:
changed = false
cancel = true
files = 5
And this will also do cancel:
changed = false
files = 5
if (files > 2) {
cancel = true
}
I hope this will save some time for somebody.
I am having a similar problem.
In the Pre-send script I put:
if ((build.getNumber() % 2) == 0) {
cancel=true;
} else {
cancel=false;
}
logger.println("cancel = " + cancel);
I get e-mail, with the build.log file attached, that shows the "cancel = true" and "cancel = false" cases.

XPages create a full text index in SSJS

I have a DB that must be full text indexed, so I added the code below to create one if it is not allready indexed:
if (database.isFTIndexed()){
database.updateFTIndex(false)
} else {
var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
database.createFTIndex(options , true);
database.updateFTIndex(false);
}
sessionScope.put("ssSelectedView","vwWFSProfile")
When it runs I get the following error:
Error source
Page Name:/xpWFSAdmin.xsp
Control Id: button2
Property: onclick
Exception
Error while executing JavaScript action expression
com.ibm.jscript.types.GeneratedWrapperObject$StaticField incompatible with com.ibm.jscript.types.FBSValue
Expression
1: #{javascript:if (database.isFTIndexed()){
2: database.updateFTIndex(false)
3: } else {
4: var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
5: database.createFTIndex(options , true);
6: database.updateFTIndex(false);
7: }
8: sessionScope.put("ssSelectedView","vwWFSProfile")}
It is choking on line 4 it does not like the summing of the parameters. So I comment out line 4 and change line 5 to read database.createFTIndex(4, true)
then I get this error:
Error while executing JavaScript action expression
Script interpreter error, line=5, col=18: [TypeError] Exception occurred calling method NotesDatabase.createFTIndex(number, boolean) null
JavaScript code
1: if (database.isFTIndexed()){
2: database.updateFTIndex(false)
3: } else {
4: //var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
5: database.createFTIndex(4 , true);
6: database.updateFTIndex(false);
7: }
8: sessionScope.put("ssSelectedView","vwWFSProfile")
Can't seem to get it to work. I can go into the DB and manually create the index so it is not a rights issue.
As far as I can read from the help, you can not use database.FTINDEX_IMMEDIATE as parameter for createFTIndex() only for setFTIndexFrequency().
So remove the use of database.FTINDEX_IMMEDIATE and do this:
var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES;
database.createFTIndex(options , true);
You can then call setFTIndexFrequency() like this:
database.setFTIndexFrequency(database.FTINDEX_IMMEDIATE);

Error when logging in with Machinist in Shoulda test

I am having some trouble getting the right usage of Machinist and Shoulda in my testing.
Here is my test:
context "on POST method rating" do
p = Product.make
u = nil
setup do
u = login_as
post :vote, :rating => 3, :id => p
end
should "set rating for product to 3" do
assert_equal p.get_user_vote(u), 3
end
And here's my blueprints:
Sham.login { Faker::Internet.user_name }
Sham.name { Faker::Lorem.words}
Sham.email { Faker::Internet.email}
Sham.body { Faker::Lorem.paragraphs(2)}
User.blueprint do
login
password "testpass"
password_confirmation { password }
email
end
Product.blueprint do
name {Sham.name}
user {User.make}
end
And my authentication test helper:
def login_as(u = nil)
u ||= User.make()
#controller.stubs(:current_user).returns(u)
u
end
The error I get is:
/home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/validations.rb:1090:in `save_without_dirty!': Validation failed: Login has already been taken, Email has already been taken (ActiveRecord::RecordInvalid)
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/dirty.rb:87:in `save_without_transactions!'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/transactions.rb:200:in `save!'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/transactions.rb:182:in `transaction'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/transactions.rb:200:in `save!'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
from /home/jason/moderndarwin/vendor/rails/activerecord/lib/active_record/transactions.rb:200:in `save!'
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist/active_record.rb:55:in `make'
from /home/jason/moderndarwin/test/blueprints.rb:37
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist.rb:77:in `generate_attribute_value'
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist.rb:46:in `method_missing'
from /home/jason/moderndarwin/test/blueprints.rb:37
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist.rb:20:in `instance_eval'
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist.rb:20:in `run'
from /usr/lib/ruby/gems/1.8/gems/machinist-1.0.6/lib/machinist/active_record.rb:53:in `make'
from ./test/functional/products_controller_test.rb:25:in `__bind_1269805681_945912'
from /home/jason/moderndarwin/vendor/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:293:in `call'
from /home/jason/moderndarwin/vendor/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:293:in `merge_block'
from /home/jason/moderndarwin/vendor/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:288:in `initialize'
from /home/jason/moderndarwin/vendor/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:169:in `new'
from /home/jason/moderndarwin/vendor/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:169:in `context'
from ./test/functional/products_controller_test.rb:24
I can't figure out what it is I'm doing wrong... I have tested the login_as with my auth (Authlogic) in my user_controller testing.
Any pointers in the right direction would be much appreciated!
I've got a partial solution... I've solved the problem above, but the should_redirect_to function is still giving me fits...
This is my new test code:
context "on POST method rating" do
setup do
#u = login_as
#p1 = Product.make
#p2 = Product.make # Make a second product that we'll show after rating the first
post :vote, :rating => 3, :id => #p1
end
should "set rating for product to 3" do
assert_equal #p1.get_user_vote(#u), 3
end
should_redirect_to("product page") {show_product_url(:id => #p2)}
end
And my new error:
response to be a redirect to <http://test.host/products/555660218> but was a redirect to <http://test.host/products>.
Any ideas where to go from here?
Is your controller redirecting to products_url?
Side note: you shouldn't use random data (Faker) for any validation that requires uniqueness. That's what Factory Girl's sequences are for. I assume Machinist has something similar.

Resources