Skip to content

Integtest: Add tests for building all books #810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion integtest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ check: \
xpack_float_expected_files xpack_float_same_files \
migration_warnings \
readme_expected_files readme_same_files \
simple_all \
relative_conf_file \
new_repo new_book \
keep_hash keep_hash_new_repo keep_hash_new_book \
Expand Down
55 changes: 55 additions & 0 deletions integtest/spec/all_books_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

RSpec.describe 'building all books' do
context 'for a minimal config' do
convert_all_before_context do |src|
src.write 'source/index.asciidoc', <<~ASCIIDOC
= Title

== Chapter

Some text.
ASCIIDOC
src.init_repo 'source'
src.write 'conf.yaml', <<~YAML
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll end up having to make generating this file more parameterized and automatic but I'd like to wait for a follow up for that.

template:
defaults:
POSTHEAD: |
<link rel="stylesheet" type="text/css" href="styles.css" />
FINAL: |
<script type="text/javascript" src="docs.js"></script>
<script type='text/javascript' src='https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml'></script>

paths:
build: html/
branch_tracker: html/branches.yaml
repos: #{src.path 'repos'}

# This configures all of the repositories used to build the docs
repos:
# Normally we use the `https://` prefix to clone from github but this file
# is for testing so use a string that we can find with sed and replace with
# a file.
source: #{src.path 'source'}

# The title to use for the table of contents
contents_title: Elastic Stack and Product Documentation

# The actual books to build
contents:
-
title: Test book
prefix: test
current: master
branches: [ master ]
index: index.asciidoc
tags: test tag
subject: Test
sources:
-
repo: source
path: index.asciidoc
YAML
end
end
end
41 changes: 25 additions & 16 deletions integtest/spec/helper/convert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,31 @@
# and `before`.
module Convert
def convert_single(from, to, asciidoctor:)
from_dir = File.expand_path('..', from)
init_repo from_dir unless Dir.exist?("#{from_dir}/.git")
cmd = convert_single_cmd from, to, asciidoctor: asciidoctor
cmd = %W[
/docs_build/build_docs.pl
--in_standard_docker
--doc #{from}
--out #{to}
]
cmd += ['--asciidoctor'] if asciidoctor
run_convert cmd
end

def convert_all(conf, to)
cmd = %W[
/docs_build/build_docs.pl
--in_standard_docker
--all
--push
--target_repo #{to}
--conf #{conf}
]
run_convert cmd
end

private

def run_convert(cmd)
# Use popen here instead of capture to keep stdin open to appease the
# docker-image-always-removed paranoia in build_docs.pl
_stdin, out, wait_thr = Open3.popen2e(*cmd)
Expand All @@ -19,17 +41,4 @@ def convert_single(from, to, asciidoctor:)

out
end

private

def convert_single_cmd(from, to, asciidoctor:)
opts = %W[
/docs_build/build_docs.pl
--in_standard_docker
--doc #{from}
--out #{to}
]
opts += ['--asciidoctor'] if asciidoctor
opts
end
end
128 changes: 8 additions & 120 deletions integtest/spec/helper/dsl.rb
Original file line number Diff line number Diff line change
@@ -1,125 +1,13 @@
# frozen_string_literal: true

require_relative 'dsl/convert_all'
require_relative 'dsl/convert_single'
require_relative 'dsl/file_contexts'

##
# Defines methods to create contexts for converting asciidoc files to html.
# Defines methods to create contexts and shared examples used in the tests.
module Dsl
##
# Create a context to assert things about an html page. By default it just
# asserts that the page was created but if you pass a block you can add
# assertions on `body` and `title`.
def page_context(file_name, &block)
context "for #{file_name}" do
include_context 'page', file_name

# Yield to the block to add more tests.
class_exec(&block)
end
end
shared_context 'page' do |file_name|
let(:file) do
dest_file(file_name)
end
let(:body) do
return unless File.exist? file

File.open(dest_file(file), 'r:UTF-8') do |f|
f.read
.sub(/.+<!-- start body -->/m, '')
.sub(/<!-- end body -->.+/m, '')
end
end
let(:title) do
return unless body

m = body.match %r{<h1 class="title"><a id=".+"></a>([^<]+)(<a.+?)?</h1>}
raise "Can't find title in #{body}" unless m

m[1]
end

it 'is created' do
expect(file).to file_exist
end
end

##
# Include a context into the current context that converts asciidoc files
# into html and adds some basic assertions about the conversion process. Pass
# a block that takes a `Source` object and returns the "root" asciidoc file
# to convert. It does the conversion with both with `--asciidoctor` and
# without `--asciidoctor` and asserts that the files are the same.
def convert_single_before_context
include_context 'tmp dirs'
before(:context) do
from = yield(Source.new @src)
@asciidoctor_out = convert_single from, @dest,
asciidoctor: true
# Convert a second time with the legacy `AsciiDoc` tool and stick the
# result into the `asciidoc` directory. We will compare the results of
# this conversion with the results of the `Asciidoctor` conversion.
@asciidoc_out = convert_single from, "#{@dest}/asciidoc",
asciidoctor: false
end
include_examples 'convert single'
end
shared_context 'convert single' do
let(:out) { @asciidoctor_out }
let(:asciidoctor_files) do
files_in(dest_file('.')).reject { |f| f.start_with? 'asciidoc/' }
end
let(:asciidoc_files) do
files_in(dest_file('asciidoc'))
end
it 'prints the path to the html index' do
expect(out).to include(dest_file('index.html'))
end
it 'creates the template hash' do
expect(dest_file('template.md5')).to file_exist
end
it 'creates the css' do
expect(dest_file('styles.css')).to file_exist
end
it 'creates the js' do
expect(dest_file('docs.js')).to file_exist
end
it 'logs the same lines with asciidoc' do
# The only difference should be that the output path includes `asciidoc/`
expect(@asciidoc_out.gsub('asciidoc/', '')).to eq(@asciidoctor_out)
end
it 'makes the same files with asciidoc' do
expect(asciidoc_files).to eq(asciidoctor_files)
end
it 'makes exactly the same html files with asciidoc' do
# This does *all* the files in the same example which doesn't feel very
# rspec but it gets the job done and we don't know the file list at this
# point so there isn't much we can do about it.
asciidoctor_files.each do |file|
next unless File.extname(file) == '.html'

# We shell out to the html_diff tool that we wrote for this when the
# integration tests were all defined in a Makefile. It isn't great to
# shell out here but we've already customized html_diff.
asciidoctor_file = dest_file(file)
asciidoc_file = dest_file("asciidoc/#{file}")
html_diff = File.expand_path '../../html_diff', __dir__
sh "#{html_diff} #{asciidoctor_file} #{asciidoc_file}"
end
end
end

class Source
def initialize(root)
@root = root
end

##
# Write a source file and return the absolute path to that file.
def write(path, text)
path = "#{@root}/#{path}"
File.open(path, 'w:UTF-8') do |f|
f.write text
end
path
end
end
include ConvertAll
include ConvertSingle
include FileContexts
end
65 changes: 65 additions & 0 deletions integtest/spec/helper/dsl/convert_all.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require_relative 'source'

module Dsl
module ConvertAll
##
# Include a context into the current context that converts "all books" as
# configured by a conf file. Pass a block that takes a `Source` object,
# writes all of the input asciidoc files, writes the conf file, and returns
# the path to the conf file.
def convert_all_before_context
include_context 'tmp dirs'
before(:context) do
source = Source.new @src
from = yield source
destbare = File.join @tmp, 'dest.git'
sh "git init --bare #{destbare}"
@out = convert_all from, destbare
sh "git clone #{destbare} #{@dest}"
end
include_examples 'convert all'
end
shared_context 'convert all' do
let(:out) { @out }
let(:dest) { @dest }
it 'prints that it is updating repositories' do
# TODO: more assertions about the logged output
expect(out).to include('Updating repositories')
end
it 'creates redirects.conf' do
expect(dest_file('redirects.conf')).to file_exist
end
it 'creates html/branches.yaml' do
expect(dest_file('html/branches.yaml')).to file_exist
end
file_context 'html/revision.txt' do
it 'contains the initial revision message' do
expect(contents).to include('init')
end
end
page_context 'the global index', 'html/index.html' do
it 'contains a link to the test book' do
expect(body).to include(
'<a class="ulink" href="test/current/index.html" target="_top">' \
'Test book</a>'
)
end
end
page_context 'the book index', 'html/test/index.html' do
it 'contains a redirect to the only version of the book' do
expect(body).to include(
'<meta http-equiv="refresh" content="0; url=current/index.html">'
)
end
end
page_context "the current version's index",
'html/test/current/index.html' do
it 'contains a table of contents' do
expect(body).to include('<div class="toc">')
end
end
end
end
end
74 changes: 74 additions & 0 deletions integtest/spec/helper/dsl/convert_single.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

require_relative 'source'

module Dsl
module ConvertSingle
##
# Include a context into the current context that converts asciidoc files
# into html and adds some basic assertions about the conversion process.
# Pass a block that takes a `Source` object and returns the "root" asciidoc
# file to convert. It does the conversion with both with `--asciidoctor`
# and without `--asciidoctor` and asserts that the files are the same.
def convert_single_before_context
include_context 'tmp dirs'
before(:context) do
source = Source.new @src
from = yield source
source.init_repo '.'
@asciidoctor_out = convert_single from, @dest, asciidoctor: true
# Convert a second time with the legacy `AsciiDoc` tool and stick the
# result into the `asciidoc` directory. We will compare the results of
# this conversion with the results of the `Asciidoctor` conversion.
@asciidoc_out = convert_single from, "#{@dest}/asciidoc",
asciidoctor: false
end
include_examples 'convert single'
end
shared_context 'convert single' do
let(:out) { @asciidoctor_out }
let(:asciidoctor_files) do
files_in(dest_file('.')).reject { |f| f.start_with? 'asciidoc/' }
end
let(:asciidoc_files) do
files_in(dest_file('asciidoc'))
end
it 'prints the path to the html index' do
expect(out).to include(dest_file('index.html'))
end
it 'creates the template hash' do
expect(dest_file('template.md5')).to file_exist
end
it 'creates the css' do
expect(dest_file('styles.css')).to file_exist
end
it 'creates the js' do
expect(dest_file('docs.js')).to file_exist
end
it 'logs the same lines with asciidoc' do
# The only difference should be that the output path
# includes `asciidoc/`
expect(@asciidoc_out.gsub('asciidoc/', '')).to eq(@asciidoctor_out)
end
it 'makes the same files with asciidoc' do
expect(asciidoc_files).to eq(asciidoctor_files)
end
it 'makes exactly the same html files with asciidoc' do
# This does *all* the files in the same example which doesn't feel very
# rspec but it gets the job done and we don't know the file list at this
# point so there isn't much we can do about it.
asciidoctor_files.each do |file|
next unless File.extname(file) == '.html'

# We shell out to the html_diff tool that we wrote for this when the
# integration tests were all defined in a Makefile. It isn't great to
# shell out here but we've already customized html_diff.
asciidoctor_file = dest_file(file)
asciidoc_file = dest_file("asciidoc/#{file}")
html_diff = File.expand_path '../../../html_diff', __dir__
sh "#{html_diff} #{asciidoctor_file} #{asciidoc_file}"
end
end
end
end
end
Loading