Skip to content

Commit 15bf3c0

Browse files
authored
Integtest: Add tests for building all books (elastic#810)
Adds a basic test for building all books. I expect we'll want to refactor it significantly as we port more tests for Make to rspec, but this is a start!
1 parent 1284d17 commit 15bf3c0

10 files changed

+342
-150
lines changed

integtest/Makefile

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ check: \
2222
xpack_float_expected_files xpack_float_same_files \
2323
migration_warnings \
2424
readme_expected_files readme_same_files \
25-
simple_all \
2625
relative_conf_file \
2726
new_repo new_book \
2827
keep_hash keep_hash_new_repo keep_hash_new_book \

integtest/spec/all_books_spec.rb

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe 'building all books' do
4+
context 'for a minimal config' do
5+
convert_all_before_context do |src|
6+
src.write 'source/index.asciidoc', <<~ASCIIDOC
7+
= Title
8+
9+
== Chapter
10+
11+
Some text.
12+
ASCIIDOC
13+
src.init_repo 'source'
14+
src.write 'conf.yaml', <<~YAML
15+
template:
16+
defaults:
17+
POSTHEAD: |
18+
<link rel="stylesheet" type="text/css" href="styles.css" />
19+
FINAL: |
20+
<script type="text/javascript" src="docs.js"></script>
21+
<script type='text/javascript' src='https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml'></script>
22+
23+
paths:
24+
build: html/
25+
branch_tracker: html/branches.yaml
26+
repos: #{src.path 'repos'}
27+
28+
# This configures all of the repositories used to build the docs
29+
repos:
30+
# Normally we use the `https://` prefix to clone from github but this file
31+
# is for testing so use a string that we can find with sed and replace with
32+
# a file.
33+
source: #{src.path 'source'}
34+
35+
# The title to use for the table of contents
36+
contents_title: Elastic Stack and Product Documentation
37+
38+
# The actual books to build
39+
contents:
40+
-
41+
title: Test book
42+
prefix: test
43+
current: master
44+
branches: [ master ]
45+
index: index.asciidoc
46+
tags: test tag
47+
subject: Test
48+
sources:
49+
-
50+
repo: source
51+
path: index.asciidoc
52+
YAML
53+
end
54+
end
55+
end

integtest/spec/helper/convert.rb

+25-16
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,31 @@
77
# and `before`.
88
module Convert
99
def convert_single(from, to, asciidoctor:)
10-
from_dir = File.expand_path('..', from)
11-
init_repo from_dir unless Dir.exist?("#{from_dir}/.git")
12-
cmd = convert_single_cmd from, to, asciidoctor: asciidoctor
10+
cmd = %W[
11+
/docs_build/build_docs.pl
12+
--in_standard_docker
13+
--doc #{from}
14+
--out #{to}
15+
]
16+
cmd += ['--asciidoctor'] if asciidoctor
17+
run_convert cmd
18+
end
19+
20+
def convert_all(conf, to)
21+
cmd = %W[
22+
/docs_build/build_docs.pl
23+
--in_standard_docker
24+
--all
25+
--push
26+
--target_repo #{to}
27+
--conf #{conf}
28+
]
29+
run_convert cmd
30+
end
31+
32+
private
33+
34+
def run_convert(cmd)
1335
# Use popen here instead of capture to keep stdin open to appease the
1436
# docker-image-always-removed paranoia in build_docs.pl
1537
_stdin, out, wait_thr = Open3.popen2e(*cmd)
@@ -19,17 +41,4 @@ def convert_single(from, to, asciidoctor:)
1941

2042
out
2143
end
22-
23-
private
24-
25-
def convert_single_cmd(from, to, asciidoctor:)
26-
opts = %W[
27-
/docs_build/build_docs.pl
28-
--in_standard_docker
29-
--doc #{from}
30-
--out #{to}
31-
]
32-
opts += ['--asciidoctor'] if asciidoctor
33-
opts
34-
end
3544
end

integtest/spec/helper/dsl.rb

+8-120
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,13 @@
11
# frozen_string_literal: true
22

3+
require_relative 'dsl/convert_all'
4+
require_relative 'dsl/convert_single'
5+
require_relative 'dsl/file_contexts'
6+
37
##
4-
# Defines methods to create contexts for converting asciidoc files to html.
8+
# Defines methods to create contexts and shared examples used in the tests.
59
module Dsl
6-
##
7-
# Create a context to assert things about an html page. By default it just
8-
# asserts that the page was created but if you pass a block you can add
9-
# assertions on `body` and `title`.
10-
def page_context(file_name, &block)
11-
context "for #{file_name}" do
12-
include_context 'page', file_name
13-
14-
# Yield to the block to add more tests.
15-
class_exec(&block)
16-
end
17-
end
18-
shared_context 'page' do |file_name|
19-
let(:file) do
20-
dest_file(file_name)
21-
end
22-
let(:body) do
23-
return unless File.exist? file
24-
25-
File.open(dest_file(file), 'r:UTF-8') do |f|
26-
f.read
27-
.sub(/.+<!-- start body -->/m, '')
28-
.sub(/<!-- end body -->.+/m, '')
29-
end
30-
end
31-
let(:title) do
32-
return unless body
33-
34-
m = body.match %r{<h1 class="title"><a id=".+"></a>([^<]+)(<a.+?)?</h1>}
35-
raise "Can't find title in #{body}" unless m
36-
37-
m[1]
38-
end
39-
40-
it 'is created' do
41-
expect(file).to file_exist
42-
end
43-
end
44-
45-
##
46-
# Include a context into the current context that converts asciidoc files
47-
# into html and adds some basic assertions about the conversion process. Pass
48-
# a block that takes a `Source` object and returns the "root" asciidoc file
49-
# to convert. It does the conversion with both with `--asciidoctor` and
50-
# without `--asciidoctor` and asserts that the files are the same.
51-
def convert_single_before_context
52-
include_context 'tmp dirs'
53-
before(:context) do
54-
from = yield(Source.new @src)
55-
@asciidoctor_out = convert_single from, @dest,
56-
asciidoctor: true
57-
# Convert a second time with the legacy `AsciiDoc` tool and stick the
58-
# result into the `asciidoc` directory. We will compare the results of
59-
# this conversion with the results of the `Asciidoctor` conversion.
60-
@asciidoc_out = convert_single from, "#{@dest}/asciidoc",
61-
asciidoctor: false
62-
end
63-
include_examples 'convert single'
64-
end
65-
shared_context 'convert single' do
66-
let(:out) { @asciidoctor_out }
67-
let(:asciidoctor_files) do
68-
files_in(dest_file('.')).reject { |f| f.start_with? 'asciidoc/' }
69-
end
70-
let(:asciidoc_files) do
71-
files_in(dest_file('asciidoc'))
72-
end
73-
it 'prints the path to the html index' do
74-
expect(out).to include(dest_file('index.html'))
75-
end
76-
it 'creates the template hash' do
77-
expect(dest_file('template.md5')).to file_exist
78-
end
79-
it 'creates the css' do
80-
expect(dest_file('styles.css')).to file_exist
81-
end
82-
it 'creates the js' do
83-
expect(dest_file('docs.js')).to file_exist
84-
end
85-
it 'logs the same lines with asciidoc' do
86-
# The only difference should be that the output path includes `asciidoc/`
87-
expect(@asciidoc_out.gsub('asciidoc/', '')).to eq(@asciidoctor_out)
88-
end
89-
it 'makes the same files with asciidoc' do
90-
expect(asciidoc_files).to eq(asciidoctor_files)
91-
end
92-
it 'makes exactly the same html files with asciidoc' do
93-
# This does *all* the files in the same example which doesn't feel very
94-
# rspec but it gets the job done and we don't know the file list at this
95-
# point so there isn't much we can do about it.
96-
asciidoctor_files.each do |file|
97-
next unless File.extname(file) == '.html'
98-
99-
# We shell out to the html_diff tool that we wrote for this when the
100-
# integration tests were all defined in a Makefile. It isn't great to
101-
# shell out here but we've already customized html_diff.
102-
asciidoctor_file = dest_file(file)
103-
asciidoc_file = dest_file("asciidoc/#{file}")
104-
html_diff = File.expand_path '../../html_diff', __dir__
105-
sh "#{html_diff} #{asciidoctor_file} #{asciidoc_file}"
106-
end
107-
end
108-
end
109-
110-
class Source
111-
def initialize(root)
112-
@root = root
113-
end
114-
115-
##
116-
# Write a source file and return the absolute path to that file.
117-
def write(path, text)
118-
path = "#{@root}/#{path}"
119-
File.open(path, 'w:UTF-8') do |f|
120-
f.write text
121-
end
122-
path
123-
end
124-
end
10+
include ConvertAll
11+
include ConvertSingle
12+
include FileContexts
12513
end
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'source'
4+
5+
module Dsl
6+
module ConvertAll
7+
##
8+
# Include a context into the current context that converts "all books" as
9+
# configured by a conf file. Pass a block that takes a `Source` object,
10+
# writes all of the input asciidoc files, writes the conf file, and returns
11+
# the path to the conf file.
12+
def convert_all_before_context
13+
include_context 'tmp dirs'
14+
before(:context) do
15+
source = Source.new @src
16+
from = yield source
17+
destbare = File.join @tmp, 'dest.git'
18+
sh "git init --bare #{destbare}"
19+
@out = convert_all from, destbare
20+
sh "git clone #{destbare} #{@dest}"
21+
end
22+
include_examples 'convert all'
23+
end
24+
shared_context 'convert all' do
25+
let(:out) { @out }
26+
let(:dest) { @dest }
27+
it 'prints that it is updating repositories' do
28+
# TODO: more assertions about the logged output
29+
expect(out).to include('Updating repositories')
30+
end
31+
it 'creates redirects.conf' do
32+
expect(dest_file('redirects.conf')).to file_exist
33+
end
34+
it 'creates html/branches.yaml' do
35+
expect(dest_file('html/branches.yaml')).to file_exist
36+
end
37+
file_context 'html/revision.txt' do
38+
it 'contains the initial revision message' do
39+
expect(contents).to include('init')
40+
end
41+
end
42+
page_context 'the global index', 'html/index.html' do
43+
it 'contains a link to the test book' do
44+
expect(body).to include(
45+
'<a class="ulink" href="test/current/index.html" target="_top">' \
46+
'Test book</a>'
47+
)
48+
end
49+
end
50+
page_context 'the book index', 'html/test/index.html' do
51+
it 'contains a redirect to the only version of the book' do
52+
expect(body).to include(
53+
'<meta http-equiv="refresh" content="0; url=current/index.html">'
54+
)
55+
end
56+
end
57+
page_context "the current version's index",
58+
'html/test/current/index.html' do
59+
it 'contains a table of contents' do
60+
expect(body).to include('<div class="toc">')
61+
end
62+
end
63+
end
64+
end
65+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'source'
4+
5+
module Dsl
6+
module ConvertSingle
7+
##
8+
# Include a context into the current context that converts asciidoc files
9+
# into html and adds some basic assertions about the conversion process.
10+
# Pass a block that takes a `Source` object and returns the "root" asciidoc
11+
# file to convert. It does the conversion with both with `--asciidoctor`
12+
# and without `--asciidoctor` and asserts that the files are the same.
13+
def convert_single_before_context
14+
include_context 'tmp dirs'
15+
before(:context) do
16+
source = Source.new @src
17+
from = yield source
18+
source.init_repo '.'
19+
@asciidoctor_out = convert_single from, @dest, asciidoctor: true
20+
# Convert a second time with the legacy `AsciiDoc` tool and stick the
21+
# result into the `asciidoc` directory. We will compare the results of
22+
# this conversion with the results of the `Asciidoctor` conversion.
23+
@asciidoc_out = convert_single from, "#{@dest}/asciidoc",
24+
asciidoctor: false
25+
end
26+
include_examples 'convert single'
27+
end
28+
shared_context 'convert single' do
29+
let(:out) { @asciidoctor_out }
30+
let(:asciidoctor_files) do
31+
files_in(dest_file('.')).reject { |f| f.start_with? 'asciidoc/' }
32+
end
33+
let(:asciidoc_files) do
34+
files_in(dest_file('asciidoc'))
35+
end
36+
it 'prints the path to the html index' do
37+
expect(out).to include(dest_file('index.html'))
38+
end
39+
it 'creates the template hash' do
40+
expect(dest_file('template.md5')).to file_exist
41+
end
42+
it 'creates the css' do
43+
expect(dest_file('styles.css')).to file_exist
44+
end
45+
it 'creates the js' do
46+
expect(dest_file('docs.js')).to file_exist
47+
end
48+
it 'logs the same lines with asciidoc' do
49+
# The only difference should be that the output path
50+
# includes `asciidoc/`
51+
expect(@asciidoc_out.gsub('asciidoc/', '')).to eq(@asciidoctor_out)
52+
end
53+
it 'makes the same files with asciidoc' do
54+
expect(asciidoc_files).to eq(asciidoctor_files)
55+
end
56+
it 'makes exactly the same html files with asciidoc' do
57+
# This does *all* the files in the same example which doesn't feel very
58+
# rspec but it gets the job done and we don't know the file list at this
59+
# point so there isn't much we can do about it.
60+
asciidoctor_files.each do |file|
61+
next unless File.extname(file) == '.html'
62+
63+
# We shell out to the html_diff tool that we wrote for this when the
64+
# integration tests were all defined in a Makefile. It isn't great to
65+
# shell out here but we've already customized html_diff.
66+
asciidoctor_file = dest_file(file)
67+
asciidoc_file = dest_file("asciidoc/#{file}")
68+
html_diff = File.expand_path '../../../html_diff', __dir__
69+
sh "#{html_diff} #{asciidoctor_file} #{asciidoc_file}"
70+
end
71+
end
72+
end
73+
end
74+
end

0 commit comments

Comments
 (0)