"Fossies" - the Fresh Open Source Software Archive

Member "asciidoctor-2.0.10/test/invoker_test.rb" (1 Jun 2019, 27966 Bytes) of package /linux/www/asciidoctor-2.0.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "invoker_test.rb": 2.0.5_vs_2.0.6.

    1 # frozen_string_literal: false
    2 require_relative 'test_helper'
    3 require File.join Asciidoctor::LIB_DIR, 'asciidoctor/cli'
    4 
    5 context 'Invoker' do
    6   test 'should parse source and convert to html5 article by default' do
    7     invoker = nil
    8     output = nil
    9     redirect_streams do |out, err|
   10       invoker = invoke_cli %w(-o -)
   11       output = out.string
   12     end
   13     refute_nil invoker
   14     doc = invoker.document
   15     refute_nil doc
   16     assert_equal 'Document Title', doc.doctitle
   17     assert_equal 'Doc Writer', doc.attr('author')
   18     assert_equal 'html5', doc.attr('backend')
   19     assert_equal '.html', doc.attr('outfilesuffix')
   20     assert_equal 'article', doc.attr('doctype')
   21     assert doc.blocks?
   22     assert_equal :preamble, doc.blocks.first.context
   23     refute_empty output
   24     assert_xpath '/html', output, 1
   25     assert_xpath '/html/head', output, 1
   26     assert_xpath '/html/body', output, 1
   27     assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
   28     assert_xpath '/html/body[@class="article"]/*[@id="header"]/h1[text() = "Document Title"]', output, 1
   29   end
   30 
   31   test 'should set implicit doc info attributes' do
   32     sample_filepath = fixture_path 'sample.adoc'
   33     sample_filedir = fixturedir
   34     invoker = invoke_cli_to_buffer %w(-o /dev/null), sample_filepath
   35     doc = invoker.document
   36     assert_equal 'sample', doc.attr('docname')
   37     assert_equal sample_filepath, doc.attr('docfile')
   38     assert_equal sample_filedir, doc.attr('docdir')
   39     assert doc.attr?('docdate')
   40     assert doc.attr?('docyear')
   41     assert doc.attr?('doctime')
   42     assert doc.attr?('docdatetime')
   43     assert_empty invoker.read_output
   44   end
   45 
   46   test 'should allow docdate and doctime to be overridden' do
   47     sample_filepath = fixture_path 'sample.adoc'
   48     invoker = invoke_cli_to_buffer %w(-o /dev/null -a docdate=2015-01-01 -a doctime=10:00:00-0700), sample_filepath
   49     doc = invoker.document
   50     assert doc.attr?('docdate', '2015-01-01')
   51     assert doc.attr?('docyear', '2015')
   52     assert doc.attr?('doctime', '10:00:00-0700')
   53     assert doc.attr?('docdatetime', '2015-01-01 10:00:00-0700')
   54   end
   55 
   56   test 'should accept document from stdin and write to stdout' do
   57     invoker = invoke_cli_to_buffer(%w(-s), '-') { 'content' }
   58     doc = invoker.document
   59     refute doc.attr?('docname')
   60     refute doc.attr?('docfile')
   61     assert_equal Dir.pwd, doc.attr('docdir')
   62     assert_equal doc.attr('docdate'), doc.attr('localdate')
   63     assert_equal doc.attr('docyear'), doc.attr('localyear')
   64     assert_equal doc.attr('doctime'), doc.attr('localtime')
   65     assert_equal doc.attr('docdatetime'), doc.attr('localdatetime')
   66     refute doc.attr?('outfile')
   67     output = invoker.read_output
   68     refute_empty output
   69     assert_xpath '/*[@class="paragraph"]/p[text()="content"]', output, 1
   70   end
   71 
   72   test 'should not fail to rewind input if reading document from stdin' do
   73     begin
   74       old_stdin = $stdin
   75       $stdin = StringIO.new 'paragraph'
   76       invoker = invoke_cli_to_buffer(%w(-s), '-')
   77       assert_equal 0, invoker.code
   78       assert_equal 1, invoker.document.blocks.size
   79     ensure
   80       $stdin = old_stdin
   81     end
   82   end
   83 
   84   test 'should accept document from stdin and write to output file' do
   85     sample_outpath = fixture_path 'sample-output.html'
   86     begin
   87       invoker = invoke_cli(%W(-s -o #{sample_outpath}), '-') { 'content' }
   88       doc = invoker.document
   89       refute doc.attr?('docname')
   90       refute doc.attr?('docfile')
   91       assert_equal Dir.pwd, doc.attr('docdir')
   92       assert_equal doc.attr('docdate'), doc.attr('localdate')
   93       assert_equal doc.attr('docyear'), doc.attr('localyear')
   94       assert_equal doc.attr('doctime'), doc.attr('localtime')
   95       assert_equal doc.attr('docdatetime'), doc.attr('localdatetime')
   96       assert doc.attr?('outfile')
   97       assert_equal sample_outpath, doc.attr('outfile')
   98       assert File.exist?(sample_outpath)
   99     ensure
  100       FileUtils.rm_f(sample_outpath)
  101     end
  102   end
  103 
  104   test 'should fail if input file matches resolved output file' do
  105     invoker = invoke_cli_to_buffer %W(-a outfilesuffix=.adoc), 'sample.adoc'
  106     assert_match(/input file and output file cannot be the same/, invoker.read_error)
  107   end
  108 
  109   test 'should fail if input file matches specified output file' do
  110     sample_outpath = fixture_path 'sample.adoc'
  111     invoker = invoke_cli_to_buffer %W(-o #{sample_outpath}), 'sample.adoc'
  112     assert_match(/input file and output file cannot be the same/, invoker.read_error)
  113   end
  114 
  115   test 'should accept input from named pipe and output to stdout' do
  116     sample_inpath = fixture_path 'sample-pipe.adoc'
  117     begin
  118       %x(mkfifo #{sample_inpath})
  119       write_thread = Thread.new do
  120         File.write sample_inpath, 'pipe content'
  121       end
  122       invoker = invoke_cli_to_buffer %w(-a stylesheet!), sample_inpath
  123       result = invoker.read_output
  124       assert_match(/pipe content/, result)
  125       write_thread.join
  126     ensure
  127       FileUtils.rm_f sample_inpath
  128     end
  129   end unless windows?
  130 
  131   test 'should allow docdir to be specified when input is a string' do
  132     expected_docdir = fixturedir
  133     invoker = invoke_cli_to_buffer(%w(-s --base-dir test/fixtures -o /dev/null), '-') { 'content' }
  134     doc = invoker.document
  135     assert_equal expected_docdir, doc.attr('docdir')
  136     assert_equal expected_docdir, doc.base_dir
  137   end
  138 
  139   test 'should display version and exit' do
  140     expected = %(Asciidoctor #{Asciidoctor::VERSION} [https://asciidoctor.org]\nRuntime Environment (#{RUBY_DESCRIPTION}))
  141     ['--version', '-V'].each do |switch|
  142       actual = nil
  143       redirect_streams do |out, err|
  144         invoke_cli [switch]
  145         actual = out.string.rstrip
  146       end
  147       refute_nil actual
  148       assert actual.start_with?(expected), %(Expected to print version when using #{switch} switch)
  149     end
  150   end
  151 
  152   test 'should print warnings to stderr by default' do
  153     input = <<~'EOS'
  154     2. second
  155     3. third
  156     EOS
  157     warnings = nil
  158     redirect_streams do |out, err|
  159       invoke_cli_to_buffer(%w(-o /dev/null), '-') { input }
  160       warnings = err.string
  161     end
  162     assert_match(/WARNING/, warnings)
  163   end
  164 
  165   test 'should enable script warnings if -w flag is specified' do
  166     old_verbose, $VERBOSE = $VERBOSE, false
  167     begin
  168       warnings = nil
  169       redirect_streams do |out, err|
  170         invoke_cli_to_buffer(%w(-w -o /dev/null), '-') { $NO_SUCH_VARIABLE || 'text' }
  171         warnings = err.string
  172       end
  173       assert_equal false, $VERBOSE
  174       refute_empty warnings
  175     rescue
  176       $VERBOSE = old_verbose
  177     end
  178   end
  179 
  180   test 'should silence warnings if -q flag is specified' do
  181     input = <<~'EOS'
  182     2. second
  183     3. third
  184     EOS
  185     warnings = nil
  186     redirect_streams do |out, err|
  187       invoke_cli_to_buffer(%w(-q -o /dev/null), '-') { input }
  188       warnings = err.string
  189     end
  190     assert_equal '', warnings
  191   end
  192 
  193   test 'should not fail to check log level when -q flag is specified' do
  194     input = <<~'EOS'
  195     skip to <<install>>
  196 
  197     . download
  198     . install[[install]]
  199     . run
  200     EOS
  201     begin
  202       old_stderr, $stderr = $stderr, ::StringIO.new
  203       old_stdout, $stdout = $stdout, ::StringIO.new
  204       invoker = invoke_cli(%w(-q), '-') { input }
  205       assert_equal 0, invoker.code
  206     ensure
  207       $stderr = old_stderr
  208       $stdout = old_stdout
  209     end
  210   end
  211 
  212   test 'should return non-zero exit code if failure level is reached' do
  213     input = <<~'EOS'
  214     2. second
  215     3. third
  216     EOS
  217     exit_code, messages = redirect_streams do |_, err|
  218       [invoke_cli(%w(-q --failure-level=WARN -o /dev/null), '-') { input }.code, err.string]
  219     end
  220     assert_equal 1, exit_code
  221     assert messages.empty?
  222   end
  223 
  224   test 'should report usage if no input file given' do
  225     redirect_streams do |out, err|
  226       invoke_cli [], nil
  227       assert_match(/Usage:/, err.string)
  228     end
  229   end
  230 
  231   test 'should report error if input file does not exist' do
  232     redirect_streams do |out, err|
  233       invoker = invoke_cli [], 'missing_file.adoc'
  234       assert_match(/input file .* is missing/, err.string)
  235       assert_equal 1, invoker.code
  236     end
  237   end
  238 
  239   test 'should treat extra arguments as files' do
  240     redirect_streams do |out, err|
  241       invoker = invoke_cli %w(-o /dev/null extra arguments sample.adoc), nil
  242       assert_match(/input file .* is missing/, err.string)
  243       assert_equal 1, invoker.code
  244     end
  245   end
  246 
  247   test 'should output to file name based on input file name' do
  248     sample_outpath = fixture_path 'sample.html'
  249     begin
  250       invoker = invoke_cli
  251       doc = invoker.document
  252       assert_equal sample_outpath, doc.attr('outfile')
  253       assert File.exist?(sample_outpath)
  254       output = File.read(sample_outpath, mode: Asciidoctor::FILE_READ_MODE)
  255       refute_empty output
  256       assert_xpath '/html', output, 1
  257       assert_xpath '/html/head', output, 1
  258       assert_xpath '/html/body', output, 1
  259       assert_xpath '/html/head/title[text() = "Document Title"]', output, 1
  260       assert_xpath '/html/body/*[@id="header"]/h1[text() = "Document Title"]', output, 1
  261     ensure
  262       FileUtils.rm_f(sample_outpath)
  263     end
  264   end
  265 
  266   test 'should output to file in destination directory if set' do
  267     destination_path = File.join testdir, 'test_output'
  268     sample_outpath = File.join destination_path, 'sample.html'
  269     begin
  270       FileUtils.mkdir_p(destination_path)
  271       # QUESTION should -D be relative to working directory or source directory?
  272       invoker = invoke_cli %w(-D test/test_output)
  273       #invoker = invoke_cli %w(-D ../../test/test_output)
  274       doc = invoker.document
  275       assert_equal sample_outpath, doc.attr('outfile')
  276       assert File.exist?(sample_outpath)
  277     ensure
  278       FileUtils.rm_f(sample_outpath)
  279       FileUtils.rmdir(destination_path)
  280     end
  281   end
  282 
  283   test 'should preserve directory structure in destination directory if source directory is set' do
  284     sample_inpath = 'subdir/index.adoc'
  285     destination_path = 'test_output'
  286     destination_subdir_path = File.join destination_path, 'subdir'
  287     sample_outpath = File.join destination_subdir_path, 'index.html'
  288     begin
  289       FileUtils.mkdir_p(destination_path)
  290       invoke_cli %W(-D #{destination_path} -R test/fixtures), sample_inpath
  291       assert File.directory?(destination_subdir_path)
  292       assert File.exist?(sample_outpath)
  293     ensure
  294       FileUtils.rm_f(sample_outpath)
  295       FileUtils.rmdir(destination_subdir_path)
  296       FileUtils.rmdir(destination_path)
  297     end
  298   end
  299 
  300   test 'should output to file specified' do
  301     sample_outpath = fixture_path 'sample-output.html'
  302     begin
  303       invoker = invoke_cli %W(-o #{sample_outpath})
  304       doc = invoker.document
  305       assert_equal sample_outpath, doc.attr('outfile')
  306       assert File.exist?(sample_outpath)
  307     ensure
  308       FileUtils.rm_f(sample_outpath)
  309     end
  310   end
  311 
  312   test 'should copy default stylesheet to target directory if linkcss is specified' do
  313     sample_outpath = fixture_path 'sample-output.html'
  314     asciidoctor_stylesheet = fixture_path 'asciidoctor.css'
  315     coderay_stylesheet = fixture_path 'coderay-asciidoctor.css'
  316     begin
  317       invoke_cli %W(-o #{sample_outpath} -a linkcss -a source-highlighter=coderay), 'source-block.adoc'
  318       assert File.exist?(sample_outpath)
  319       assert File.exist?(asciidoctor_stylesheet)
  320       assert File.exist?(coderay_stylesheet)
  321     ensure
  322       FileUtils.rm_f(sample_outpath)
  323       FileUtils.rm_f(asciidoctor_stylesheet)
  324       FileUtils.rm_f(coderay_stylesheet)
  325     end
  326   end
  327 
  328   test 'should not copy coderay stylesheet to target directory when no source blocks where highlighted' do
  329     sample_outpath = fixture_path 'sample-output.html'
  330     asciidoctor_stylesheet = fixture_path 'asciidoctor.css'
  331     coderay_stylesheet = fixture_path 'coderay-asciidoctor.css'
  332     begin
  333       invoke_cli %W(-o #{sample_outpath} -a linkcss -a source-highlighter=coderay)
  334       assert File.exist?(sample_outpath)
  335       assert File.exist?(asciidoctor_stylesheet)
  336       refute File.exist?(coderay_stylesheet)
  337     ensure
  338       FileUtils.rm_f(sample_outpath)
  339       FileUtils.rm_f(asciidoctor_stylesheet)
  340       FileUtils.rm_f(coderay_stylesheet)
  341     end
  342   end
  343 
  344   test 'should not copy default stylesheet to target directory if linkcss is set and copycss is unset' do
  345     sample_outpath = fixture_path 'sample-output.html'
  346     default_stylesheet = fixture_path 'asciidoctor.css'
  347     begin
  348       invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a copycss!)
  349       invoker.document
  350       assert File.exist?(sample_outpath)
  351       refute File.exist?(default_stylesheet)
  352     ensure
  353       FileUtils.rm_f(sample_outpath)
  354       FileUtils.rm_f(default_stylesheet)
  355     end
  356   end
  357 
  358   test 'should copy custom stylesheet to target directory if stylesheet and linkcss is specified' do
  359     destdir = fixture_path 'output'
  360     sample_outpath = File.join destdir, 'sample-output.html'
  361     stylesdir = File.join destdir, 'styles'
  362     custom_stylesheet = File.join stylesdir, 'custom.css'
  363     begin
  364       invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a copycss=stylesheets/custom.css -a stylesdir=./styles -a stylesheet=custom.css)
  365       invoker.document
  366       assert File.exist?(sample_outpath)
  367       assert File.exist?(custom_stylesheet)
  368     ensure
  369       FileUtils.rm_f(sample_outpath)
  370       FileUtils.rm_f(custom_stylesheet)
  371       FileUtils.rmdir(stylesdir)
  372       FileUtils.rmdir(destdir)
  373     end
  374   end
  375 
  376   test 'should not copy custom stylesheet to target directory if stylesheet and linkcss are set and copycss is unset' do
  377     destdir = fixture_path 'output'
  378     sample_outpath = File.join destdir, 'sample-output.html'
  379     stylesdir = File.join destdir, 'styles'
  380     custom_stylesheet = File.join stylesdir, 'custom.css'
  381     begin
  382       invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a stylesdir=./styles -a stylesheet=custom.css -a copycss!)
  383       invoker.document
  384       assert File.exist?(sample_outpath)
  385       refute File.exist?(custom_stylesheet)
  386     ensure
  387       FileUtils.rm_f(sample_outpath)
  388       FileUtils.rm_f(custom_stylesheet)
  389       FileUtils.rmdir(stylesdir) if File.directory? stylesdir
  390       FileUtils.rmdir(destdir)
  391     end
  392   end
  393 
  394   test 'should not copy custom stylesheet to target directory if stylesdir is a URI' do
  395     destdir = fixture_path 'output'
  396     sample_outpath = File.join destdir, 'sample-output.html'
  397     stylesdir = File.join destdir, 'http:'
  398     begin
  399       invoker = invoke_cli %W(-o #{sample_outpath} -a linkcss -a stylesdir=http://example.org/styles -a stylesheet=custom.css)
  400       invoker.document
  401       assert File.exist?(sample_outpath)
  402       refute File.exist?(stylesdir)
  403     ensure
  404       FileUtils.rm_f(sample_outpath)
  405       FileUtils.rmdir(stylesdir) if File.directory? stylesdir
  406       FileUtils.rmdir(destdir)
  407     end
  408   end
  409 
  410   test 'should convert all passed files' do
  411     basic_outpath = fixture_path 'basic.html'
  412     sample_outpath = fixture_path 'sample.html'
  413     begin
  414       invoke_cli_with_filenames [], %w(basic.adoc sample.adoc)
  415       assert File.exist?(basic_outpath)
  416       assert File.exist?(sample_outpath)
  417     ensure
  418       FileUtils.rm_f(basic_outpath)
  419       FileUtils.rm_f(sample_outpath)
  420     end
  421   end
  422 
  423   test 'options should not be modified when processing multiple files' do
  424     destination_path = File.join testdir, 'test_output'
  425     basic_outpath = File.join destination_path, 'basic.htm'
  426     sample_outpath = File.join destination_path, 'sample.htm'
  427     begin
  428       invoke_cli_with_filenames %w(-D test/test_output -a outfilesuffix=.htm), %w(basic.adoc sample.adoc)
  429       assert File.exist?(basic_outpath)
  430       assert File.exist?(sample_outpath)
  431     ensure
  432       FileUtils.rm_f(basic_outpath)
  433       FileUtils.rm_f(sample_outpath)
  434       FileUtils.rmdir(destination_path)
  435     end
  436   end
  437 
  438   test 'should convert all files that matches a glob expression' do
  439     basic_outpath = fixture_path 'basic.html'
  440     begin
  441       invoke_cli_to_buffer [], "ba*.adoc"
  442       assert File.exist?(basic_outpath)
  443     ensure
  444       FileUtils.rm_f(basic_outpath)
  445     end
  446   end
  447 
  448   test 'should convert all files that matches an absolute path glob expression' do
  449     basic_outpath = fixture_path 'basic.html'
  450     glob = fixture_path 'ba*.adoc'
  451     # test Windows using backslash-style pathname
  452     if File::ALT_SEPARATOR == '\\'
  453       glob = glob.tr '/', '\\'
  454     end
  455 
  456     begin
  457       invoke_cli_to_buffer [], glob
  458       assert File.exist?(basic_outpath)
  459     ensure
  460       FileUtils.rm_f(basic_outpath)
  461     end
  462   end
  463 
  464   test 'should suppress header footer if specified' do
  465     [%w(-s -o -), %w(-e -o -)].each do |flags|
  466       invoker = invoke_cli_to_buffer flags
  467       output = invoker.read_output
  468       assert_xpath '/html', output, 0
  469       assert_xpath '/*[@id="preamble"]', output, 1
  470     end
  471   end
  472 
  473   test 'should write page for each alternate manname' do
  474     outdir = fixturedir
  475     outfile_1 = File.join outdir, 'eve.1'
  476     outfile_2 = File.join outdir, 'islifeform.1'
  477     input = <<~'EOS'
  478     = eve(1)
  479     Andrew Stanton
  480     v1.0.0
  481     :doctype: manpage
  482     :manmanual: EVE
  483     :mansource: EVE
  484 
  485     == NAME
  486 
  487     eve, islifeform - analyzes an image to determine if it's a picture of a life form
  488 
  489     == SYNOPSIS
  490 
  491     *eve* ['OPTION']... 'FILE'...
  492     EOS
  493 
  494     begin
  495       invoke_cli(%W(-b manpage -o #{outfile_1}), '-') { input }
  496       assert File.exist?(outfile_1)
  497       assert File.exist?(outfile_2)
  498       assert_equal '.so eve.1', (File.read outfile_2, mode: Asciidoctor::FILE_READ_MODE).chomp
  499     ensure
  500       FileUtils.rm_f outfile_1
  501       FileUtils.rm_f outfile_2
  502     end
  503   end
  504 
  505   test 'should output a trailing newline to stdout' do
  506     invoker = nil
  507     output = nil
  508     redirect_streams do |out, err|
  509       invoker = invoke_cli %w(-o -)
  510       output = out.string
  511     end
  512     refute_nil invoker
  513     refute_nil output
  514     assert output.end_with?("\n")
  515   end
  516 
  517   test 'should set backend to html5 if specified' do
  518     invoker = invoke_cli_to_buffer %w(-b html5 -o -)
  519     doc = invoker.document
  520     assert_equal 'html5', doc.attr('backend')
  521     assert_equal '.html', doc.attr('outfilesuffix')
  522     output = invoker.read_output
  523     assert_xpath '/html', output, 1
  524   end
  525 
  526   test 'should set backend to docbook5 if specified' do
  527     invoker = invoke_cli_to_buffer %w(-b docbook5 -a xmlns -o -)
  528     doc = invoker.document
  529     assert_equal 'docbook5', doc.attr('backend')
  530     assert_equal '.xml', doc.attr('outfilesuffix')
  531     output = invoker.read_output
  532     assert_xpath '/xmlns:article', output, 1
  533   end
  534 
  535   test 'should set doctype to article if specified' do
  536     invoker = invoke_cli_to_buffer %w(-d article -o -)
  537     doc = invoker.document
  538     assert_equal 'article', doc.attr('doctype')
  539     output = invoker.read_output
  540     assert_xpath '/html/body[@class="article"]', output, 1
  541   end
  542 
  543   test 'should set doctype to book if specified' do
  544     invoker = invoke_cli_to_buffer %w(-d book -o -)
  545     doc = invoker.document
  546     assert_equal 'book', doc.attr('doctype')
  547     output = invoker.read_output
  548     assert_xpath '/html/body[@class="book"]', output, 1
  549   end
  550 
  551   test 'should warn if doctype is inline and the first block is not a candidate for inline conversion' do
  552     ['== Section Title', 'image::tiger.png[]'].each do |input|
  553       warnings = redirect_streams do |out, err|
  554         invoke_cli_to_buffer(%w(-d inline), '-') { input }
  555         err.string
  556       end
  557       assert_match(/WARNING: no inline candidate/, warnings)
  558     end
  559   end
  560 
  561   test 'should not warn if doctype is inline and the document has no blocks' do
  562     warnings = redirect_streams do |out, err|
  563       invoke_cli_to_buffer(%w(-d inline), '-') { '// comment' }
  564       err.string
  565     end
  566     refute_match(/WARNING/, warnings)
  567   end
  568 
  569   test 'should not warn if doctype is inline and the document contains multiple blocks' do
  570     warnings = redirect_streams do |out, err|
  571       invoke_cli_to_buffer(%w(-d inline), '-') { %(paragraph one\n\nparagraph two\n\nparagraph three) }
  572       err.string
  573     end
  574     refute_match(/WARNING/, warnings)
  575   end
  576 
  577   test 'should locate custom templates based on template dir, template engine and backend' do
  578     custom_backend_root = fixture_path 'custom-backends'
  579     invoker = invoke_cli_to_buffer %W(-E haml -T #{custom_backend_root} -o -)
  580     doc = invoker.document
  581     assert_kind_of Asciidoctor::Converter::CompositeConverter, doc.converter
  582     selected = doc.converter.find_converter 'paragraph'
  583     assert_kind_of Asciidoctor::Converter::TemplateConverter, selected
  584     assert_kind_of Tilt::HamlTemplate, selected.templates['paragraph']
  585   end
  586 
  587   test 'should load custom templates from multiple template directories' do
  588     custom_backend_1 = fixture_path 'custom-backends/haml/html5'
  589     custom_backend_2 = fixture_path 'custom-backends/haml/html5-tweaks'
  590     invoker = invoke_cli_to_buffer %W(-T #{custom_backend_1} -T #{custom_backend_2} -o - -s)
  591     output = invoker.read_output
  592     assert_css '.paragraph', output, 0
  593     assert_css '#preamble > .sectionbody > p', output, 1
  594   end
  595 
  596   test 'should set attribute with value' do
  597     invoker = invoke_cli_to_buffer %w(--trace -a idprefix=id -s -o -)
  598     doc = invoker.document
  599     assert_equal 'id', doc.attr('idprefix')
  600     output = invoker.read_output
  601     assert_xpath '//h2[@id="idsection_a"]', output, 1
  602   end
  603 
  604   test 'should set attribute with value containing equal sign' do
  605     invoker = invoke_cli_to_buffer %w(--trace -a toc -a toc-title=t=o=c -o -)
  606     doc = invoker.document
  607     assert_equal 't=o=c', doc.attr('toc-title')
  608     output = invoker.read_output
  609     assert_xpath '//*[@id="toctitle"][text() = "t=o=c"]', output, 1
  610   end
  611 
  612   test 'should set attribute with quoted value containing a space' do
  613     # emulating commandline arguments: --trace -a toc -a note-caption="Note to self:" -o -
  614     invoker = invoke_cli_to_buffer %w(--trace -a toc -a note-caption=Note\ to\ self: -o -)
  615     doc = invoker.document
  616     assert_equal 'Note to self:', doc.attr('note-caption')
  617     output = invoker.read_output
  618     assert_xpath %(//*[#{contains_class('admonitionblock')}]//*[@class='title'][text() = 'Note to self:']), output, 1
  619   end
  620 
  621   test 'should not set attribute ending in @ if defined in document' do
  622     invoker = invoke_cli_to_buffer %w(--trace -a idprefix=id@ -s -o -)
  623     doc = invoker.document
  624     assert_equal 'id_', doc.attr('idprefix')
  625     output = invoker.read_output
  626     assert_xpath '//h2[@id="id_section_a"]', output, 1
  627   end
  628 
  629   test 'should set attribute with no value' do
  630     invoker = invoke_cli_to_buffer %w(-a icons -s -o -)
  631     doc = invoker.document
  632     assert_equal '', doc.attr('icons')
  633     output = invoker.read_output
  634     assert_xpath '//*[@class="admonitionblock note"]//img[@alt="Note"]', output, 1
  635   end
  636 
  637   test 'should unset attribute ending in bang' do
  638     invoker = invoke_cli_to_buffer %w(-a sectids! -s -o -)
  639     doc = invoker.document
  640     refute doc.attr?('sectids')
  641     output = invoker.read_output
  642     # leave the count loose in case we add more sections
  643     assert_xpath '//h2[not(@id)]', output
  644   end
  645 
  646   test 'default mode for cli should be unsafe' do
  647     invoker = invoke_cli_to_buffer %w(-o /dev/null)
  648     doc = invoker.document
  649     assert_equal Asciidoctor::SafeMode::UNSAFE, doc.safe
  650   end
  651 
  652   test 'should set safe mode if specified' do
  653     invoker = invoke_cli_to_buffer %w(--safe -o /dev/null)
  654     doc = invoker.document
  655     assert_equal Asciidoctor::SafeMode::SAFE, doc.safe
  656   end
  657 
  658   test 'should set safe mode to specified level' do
  659     levels = {
  660       'unsafe' => Asciidoctor::SafeMode::UNSAFE,
  661       'safe'   => Asciidoctor::SafeMode::SAFE,
  662       'server' => Asciidoctor::SafeMode::SERVER,
  663       'secure' => Asciidoctor::SafeMode::SECURE,
  664     }
  665     levels.each do |name, const|
  666       invoker = invoke_cli_to_buffer %W(-S #{name} -o /dev/null)
  667       doc = invoker.document
  668       assert_equal const, doc.safe
  669     end
  670   end
  671 
  672   test 'should set eRuby impl if specified' do
  673     invoker = invoke_cli_to_buffer %w(--eruby erubis -o /dev/null)
  674     doc = invoker.document
  675     assert_equal 'erubis', doc.instance_variable_get('@options')[:eruby]
  676   end
  677 
  678   test 'should force default external encoding to UTF-8' do
  679     input_path = fixture_path 'encoding.adoc'
  680     # using open3 to work around a bug in JRuby process_manager.rb,
  681     # which tries to run a gsub on stdout prematurely breaking the test
  682     # warnings may be issued, so don't assert on stderr
  683     stdout_lines = run_command({ 'LANG' => 'US-ASCII' }, %(#{asciidoctor_cmd} -o - --trace #{input_path})) {|out| out.readlines }
  684     refute_empty stdout_lines
  685     # NOTE Ruby on Windows runs with a IBM437 encoding by default
  686     stdout_lines.each {|l| l.force_encoding Encoding::UTF_8 } unless Encoding.default_external == Encoding::UTF_8
  687     stdout_str = stdout_lines.join
  688     assert_includes stdout_str, 'Codierungen sind verrückt auf älteren Versionen von Ruby'
  689   end
  690 
  691   test 'should force stdio encoding to UTF-8' do
  692     result = run_command(%(#{asciidoctor_cmd true, '-E IBM866:IBM866'} -r #{fixture_path 'configure-stdin.rb'} -s -o - -)) {|out| out.read }
  693     # NOTE Ruby on Windows runs with a IBM437 encoding by default
  694     result.force_encoding Encoding::UTF_8 unless Encoding.default_external == Encoding::UTF_8
  695     assert_equal Encoding::UTF_8, result.encoding
  696     assert_include '<p>é</p>', result
  697     assert_include '<p>IBM866:IBM866</p>', result
  698   end
  699 
  700   test 'should not fail to load if call to Dir.home fails' do
  701     rubyopt = %(-r #{fixture_path 'undef-dir-home.rb'})
  702     result = run_command(%(#{asciidoctor_cmd true, rubyopt} -s -o - #{fixture_path 'basic.adoc'})) {|out| out.read }
  703     assert_include 'Body content', result
  704   end
  705 
  706   test 'should print timings when -t flag is specified' do
  707     input = 'Sample *AsciiDoc*'
  708     invoker = nil
  709     error = nil
  710     redirect_streams do |_, err|
  711       invoker = invoke_cli(%w(-t -o /dev/null), '-') { input }
  712       error = err.string
  713     end
  714     refute_nil invoker
  715     refute_nil error
  716     assert_match(/Total time/, error)
  717   end
  718 
  719   test 'should show timezone as UTC if system TZ is set to UTC' do
  720     input_path = fixture_path 'doctime-localtime.adoc'
  721     output = run_command({ 'TZ' => 'UTC', 'SOURCE_DATE_EPOCH' => nil }, %(#{asciidoctor_cmd} -d inline -o - -s #{input_path})) {|out| out.read }
  722     doctime, localtime = output.lines.map(&:chomp)
  723     assert doctime.end_with?(' UTC')
  724     assert localtime.end_with?(' UTC')
  725   end
  726 
  727   test 'should show timezone as offset if system TZ is not set to UTC' do
  728     input_path = fixture_path 'doctime-localtime.adoc'
  729     output = run_command({ 'TZ' => 'EST+5', 'SOURCE_DATE_EPOCH' => nil }, %(#{asciidoctor_cmd} -d inline -o - -s #{input_path})) {|out| out.read }
  730     doctime, localtime = output.lines.map(&:chomp)
  731     assert doctime.end_with?(' -0500')
  732     assert localtime.end_with?(' -0500')
  733   end
  734 
  735   test 'should use SOURCE_DATE_EPOCH as modified time of input file and local time' do
  736     old_source_date_epoch = ENV.delete 'SOURCE_DATE_EPOCH'
  737     begin
  738       ENV['SOURCE_DATE_EPOCH'] = '1234123412'
  739       sample_filepath = fixture_path 'sample.adoc'
  740       invoker = invoke_cli_to_buffer %w(-o /dev/null), sample_filepath
  741       doc = invoker.document
  742       assert_equal '2009-02-08', (doc.attr 'docdate')
  743       assert_equal '2009', (doc.attr 'docyear')
  744       assert_match(/2009-02-08 20:03:32 UTC/, (doc.attr 'docdatetime'))
  745       assert_equal '2009-02-08', (doc.attr 'localdate')
  746       assert_equal '2009', (doc.attr 'localyear')
  747       assert_match(/2009-02-08 20:03:32 UTC/, (doc.attr 'localdatetime'))
  748     ensure
  749       if old_source_date_epoch
  750         ENV['SOURCE_DATE_EPOCH'] = old_source_date_epoch
  751       else
  752         ENV.delete 'SOURCE_DATE_EPOCH'
  753       end
  754     end
  755   end
  756 
  757   test 'should fail if SOURCE_DATE_EPOCH is malformed' do
  758     old_source_date_epoch = ENV.delete 'SOURCE_DATE_EPOCH'
  759     begin
  760       ENV['SOURCE_DATE_EPOCH'] = 'aaaaaaaa'
  761       sample_filepath = fixture_path 'sample.adoc'
  762       assert_equal 1, (invoke_cli_to_buffer %w(-o /dev/null), sample_filepath).code
  763     ensure
  764       if old_source_date_epoch
  765         ENV['SOURCE_DATE_EPOCH'] = old_source_date_epoch
  766       else
  767         ENV.delete 'SOURCE_DATE_EPOCH'
  768       end
  769     end
  770   end
  771 end