Setting up Rails 5 — Vue.js application testing

Chanmann Lim
lchanmann
Published in
4 min readJul 31, 2018

Rails 5 has been bundled with webpacker gem which offers great support for integrating popular JavaScript Frameworks (e.g. Vue, React Angular and Elm) for building Single-page application (SPA) front-end. Nevertheless, JavaScript testing facility doesn’t come out-of-the-box and it is left to developers to setup and configure it manually.

In this article, we are going to walk through step-by-step the creation of Vue.js application in Rails 5, and adding and configuring dependencies for JavaScript testing.

We are going to use Karma and Jasmine for our JavaScript testing. Karma is an awesome JavaScript test runner and I encourage you to also checkout Vojta’s talk for more on Karma.

System requirements

  • Ruby 2.2+
  • Rails 5.1+
  • Node.js 6.0.0+
  • Yarn 0.25.2+

Creating a new Vue.js app in Rails

If you do not have rails installed yet, run the following command in your terminal:

gem install rails

Now, we can create a new rails application with --webpack option:

rails new myapp --webpack

Or add to the Gemfile of your existing rails project:

# Gemfile
gem 'webpacker', '~> 3.5'

Remember to always run bundle install from your terminal after changing your Gemfile.

Installing webpacker:

Run Webpacker installer from your terminal inside your project root directory.

rails webpacker:install

This will create webpack configuration files and executables, JavaScript app source directory and install JavaScript dependencies for the project.

# Files created by webpacker installer
app
└── javascript
│ └── packs
│ └── application.js
bin
├── webpack
└── webpack-dev-server
config
├── webpack
│ ├── development.js
│ ├── environment.js
│ ├── production.js
│ └── test.js
└── webpacker.yml

It will also turn on Yarn integrity check for Rails environment configurations.

# config/environments/development.rb
config.webpacker.check_yarn_integrity = true
# config/environments/production.rb
config.webpacker.check_yarn_integrity = false

Integrate Vue in Rails

Run Webpacker Vue installer from your terminal:

rails webpacker:install:vue

This will add required configuration to Webpacker to enable Vue.js development, install dependencies and generate a sample component app/javascript/app.vue and app/javascript/packs/hello_vue.js which is an entry file to be included in our Rails view or layout files.

Use javascript_pack_tag helper to link to the hello_vue.js in the application layout file:

# app/views/layouts/application.html.erb
<%= javascript_pack_tag 'hello_vue' %>

Install JavaScript testing facilities

Add development dependencies to your package.json file using yarn command line tool from your terminal:

yarn add -D karma jasmine-core karma-jasmine karma-webpack karma-sourcemap-loader karma-spec-reporter karma-chrome-launcher @vue/test-utils

Configure Webpack

Edit config/webpack/test.js file to match the following.

// config/webpack/test.js
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')// Re-generate manifest file when not in test env
// https://github.com/danethurber/webpack-manifest-plugin
environment.plugins.get('Manifest').opts.writeToFileEmit = process.env.NODE_ENV !== 'test'
// Use inline-source-map devtool,
// https://webpack.js.org/configuration/devtool/
environment.config.set('devtool', 'inline-source-map')
module.exports = environment.toWebpackConfig()

Configure Karma

Create new Karma configuration file in the project root and name it karma.conf.js.

// karma.conf.js
const webpackConfig = require('./config/webpack/test.js')
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
plugins: [
'karma-jasmine',
'karma-webpack',
'karma-chrome-launcher',
'karma-spec-reporter',
'karma-sourcemap-loader'
],
files: [
'test/javascript/*.spec.js',
'test/javascript/**/*.spec.js'
],
exclude: [],
webpack: webpackConfig,
preprocessors: {
'test/javascript/*.spec.js': ['webpack', 'sourcemap'],
'test/javascript/**/*.spec.js': ['webpack', 'sourcemap']
},
reporters: ['spec'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
}

Update your package.json file to include script for running karma:

// Add scripts section to package.json
{
"name": "myapp",
"private": true,
"scripts": {
"test": "NODE_ENV=test karma start"
},

...
}

Now, you can start Karma by running yarn test from your terminal. The terminal will start watching *.spec.js files under test/javascript/ directory as defined in karma.conf.js. A chrome browser session for Karma will also open up.

Karma browser session

Write some tests

Create new test file test/javascript/app.vue.spec.js for testing app/javascript/app.vue, the sample Vue component generated earlier.

// test/javascript/app.vue.spec.js
import { shallowMount } from '@vue/test-utils'
import App from '../../app/javascript/app'
describe("app.vue", () => {
it("renders message", () => {
const wrapper = shallowMount(App)
expect(wrapper.text()).toEqual('Hello Vue!')
})
})

Upon saving the file, Karma will instruct Webpack to re-compile our Vue component and (re-)run the test. Back in the terminal where yarn test is running, you will see the test is passing, something similar to mine as shown below (Chrome version, OS and execution time might defer).

# My `yarn test` terminalapp.vue
✓ renders message
Chrome 67.0.3396 (Mac OS X 10.12.6): Executed 1 of 1 SUCCESS (0.003 secs / 0.003 secs)
TOTAL: 1 SUCCESS

Add new unit test

Let’s add new test for reversing the message data property of the component.

// test/javascript/app.vue.spec.js
...

it("reverse message text", () => {
const wrapper = shallowMount(App)
wrapper.vm.reverseMessage()
expect(wrapper.text()).toEqual('!euV olleH')
})

Save the file and you will see failing test in the terminal. Now, implement reverseMessage method in app/javascript/app.vue.

// app/javascript/app.vue
...
<script>
export default {
data: function () {
return {
message: "Hello Vue!"
}
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
}
</script>

Then all tests should pass.

# My `yarn test` terminalapp.vue
✓ reverse message text
✓ renders message
Chrome 67.0.3396 (Mac OS X 10.12.6): Executed 2 of 2 SUCCESS (0.095 secs / 0.031 secs)
TOTAL: 2 SUCCESS

Bonus (debugging your test)

The fact that Karma runs tests on real device (e.g. Chrome browser) makes it super easy when it come to debugging your JavaScript module. You can simply drop debugger statement inside your test files or Vue component where debugging is needed.

Enable DevTools for the Karma browser session then refresh the page.

Karma browser session debugging

Congratulation! You have just setup JavaScript testing for your Rails 5 — Vue.js application.

The repository for this post is available at https://github.com/lchanmann/rails5_vue/commits/master.

References

  1. https://github.com/rails/webpacker/blob/3-x-stable/README.md
  2. https://github.com/rails/webpacker/blob/3-x-stable/docs/testing.md
  3. https://webpack.js.org/
  4. https://github.com/danethurber/webpack-manifest-plugin
  5. https://karma-runner.github.io/2.0/index.html
  6. https://jasmine.github.io/
  7. https://vue-test-utils.vuejs.org/

--

--

Chanmann Lim
lchanmann

M.S. in Computer Science, University of Missouri-Columbia.