Skip to content

Commit

Permalink
Website experiment with test suite (#69)
Browse files Browse the repository at this point in the history
* Experiment with test suite (failing to inspect Netlify build)

* Trigger Netlify deploy this time

* Now, tests should pass!

* Add rails-dom-testing and additional website tests

* Get a docs page started for Automated Testing
  • Loading branch information
jaredcwhite committed Jun 5, 2020
1 parent edff38c commit c3227da
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 3 deletions.
9 changes: 9 additions & 0 deletions bridgetown-website/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@ gem 'bridgetown', path: '../bridgetown'
gem "bridgetown-seo-tag", "3.0.5.beta1", :group => :bridgetown_plugins
gem "bridgetown-feed", "~> 1.0", :group => :bridgetown_plugins
gem "bridgetown-quick-search", "~> 1.0.2", group: :bridgetown_plugins

group :test, optional: true do
gem "nokogiri"
gem "minitest"
gem "minitest-profile"
gem "minitest-reporters"
gem "shoulda"
gem "rails-dom-testing"
end
2 changes: 1 addition & 1 deletion bridgetown-website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"serve": "bundle exec bridgetown serve",
"webpack-build": "webpack --mode production",
"webpack-dev": "webpack --mode development -w",
"deploy": "yarn webpack-build && yarn build",
"deploy": "bundle install --with test && yarn webpack-build && yarn build",
"sync": "node sync.js",
"start": "node start.js"
},
Expand Down
12 changes: 12 additions & 0 deletions bridgetown-website/plugins/test_output.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

unless Bridgetown.environment == "development"
Bridgetown::Hooks.register :site, :post_write do
# Load test suite to run on exit
require "nokogiri"
Dir["test/**/*.rb"].each { |file| require_relative("../#{file}") }
rescue LoadError
# To allow test suite to run:
# bundle install --with test
end
end
2 changes: 1 addition & 1 deletion bridgetown-website/src/_docs/deployment.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
order: 4.5
next_page_order: 5
next_page_order: 4.7
title: Deploying Your Site
top_section: Setup
category: deployment
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-website/src/_docs/plugins/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ completely built and everything has been saved to the destination folder.

For example, there might be certain files you want to compress, or maybe you
need to notify an external web service about new updates, or perhaps you'd like
to run tests against the final output.
to [run tests against the final output](/docs/testing).

## Priorities

Expand Down
43 changes: 43 additions & 0 deletions bridgetown-website/src/_docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
order: 4.7
next_page_order: 5
title: Automated Testing
top_section: Setup
category: testing
---

Running an automated test suite after your Bridgetown site has been built is a great way to ensure important content is available and formatted as you expect, and that some recent change hasn't broken anything critical within your build process.

Bridgetown doesn't come with an opinionated testing setup, so you're welcome to choose from a variety of approaches—and perhaps even use several at once!

## Use Ruby and Minitest to Test HTML Directly

New in Bridgetown 0.15, you can apply an automation to your site to add a [`post_write` hook plugin](/docs/plugins/hooks) that kicks off a Minitest-based test suite. The plugin will automatically detect if the [Bridgetown environment](/docs/configuration/environments) isn't `development` (aka it's `test` or `production`) and if the optional set of test gems (Minitest, Nokogiri, etc.) are available. If so, the tests will run after the site has been built.

The tests you write will be simple DOM selection assertions that operate on the output HTML that's in memory after the site has been rendered, so they run extremely fast. You use the native Ruby APIs provided by Bridgetown to find pages to test, and use assertions you may be familiar with from the Ruby on Rails framework (such as `assert_select` and `assert_dom_equal`). Here's an example of such a test:

```ruby
require_relative "./helper"

class TestBlog < Minitest::Test
context "blog page" do
setup do
page = site.pages.find { |doc| doc.url == "/blog/index.html" }
document_root nokogiri(page)
end

should "show authors" do
assert_select ".box .author img" do |imgs|
assert_dom_equal imgs.last.to_html,
'<img src="/images/khristi-jamil-avatar.jpg" alt="Khristi Jamil" class="avatar">'
end
end
end
end
```

TBC…

## Headless Browser Testing with Cypress

TBC…
39 changes: 39 additions & 0 deletions bridgetown-website/test/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require "nokogiri"
require "minitest/autorun"
require "minitest/reporters"
require "minitest/profile"
require "shoulda"
require "rails-dom-testing"

# Report with color.
Minitest::Reporters.use! [
Minitest::Reporters::DefaultReporter.new(
color: true
),
]

Minitest::Test.class_eval do
include Rails::Dom::Testing::Assertions

def site
@site ||= Bridgetown.sites.first
end

def nokogiri(input)
input.respond_to?(:output) ? Nokogiri::HTML(input.output) : input
end

def document_root(root)
@document_root = root
end

def document_root_element
if @document_root.nil?
raise "Call `document_root' with a Nokogiri document before testing your assertions"
end

@document_root
end
end
81 changes: 81 additions & 0 deletions bridgetown-website/test/test_blog.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

require_relative "./helper"

class TestBlog < Minitest::Test
context "blog page" do
setup do
page = site.pages.find { |doc| doc.url == "/blog/index.html" }
document_root nokogiri(page)
end

should "show authors" do
assert_select ".box .author img" do |imgs|
assert_dom_equal imgs.last.to_html,
'<img src="/images/jared-white-avatar.jpg" alt="Jared White" class="avatar">'
end
end
end

context "blog page" do
setup do
page = site.collections[:docs].docs.find { |doc| doc.url == "/docs/plugins" }
document_root nokogiri(page)
end

should "have a formatted JSON code example" do
assert_select "div.language-json pre.highlight", <<~JSON
"dependencies": {
"random-js-package": "2.4.6",
"my-plugin": "../my-plugin"
}
JSON
end
end

context "blog post" do
setup do
page = site.posts.docs.find { |doc| doc.url == "/release/whats-new-in-0.14-hazelwood/" }
document_root nokogiri(page)
end

should "display a Builder code example" do
assert_select ".box > h1" do |h1|
assert_dom_equal h1.to_html, '<h1 class="mt-3 mb-10 title is-1 is-size-2-mobile has-text-centered has-text-brown">A Bridge to the Future: What’s New in Bridgetown 0.14 “Hazelwood”</h1>'
end

code_example = <<~RUBY
# plugins/builders/welcome_to_hazelwood.rb
class WelcomeToHazelwood < SiteBuilder
def build
liquid_tag "welcome" do |attributes|
"Welcome to Hazelwood, \#{attributes}!"
end
liquid_filter "party_time", :party_time
add_new_posts
end
def party_time(input)
"\#{input} 🥳"
end
def add_new_posts
get "https://___domain.com/posts.json" do |data|
data.each do |post|
doc "\#{post[:slug]}.md" do
front_matter post
categories post[:taxonomy][:category].map { |category| category[:slug] }
date Bridgetown::Utils.parse_date(post[:date])
content post[:body]
end
end
end
end
end
RUBY

assert_select ".content > div.language-ruby:nth-of-type(1) pre.highlight", code_example
end
end
end
21 changes: 21 additions & 0 deletions bridgetown-website/test/test_documentation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require_relative "./helper"

class TestDocumentation < Minitest::Test
context "plugins page" do
setup do
page = site.collections[:docs].docs.find { |doc| doc.url == "/docs/plugins" }
document_root nokogiri(page)
end

should "have a formatted JSON code example" do
assert_select "div.language-json pre.highlight", <<~JSON
"dependencies": {
"random-js-package": "2.4.6",
"my-plugin": "../my-plugin"
}
JSON
end
end
end
20 changes: 20 additions & 0 deletions bridgetown-website/test/test_navbar.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require_relative "./helper"

class TestNavbar < Minitest::Test
context "top navbar" do
setup do
page = site.pages.find { |doc| doc.url == "/about/" }
document_root nokogiri(page)
end

should "have a star link" do
assert_select "nav .navbar-end a:nth-of-type(1)", "Star"
end

should "have a news link" do
assert_select "nav .navbar-start a:nth-of-type(3)", "News"
end
end
end

0 comments on commit c3227da

Please sign in to comment.