Testing Rails Engines with Spina

As mentioned in the previous post, I've been working on a Rails plugin gem for use in Spina CMS. After a couple of tweaks (defining factories for users and accounts, since the user is linked to the blog post as an author, and the account is required for the admin controller inheritance) I was ready to start testing again.

... and hit a major issue. I kept getting an issue saying plugins was not defined.

ActionView::Template::Error: undefined method `plugins' for nil:NilClass  

Applying a backtrace on the test, it tells me that it's on line 22 of /layouts/spina/admin/admin.html.haml, which we can find in the spina gem:

- Spina::Plugin.all.each do |plugin|

Spina::Plugin is definitely defined, however (can output to the console in the test, for example). It's actually the following line that's the problem:

- if current_theme.plugins.include? plugin.name

current_theme is the culprit here. In our accounts.rb factory file, the account is defined as (taken wholesale from the spina gem):

FactoryBot.define do  
  factory :account, class: Spina::Account do
    name 'My Website'
    preferences { { theme: 'demo' } }

Spina defines themes under config/initializers/themes. This doesn't exist in the default app created under test/dummy, nor the spina.rb initalizer.

So you need to add them to the dummy app to load things correctly. I haven't tried with the rake tasks/rails generators, but you should be able to do it by calling rails spina:install from inside test/dummy (don't do it from the root, or it will install Spina in your engine rather than in the test app). Whichever of the themes you choose, it should match your theme definition in your factory (and so should the site name, for consistency). Or if you want to do it manually, you'll need the following:

# config/initializers/spina.rb
Spina.configure do |config|  
  # Set locales
  config.locales = [:en]
  # Run `rake spina:update_translations` after you add any new locale.

  # Important Note
  # ==============

  # You MUST restart your server before changes to this file
  # will take effect.

  # Specify a backend path. Defaults to /admin.
  # config.backend_path = 'admin'

  # Pages Options
  # ===============

  # Note that you might need to remove cached asset after changing this value
  # config.max_page_depth = 5

I'm not 100% sure that this is required for the test app, but really, it should reflect a real-world case as much as possible, right?

And for the theme, we'll just use the default theme:

# config/initializers/themes/default.rb
::Spina::Theme.register do |theme|

  theme.name = 'default'
  theme.title = 'Default Theme'

  theme.page_parts = [{
    name:           'text',
    title:          'Text',
    partable_type:  'Spina::Text'

  theme.view_templates = [{
    name:       'homepage',
    title:      'Homepage',
    page_parts: ['text']
  }, {
    name: 'show',
    title:        'Default',
    description:  'A simple page',
    usage:        'Use for your content',
    page_parts:   ['text']

  theme.custom_pages = [{
    name:           'homepage',
    title:          'Homepage',
    deletable:      false,
    view_template:  'homepage'

  theme.navigations = [{
    name: 'mobile',
    label: 'Mobile'  
  }, {
    name: 'main',
    label: 'Main navigation',
    auto_add_pages: true


Since our theme in tests is named demo we either need to change this to default, or alternatively, we can copy/move default.rb in the themes folder to demo.rb and update the name.

As long as you have a valid theme definition here, controller tests will start to work.

You can check out the work-in-progress gem here.

Matt Redmond

Musician, composer, actor, engineer, pirate.

Adelaide, Australia