Ruby JSON schema draft-07 validation - ruby

I'd like to be able to do two things in some Ruby code:
Validate my schemas against the JSON schema draft-07 metaschemas, and
Validate my data against the schemas validated in (1).
A difficulty here is finding a Ruby library.
https://github.com/notEthan/jsi/ fails to read any schemas, even its own example on that page. I'd guess that it's because I'm using Ruby 3.1; it's fine with Ruby 2.7.5.
https://github.com/voxpupuli/json-schema is not fully maintained any more and only supports draft-04. Other than that it does what is required. I'm currently using this library, e.g.
test "schema validates against the standard" do
metaschema = JSON::Validator.validator_for_name("draft4").metaschema
assert_equal JSON::Validator.validate(metaschema, #schema), true
end
https://github.com/davishmcclurg/json_schemer doesn't include metaschema validation.
Is there anything I've missed?

Related

Validating OAS3.X YAML spec files against the OAS3.0 spec in Java

I would like to be able to validate OAS3.X compatible YAML spec files against the OAS3.0 spec (https://spec.openapis.org/oas/v3.1.0). The built-in capabilities in swagger-parser and openapi4j appear to give inconsistent results. For instance the swagger-parser is not flagging that 'decimal' is not a valid data type in OAS3 etc. How could I write a validator from scratch in Java that would load the OAS3 spec and then validate the YAML spec files against it? (Note: In openapi4j, if the URL points to the OAS3.0 spec file, the parser quits with an exception.)
Thanks!

How to Fix Document Not Found errors with find

I have a collection of Person, stored in a legacy mongodb server (2.4) and accessed with the mongoid gem via the ruby mongodb driver.
If I perform a
Person.where(email: 'some.existing.email#server.tld').first
I get a result (let's assume I store the id in a variable called "the_very_same_id_obtained_above")
If I perform a
Person.find(the_very_same_id_obtained_above)
I got a
Mongoid::Errors::DocumentNotFound
exception
If I use the javascript syntax to perform the query, the result is found
Person.where("this._id == #{the_very_same_id_obtained_above}").first # this works!
I'm currently trying to migrate the data to a newever version. Currently mongodbrestore-ing on amazon documentdb to make tests (mongodb 3.6 compatible) and the issue remains.
One thing I noticed is that those object ids are peculiar:
5ce24b1169902e72c9739ff6 this works anyway
59de48f53137ec054b000004 this requires the trick
The small number of zeroes toward the end of the id seems to be highly correlated with the problem (I have no idea of the reason).
That's the default:
# Raise an error when performing a #find and the document is not found.
# (default: true)
raise_not_found_error: true
Source: https://docs.mongodb.com/mongoid/current/tutorials/mongoid-configuration/#anatomy-of-a-mongoid-config
If this doesn't answer your question, it's very likely the find method is overridden somewhere in your code!

Mongoengine Django Rest Framework - Serializer Error - ReferenceField is not JSON serializable

Everything works great until the ObjectID value of the ReferenceField no longer points to a valid document. Then The ObjectID is left as the value, and json doesn't know how to serialize this.
How do I deal with invalid ReferenceFields?
E.g.
class Food(Document):
name = StringField()
owner = ReferenceField("Person")
class Person(Document):
first_name = StringField()
last_name = StringField()
...
p = Person(...)
apple = Food(name="apple", owner=p)
p.delete() # might be the wrong method, but you get the idea
At this point, attempting to fetch a list of foods via the REST API will fail with the is not JSON serializable error, since apple.owner no longer points to an owner that exists.
Since you are using DRF with mongoengine, you must be using django-rest-framework-mongoengine.
Apparenly, its a bug in django-rest-framework-mongoengine. Check this open issue on Github which was reported recently regarding the same.
https://github.com/umutbozkurt/django-rest-framework-mongoengine/issues/91
One way is to write your own JSONEncoder for this. This link might help.
Another option is to use the json_util library of Pymongo. They provide explicit BSON conversion to and from json.
As per json-util docs:
This module provides two helper methods dumps and loads that wrap the
native json methods and provide explicit BSON conversion to and from
json. This allows for specialized encoding and decoding of BSON
documents into Mongo Extended JSON‘s Strict mode. This lets you encode
/ decode BSON documents to JSON even when they use special BSON types.

Is it better idea to save elements in yml file?

I'm writing automated tests using Selenium WebDriver with Ruby. So, I'm thinking to keep elements in another file and actual code in another file. And for Ruby, I found yaml gem which allows to store data and access it. Hence I stored elements in lib.yml and test code in test.rb as following:
lib/lib.yml
homepage:
frame: 'mainPage'
email: 'loginPage-email'
password: 'loginPage-password'
login_button: 'btnLogin'
tests/test.rb
require 'selenium-webdriver'
require 'yaml'
driver = Selenium::WebDriver.for :firefox
driver.get 'http://www.abc.com'
config = YAML.load_file('./lib/lib.yml')
driver.switch_to.frame(config['homepage']['frame'])
email = driver.find_element(:id, config['homepage']['email'])
password = driver.find_element(:id, config['homepage']['password'])
email.clear
email.send_keys 'abc#gmail.com'
password.clear
password.send_keys 'password'
driver.find_element(:id, config['homepage']['login_button']).click
driver.quit
This way maintenance becomes easier. I just want to make sure if doing so is a good way or not. I'm asking because I'm trying this first time and don't know what difficulties I'll run into if I choose this for larger project.
I know, using Page object model, we can achieve same thing. But I don't know about Page object. So should I avoid using yml gem and directly go for page object gem?
Also, can someone explain how using yml will not be good idea(if it's not)?
Note:
In above code, config['homepage']['something'] is repetitive code. I'll write method to avoid repetition for that.
Yeah this definitely is useful... It keeps the changes to minimum when there is UI change in future.. You always have just one place to edit... Is there any data you have to pass to your code? How are storing the automation data passed to your test.. The only concern might be you might end up with too many yaml files which could be difficult to keep track...
In your specific case I don't see how this adds much value. Half of the settings (frame, login_button) won't change for your tests, so I suggest leaving them directly in the code where they are used. The html structure is not something that usually changes.
The other two values (email, password) seem like they might change when you want to try out different users (i.e. different cases). If you have one test with several example inputs then I suggest using a more readable solution as Cucumber.
(I'd suggest using capybara anyway for testing browser interaction, as it abstracts away many details of the underlying driver)
Apart from that, yaml is usually the ruby way for storing configuration.
I added one more step: Declared locator (id, name etc) in the yaml itself.
Ex:(yaml)
Declared env.rb which load the environment from yaml files
env.yml:
LOGIN:
UserName: {id: UserName}
Password: {id: Password}
RememberME: {id: RememberMe}
Submit: {xpath: "//input[#value='Log On']"}
Then added "pages\Login.rb"
#Loads all objects from yaml
def get_objects
username=#browser.find_element( $object_array['LOGIN']['UserName'])
password=#browser.find_element( $object_array['LOGIN']['Password'])
remember_me=#browser.find_element( $object_array['LOGIN']['RememberME'])
submit= #browser.find_element($object_array['LOGIN']['Submit'])
end
#Added methods in this class like
def loginas(uname,pass)
username.send_keys uname
password.send_keys pass
remember_me.click
submit.click
end #loginas_siteadmin
Created Tests file Login_tests.rb
lp=LoginPage::new(#browser)
lp.navigate
lp.loginas('SiteAdmin','password123')
This way your scripts and maintainable and most importantly you are free of any other external gem or dependency.

HashWithIndifferentAccess issue with a Ruby App

I have two apps that talk to the same database. One is a Ruby on Rails app and another is a console app written in Ruby.
In the Rails app, I save a bunch of settings which are saved to a column called "notification_settings".. I have the following in my model;
serialize :notification_settings, Hash
This causes the value in the column to be stored as such
--- !map:ActiveSupport::HashWithIndifferentAccess
test: !map:ActiveSupport::HashWithIndifferentAccess
email: "1"
etc
When I do the same thing in my Ruby app, the hash is simply saved as a normal hash. Even if i do something like; (in my Ruby app model.rb)
hash = HashWithIndifferentAccess.new(self.notification_settings)
hash[:test][:email] = 0
self.update_attribute(:notification_settings, hash)
How can I get the Ruby app to save the record the exact same way (HashWithIndifferentAccess) as my Rails app is saving the record?

Resources