From 8bd15ebb7df84b29f77d624634c33e505806f0f1 Mon Sep 17 00:00:00 2001 From: Jared White Date: Wed, 3 Jun 2020 11:42:15 -0700 Subject: [PATCH 1/5] Experiment with test suite (failing to inspect Netlify build) --- bridgetown-website/Gemfile | 8 ++++++++ bridgetown-website/package.json | 2 +- bridgetown-website/plugins/test_output.rb | 10 +++++++++ bridgetown-website/test/helper.rb | 25 +++++++++++++++++++++++ bridgetown-website/test/test_navbar.rb | 24 ++++++++++++++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 bridgetown-website/plugins/test_output.rb create mode 100644 bridgetown-website/test/helper.rb create mode 100644 bridgetown-website/test/test_navbar.rb diff --git a/bridgetown-website/Gemfile b/bridgetown-website/Gemfile index 4caf4c79c..0490ce89b 100644 --- a/bridgetown-website/Gemfile +++ b/bridgetown-website/Gemfile @@ -8,3 +8,11 @@ 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" +end diff --git a/bridgetown-website/package.json b/bridgetown-website/package.json index f217e7eae..a3e8a5fce 100644 --- a/bridgetown-website/package.json +++ b/bridgetown-website/package.json @@ -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" }, diff --git a/bridgetown-website/plugins/test_output.rb b/bridgetown-website/plugins/test_output.rb new file mode 100644 index 000000000..5fca9b872 --- /dev/null +++ b/bridgetown-website/plugins/test_output.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +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 diff --git a/bridgetown-website/test/helper.rb b/bridgetown-website/test/helper.rb new file mode 100644 index 000000000..66df82d71 --- /dev/null +++ b/bridgetown-website/test/helper.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require "minitest/autorun" +require "minitest/reporters" +require "minitest/profile" +require "shoulda" +require "nokogiri" +require "bundler" + +# Report with color. +Minitest::Reporters.use! [ + Minitest::Reporters::DefaultReporter.new( + color: true + ), +] + +Minitest::Test.class_eval do + def site + @site ||= Bridgetown.sites.first + end + + def nokogiri(input) + input.respond_to?(:output) ? Nokogiri::HTML(input.output) : input + end +end diff --git a/bridgetown-website/test/test_navbar.rb b/bridgetown-website/test/test_navbar.rb new file mode 100644 index 000000000..f63bcf5ed --- /dev/null +++ b/bridgetown-website/test/test_navbar.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require_relative "./helper" + +class TestNavbar < Minitest::Test + context "navbar" do + setup do + @page = site.posts.docs.find { |doc| doc.url == "/feature/supercharge-your-bridgetown-site-with-ruby-front-matter/" } + @dom = nokogiri(@page) + end + + should "have a star link" do + link = @dom.css("nav .navbar-menu a")[3] + + assert_equal "Star", link.text.strip + end + + should "have a news link" do + link = @dom.css("nav .navbar-menu a")[2] + + assert_equal "Newsss", link.text.strip + end + end +end From a7996c9883cdb23cf5fa101cbc09429123718935 Mon Sep 17 00:00:00 2001 From: Jared White Date: Wed, 3 Jun 2020 11:47:48 -0700 Subject: [PATCH 2/5] Trigger Netlify deploy this time --- bridgetown-website/test/test_navbar.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridgetown-website/test/test_navbar.rb b/bridgetown-website/test/test_navbar.rb index f63bcf5ed..1adb81ba6 100644 --- a/bridgetown-website/test/test_navbar.rb +++ b/bridgetown-website/test/test_navbar.rb @@ -3,7 +3,7 @@ require_relative "./helper" class TestNavbar < Minitest::Test - context "navbar" do + context "top navbar" do setup do @page = site.posts.docs.find { |doc| doc.url == "/feature/supercharge-your-bridgetown-site-with-ruby-front-matter/" } @dom = nokogiri(@page) From e2fff1da3a8c144b0e595aee0196363f0a34d027 Mon Sep 17 00:00:00 2001 From: Jared White Date: Wed, 3 Jun 2020 11:54:44 -0700 Subject: [PATCH 3/5] Now, tests should pass! --- bridgetown-website/test/test_navbar.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridgetown-website/test/test_navbar.rb b/bridgetown-website/test/test_navbar.rb index 1adb81ba6..03e9293f2 100644 --- a/bridgetown-website/test/test_navbar.rb +++ b/bridgetown-website/test/test_navbar.rb @@ -18,7 +18,7 @@ class TestNavbar < Minitest::Test should "have a news link" do link = @dom.css("nav .navbar-menu a")[2] - assert_equal "Newsss", link.text.strip + assert_equal "News", link.text.strip end end end From 7600042eaae3206e406e7c753b78c58a3ca8c466 Mon Sep 17 00:00:00 2001 From: Jared White Date: Thu, 4 Jun 2020 08:37:14 -0700 Subject: [PATCH 4/5] Add rails-dom-testing and additional website tests --- bridgetown-website/Gemfile | 1 + bridgetown-website/plugins/test_output.rb | 16 ++-- bridgetown-website/test/helper.rb | 18 ++++- bridgetown-website/test/test_blog.rb | 80 +++++++++++++++++++ bridgetown-website/test/test_documentation.rb | 21 +++++ bridgetown-website/test/test_navbar.rb | 12 +-- 6 files changed, 131 insertions(+), 17 deletions(-) create mode 100644 bridgetown-website/test/test_blog.rb create mode 100644 bridgetown-website/test/test_documentation.rb diff --git a/bridgetown-website/Gemfile b/bridgetown-website/Gemfile index 0490ce89b..406755ebd 100644 --- a/bridgetown-website/Gemfile +++ b/bridgetown-website/Gemfile @@ -15,4 +15,5 @@ group :test, optional: true do gem "minitest-profile" gem "minitest-reporters" gem "shoulda" + gem "rails-dom-testing" end diff --git a/bridgetown-website/plugins/test_output.rb b/bridgetown-website/plugins/test_output.rb index 5fca9b872..a40c962d2 100644 --- a/bridgetown-website/plugins/test_output.rb +++ b/bridgetown-website/plugins/test_output.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true -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 +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 diff --git a/bridgetown-website/test/helper.rb b/bridgetown-website/test/helper.rb index 66df82d71..19b14d903 100644 --- a/bridgetown-website/test/helper.rb +++ b/bridgetown-website/test/helper.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true +require "nokogiri" require "minitest/autorun" require "minitest/reporters" require "minitest/profile" require "shoulda" -require "nokogiri" -require "bundler" +require "rails-dom-testing" # Report with color. Minitest::Reporters.use! [ @@ -15,6 +15,8 @@ ] Minitest::Test.class_eval do + include Rails::Dom::Testing::Assertions + def site @site ||= Bridgetown.sites.first end @@ -22,4 +24,16 @@ def site 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 diff --git a/bridgetown-website/test/test_blog.rb b/bridgetown-website/test/test_blog.rb new file mode 100644 index 000000000..1a16cdc57 --- /dev/null +++ b/bridgetown-website/test/test_blog.rb @@ -0,0 +1,80 @@ +# 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, 'Jared White' + 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, '

A Bridge to the Future: What’s New in Bridgetown 0.14 “Hazelwood”

' + 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 diff --git a/bridgetown-website/test/test_documentation.rb b/bridgetown-website/test/test_documentation.rb new file mode 100644 index 000000000..f487f6782 --- /dev/null +++ b/bridgetown-website/test/test_documentation.rb @@ -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 diff --git a/bridgetown-website/test/test_navbar.rb b/bridgetown-website/test/test_navbar.rb index 03e9293f2..771df1d86 100644 --- a/bridgetown-website/test/test_navbar.rb +++ b/bridgetown-website/test/test_navbar.rb @@ -5,20 +5,16 @@ class TestNavbar < Minitest::Test context "top navbar" do setup do - @page = site.posts.docs.find { |doc| doc.url == "/feature/supercharge-your-bridgetown-site-with-ruby-front-matter/" } - @dom = nokogiri(@page) + page = site.pages.find { |doc| doc.url == "/about/" } + document_root nokogiri(page) end should "have a star link" do - link = @dom.css("nav .navbar-menu a")[3] - - assert_equal "Star", link.text.strip + assert_select "nav .navbar-end a:nth-of-type(1)", "Star" end should "have a news link" do - link = @dom.css("nav .navbar-menu a")[2] - - assert_equal "News", link.text.strip + assert_select "nav .navbar-start a:nth-of-type(3)", "News" end end end From a26d460c2aa352c9d6f264d40487ddabb662df22 Mon Sep 17 00:00:00 2001 From: Jared White Date: Thu, 4 Jun 2020 11:31:22 -0700 Subject: [PATCH 5/5] Get a docs page started for Automated Testing --- bridgetown-website/src/_docs/deployment.md | 2 +- bridgetown-website/src/_docs/plugins/hooks.md | 2 +- bridgetown-website/src/_docs/testing.md | 43 +++++++++++++++++++ bridgetown-website/test/test_blog.rb | 3 +- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 bridgetown-website/src/_docs/testing.md diff --git a/bridgetown-website/src/_docs/deployment.md b/bridgetown-website/src/_docs/deployment.md index 37553fffe..9dab073b5 100644 --- a/bridgetown-website/src/_docs/deployment.md +++ b/bridgetown-website/src/_docs/deployment.md @@ -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 diff --git a/bridgetown-website/src/_docs/plugins/hooks.md b/bridgetown-website/src/_docs/plugins/hooks.md index b376106cb..84594fe9b 100644 --- a/bridgetown-website/src/_docs/plugins/hooks.md +++ b/bridgetown-website/src/_docs/plugins/hooks.md @@ -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 diff --git a/bridgetown-website/src/_docs/testing.md b/bridgetown-website/src/_docs/testing.md new file mode 100644 index 000000000..5c5f06fa4 --- /dev/null +++ b/bridgetown-website/src/_docs/testing.md @@ -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, + 'Khristi Jamil' + end + end + end +end +``` + +TBC… + +## Headless Browser Testing with Cypress + +TBC… \ No newline at end of file diff --git a/bridgetown-website/test/test_blog.rb b/bridgetown-website/test/test_blog.rb index 1a16cdc57..ef523a651 100644 --- a/bridgetown-website/test/test_blog.rb +++ b/bridgetown-website/test/test_blog.rb @@ -11,7 +11,8 @@ class TestBlog < Minitest::Test should "show authors" do assert_select ".box .author img" do |imgs| - assert_dom_equal imgs.last.to_html, 'Jared White' + assert_dom_equal imgs.last.to_html, + 'Jared White' end end end