Setting up associations with Cypress on Rails and FactoryBot

Grant Petersen-Speelman
NEXL Engineering
Published in
2 min readJan 7, 2022

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:

  1. Setting the foreign keys
  2. Using transient attributes
  3. Using Nested Attributes
  4. 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
end
class 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

--

--

Grant Petersen-Speelman
NEXL Engineering
0 Followers
Editor for

Head if Engineering at NEXL and inspired to build technology solutions using GraphQL, Ruby and Rails and Typescript