rails frontend testing with javascript insights...- 2-in this ebook we will talk about rails...

16
Rails Frontend Testing with JavaScript Insights DANIEL P. CLARK FREELANCE DEVELOPER CODESHIP.COM - BLOG.CODESHIP.COM -RESOURCES.CODESHIP.COM

Upload: others

Post on 17-Jul-2020

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Rails Frontend Testing with

JavaScript Insights

DANIEL P. CLARK FREELANCE DEVELOPER

CO D E S H I P. CO M - B LO G . CO D E S H I P. CO M - R E S O U RC E S . CO D E S H I P. CO M

Page 3: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save your day.

AB

OU

T T

HIS

EB

OO

K

Rails Frontend Testing with JavaScript Insights

One of the newer things that Rails 5+ provides is system tests. This gives us a full frontend testing experience with Capybara, which runs each of our tests through a real browser window to perfectly provide what a normal web user would experience.

Having this baked in to Rails makes for an elegant way to get started and hit the ground running.

What's more, Rails will generate our standard CRUD system tests per resource when we use the Rails generator to generate it with the models name and attribute fields. This makes swapping in frontend frameworks a much more seamless experience.

In this post, we'll tackle what changes to the code are required to get our previous Rails and VueJS posts app system tests all passing.

Share this

Codeship Guide

- 3 -

Page 4: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Updating a Frontend Application

The changes we'll be demonstrating here are from where we left off in the VueJS Components with CoffeeScript for Rails post. You can find the source code for where we left off at danielpclark/vue_example.

To run your system tests, execute the following command in your project directory:

We should have two errors showing up for our create and update resources. The error message reads Unable to find visible field "Body" that is not disabled .

We get the error about only this field because it's the first error that's come across in the test. If we swap our test order around, we'll find that all of our fields in the create and update tests fail in this way. This has to do with the way Capybara looks up fields for testing.

When you use Rails' form methods to generate labels and input fields, the HTML element label will have a for field. This contains the name of whatever input's id object you're targeting. When we wrote a new form by hand with our VueJS components template, we didn't

1 rails test:system

CO

DE

Share this

Codeship Guide

- 4 -

Page 5: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

write these fields in. So you'll need to change the form fields in file app/javascript/form-document.vue.erb from:

to the following:

Now when you ask Capybara to fill_in the Subject , it gets the target by the label's content and for value and then targets the id used in that for value. What's nice about this is you may use this label targeting technique in ways other than targeting an input field that follows.

If you try to run rails test:system again, you'll notice the same error messages are coming up. This has to do with a configuration in Rails 5 where the test environment

1 <label>Subject</label>2 <input type="text" v-model="document.subject" />3 4 <label>State</label>5 <select v-model="document.state">6 <%= options_for_select(Document.states.keys, "concept") %>7 </select>8 9 <label>Body</label>10 <textarea v-model="document.body"></textarea>

CO

DE

1 <label for="document_subject">Subject</label>2 <input id="document_subject" type="text" v-model="document.subject" />3 4 <label for="document_state">State</label>5 <select id="document_state" v-model="document.state">6 <%= options_for_select(Document.states.keys, "concept") %>7 </select>8 9 <label for="document_body">Body</label>10 <textarea id="document_body" v-model="document.body"></textarea>

CO

DE

Share this

Codeship Guide

- 5 -

Page 6: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

isn't using protect_from_forgery , so the CSRF token is not being provided. Our VueJS code is failing because it explicitly requires that meta attribute field to be available.

You can fix this in one of these ways:

� Change your VueJS code so that it can work without a CSRF token present (which I advise against).

� Change your config/environments/test.rb file to have the following:

The following line of code may be required in your ApplicationController for some frontend form submission implementations to work. For our use case, we won't need it now:

1 # Forgery protection2 config.action_controller.allow_forgery_protection = trueC

OD

E

1 protect_from_forgery prepend: true

CO

DE

To discover why this issue occurred, you need to run rails server with the RAILS_ENV=test set. You can then see the JavaScript errors occurring in the browser's console when you visit the new and edit resource for our Document resource.

Share this

Codeship Guide

- 6 -

Page 7: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Now when you run rails test:system , the test error message has changed, saying the buttons Update Document and Create Document cannot be found. That's the naming scheme Rails would have generated for the submission button had we used their form helpers, so we'll need to update the tests to reflect our current button's name.

Open up test/system/documents_test.rb and change the click_on target from "Create Document" and "Update Document" to "Submit" . Now running the tests, we get a new message saying the proper flash notification wasn't found in the returned result. We'll need to add in the flash messages by adding the following to our application template app/views/layouts/application.html.erb just inside the <body> tag:

1 <% flash.each do |name, msg| -%>2 <%= content_tag :div, msg, class: name %>3 <% end -%>C

OD

EShare this

Codeship Guide

- 7 -

Page 8: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

And then updating our controller's update and new actions to have the appropriate flash notice in app/controllers/documents_controller.rb

1 def create2 @document = Document.new(document_params)3 4 respond_to do |format|5 if @document.save6 flash[:notice] = 'Document was successfully created.'7 format.html { redirect_to @document, notice: 'Document was successfully

created.' }8 format.json { render :show, status: :created, location: @document }9 else10 format.html { render :new }11 format.json { render json: @document.errors, status: :unprocessable_entity }12 end 13 end 14 end15 16 def update17 respond_to do |format|18 if @document.update(document_params)19 flash[:notice] = 'Document was successfully updated.'20 format.html { redirect_to @document, notice: 'Document was successfully

updated.' }21 format.json { render :show, status: :ok, location: @document }22 else23 format.html { render :edit }24 format.json { render json: @document.errors, status: :unprocessable_entity }25 end 26 end 27 end

CO

DE

And at this point, running rails test:system , all our system tests will pass.

Share this

Codeship Guide

- 8 -

Page 9: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

JavaScript Insights for Rails

Many Rails developers may not have a good grasp on JavaScript and its behavior when things go wrong. And in Rails, there are additional things that change its behavior in a peculiar way.

You may have heard many people express their dislike for Turbolinks and/or Spring. I happen to like both of these technologies, but if you don't know what they do for you, they may lead even the most experienced JavaScript developers scratching their heads.

Let's have a brief description of these two libraries.

Turbolinks is a tool that loads pages more quickly and provides a few quick-load UJS features for forms and some CRUD actions. The introduction of Turbolinks does change the JavaScript page ready hook you would normally use to "turbolinks:load" . Using the standard JavaScript page ready hook causes issues when Turbolinks is in use.

Spring is a preloader for code in your application. It will load both Ruby code and frontend assets in its own process and cache what's loaded to be available by the next request. If you don't know how JavaScript handles errors, this can lead you to try to track down a bug for many days, as Spring will have things work after the first navigation from the first page load. So when the site

Share this

Codeship Guide

- 9 -

Page 10: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

loads, some things may seem not to work, but then you click a link and it starts working.

Let's take a look first at how JavaScript handles bad code before delving in to Spring's role in it.

When JavaScript comes across some bad code, or anything that evaluates to something it shouldn't, JavaScript stops what it's doing and produces some output in your browser's console indicating that something is wrong. So when you introduce a new JavaScript library to your application and it has some bad code, then anything that follows it in your code, whether it's more libraries or your own code, won't run. This is the normal JavaScript behavior, to stop code execution at a point of bad code evaluation.

But when you add in Spring, which will load your assets in to a cache (with Turbolinks), Spring doesn't avoid JavaScript code after bad JavaScript code evaluation. So you load the first page and Spring/Turbolinks caches your assets and libraries for faster load.

By the time you navigate through the first link, you may not see that anything is wrong because Spring produces the good JavaScript code after the bad. If a JavaScript feature isn't needed on the first page load, then unless you're looking for a problem in the console, you may not know anything is wrong. And when you go to publish your work, all of a sudden the site is partially down and

Share this

Codeship Guide

- 10 -

Page 11: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

not behaving as you expected even though "it works on my machine."

This kind of thing has likely led many people to pull their hair out over not getting the same results on their machine as in production.

A good tip for JavaScript developers is that any time you add a new library or new JavaScript code to your application, put a simple console.log("Seems okay \̄_(ツ)_/̄ "); right after it. Then in your browser console, make sure that the code gets that far. Once you see the console log the output, you know that your JavaScript code didn't come across any bad evaluation of code when loading.

I had tried a version of the Bootstrap 4 library, which has some bad JavaScript code evaluation in it, and I had placed it before the other JavaScript libraries were required in one of my applications. This caused all of the JavaScript related code not to work on the first page load

Share this

Codeship Guide

- 11 -

Page 12: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

but then appear to work on refresh and after the first link navigation. Because I had put it before Turbolinks that code was also behaving in this manner. To get it to work with Spring on the first page load, I put together this little hack in CoffeeScript:

This of course makes it work on my machine but won't work in production. Developers in Rails often run into situations where the "turbolinks:load" trigger isn't called the first time the website's first page loads.

The Turbolinks.dispatch("turbolinks:load") is the way to instantly trigger that web hook as soon as that line of JavaScript is evaluated. This will come in handy for anyone who needs to get this to occur on first page load of their JavaScript/CoffeeScript scripts.

Triggering CoffeeScript on page load normally requires a little extra work since all CoffeeScript code is wrapped in a function and its scope is protected. Using the Turbolinks.dispatch("turoblinks:load") method makes this not so complicated.

if !Turbolinks?; location.reload is only a useful hack for when Spring is in use. It's only needed to load

1 if !Turbolinks?2 location.reload3 4 Turbolinks.dispatch("turbolinks:load")

CO

DE

Share this

Codeship Guide

- 12 -

Page 13: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

JavaScript code in your development environment despite some bad JavaScript code evaluation occurring. Instead of using it, just use the console.log technique to see how far your JavaScript code has successfully executed. Then remedy the bad code evaluation situation.

Share this

Codeship Guide

- 13 -

Page 14: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Summary

Capybara is a nice library for simple-to-write tests that work with your full frontend experience. Rails generates most of the proper Capybara tests for you so you can read the tests that are there and continue writing similar tests with what you learned from there. Rails does the heavy lifting of configuration and defaults so it's very easy to get started with frontend testing.

Another additional nicety in Rails 5 is that whenever there is an exception raised in a system test, it captures a screenshot of the browser window's contents and saves it to tmp/screenshots/ . Now you can see what's on the screen and compare it to your test to better determine what's wrong with it.

With an understanding of how JavaScript behaves with Rails' libraries, we can prevent lots of debugging time we would otherwise get stuck with. This further increases our ability to use these powerful tools that have jaded others. Turbolinks and Spring make for a wonderful experience once you understand their effects and how to take advantage of them.

It feels good to be a Rails developer these days. Enjoy frontend testing!

Share this

Codeship Guide

- 14 -

Page 15: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Share this

Codeship Guide

- 15 -

More Codeship Resources.

EB

OO

KS

Why Continuous Integration Is Important.In this eBook we will walk you through the benefits of Continuous Integration from a business as well as a development team's perspective.

Download this eBook

EB

OO

KS

Test-Driven Development for JavaScript.In this eBook we will explore the idea of Test-Driven Development (TDD) for client-side JavaScript.

Download this eBook

EB

OO

KS

Dockerizing Ruby Apps and Effectively Testing them.In this eBook you will learn how to dockerize Ruby applications and how to test them.

Download this eBook

Page 16: Rails Frontend Testing with JavaScript Insights...- 2-In this eBook we will talk about Rails frontend testing and we'll look at some JavaScript insights that might just save ABOUT

Share this

Codeship Guide

About Codeship.

Codeship is a hosted Continuous Integration service that fits all your needs. Codeship Basic provides pre-installed dependencies and a simple setup UI that let you incorporate CI and CD in only minutes. Codeship Pro has native Docker support and gives you full control of your CI and CD setup while providing the convenience of a hosted solution.

Codeship Basic

A simple out-of-the-box Continuous Integration service that just works.

Starting at $0/month.

Works out of the box

Preinstalled CI dependencies

Optimized hosted infrastructure

Quick & simple setup

Codeship Pro

A fully customizable hosted Continuous Integration service.

Starting at $0/month.

Customizability & Full Autonomy

Local CLI tool

Dedicated single-tenant instances

Deploy anywhere

LEARN MORELEARN MORE