Setting up associations with Cypress on Rails and FactoryBot
When working with cypress-on-rails and factory_bot you quickly find out setting up associated data cannot be done the same way you would do with ruby tests.
You have to approach getting associations and it’s data setup slightly differently when using cypress-on-rails and generally have the following approaches:
- Setting the foreign keys
- Using transient attributes
- Using Nested Attributes
- Some Combination of the above depending on your situation
Doing a few examples we assume you have the following models:
class Post < ApplicationRecord
belongs_to :author
accepts_nested_attributes_for :author
endclass Author < ApplicationRecord
has_many :posts
accepts_nested_attributes_for :posts
end
Setting the foreign keys
FactoryBot.define do
factory :author do
name { 'Taylor' }
end
factory :post do
title { 'Cypress on Rails is Awesome' }
author_id { create(:author).id }
end
end
Then in Cypress you can do the following:
// example with overriding the defaults
cy.appFactories([['create', 'author', { name: 'James' }]]).then((records) => {
cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_id: records[0].id }]]
});
// example without overriding anything
cy.appFactories([['create', 'author']]).then((records) => {
cy.appFactories([['create', 'post', { author_id: records[0].id }]]
});
Using transient attributes
This is my preferred approach.
FactoryBot.define do
factory :author do
name { 'Taylor' }
end
factory :post do
transient do
author_name { 'Taylor' }
end
title { 'Cypress on Rails is Awesome' }
author { create(:author, name: author_name ) }
end
end
Then in Cypress you can do the following:
// example with overriding the defaults
cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_name: 'James' }]]
// example without overriding
cy.appFactories([['create', 'post']]
Using Nested Attributes
FactoryBot.define do
factory :author do
name { 'Taylor' }
end
factory :post do
title { 'Cypress on Rails is Awesome' }
author_attributes { { name: 'Taylor' } }
end
end
Then in Cypress you can do the following:
// example with overriding the defaults
cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_attributes: { name: 'James' } }]]// example without overriding
cy.appFactories([['create', 'post']]// example of creating author with multiple posts
cy.appFactories([['create', 'author', { name: 'James', posts_attributes: [{ name: 'Cypress is cool' }, {name: 'Rails is awesome' }] ]]
Conclusion
So in order to setup associated data correctly using cypress-on-rails it requires you to write your factories slightly differently but it is still very doable. Sometimes writing a dedicated factory just for Cypress keeps things simple not having to write the factory so they can be used in your unit tests and with Cypress.
Happy Coding.
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
I added these examples so the cypress-on-rails documentation here https://github.com/shakacode/cypress-on-rails/blob/master/docs/factory_bot_associations.md
If you interested in discussing this more you can join the discussion here
https://github.com/shakacode/cypress-on-rails/discussions/101#discussion-3784681