resources/asciidoctor/spec/alternative_language_lookup_spec.rb (475 lines of code) (raw):

# frozen_string_literal: true require 'json' require 'tempfile' require 'alternative_language_lookup/extension' RSpec.describe AlternativeLanguageLookup::AlternativeLanguageLookup do before(:each) do Asciidoctor::Extensions.register AlternativeLanguageLookup end after(:each) do Asciidoctor::Extensions.unregister_all end let(:spec_dir) { File.dirname(__FILE__) } let(:example_alternatives) do "#{spec_dir}/resources/alternative_language_lookup" end let(:one_snippet) do <<~ASCIIDOC [source,console] ---- #{snippet_contents} ---- ASCIIDOC end shared_examples "doesn't modify the output" do it "doesn't modify the output" do expect(converted).to eq <<~HTML.strip <div id="preamble"> <div class="sectionbody"> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">#{snippet_contents}</code></pre> </div> </div> </div> </div> HTML end end context 'when it is not configured' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /' } include_examples "doesn't modify the output" end context 'when it is configured to an empty string' do include_context 'convert without logs' let(:convert_attributes) { { 'alternative_language_lookups' => '' } } let(:input) { one_snippet } let(:snippet_contents) { 'GET /' } include_examples "doesn't modify the output" end context 'when it is configured to a missing directory' do include_context 'convert with logs' let(:config) do <<~CSV console,missing,#{example_alternatives}/missing CSV end let(:convert_attributes) { { 'alternative_language_lookups' => config } } let(:input) { one_snippet } let(:snippet_contents) { 'GET /' } include_examples "doesn't modify the output" it 'logs an error for the missing directory' do expect(logs).to eq(<<~LOG.strip) ERROR: invalid alternative_language_lookups, [#{example_alternatives}/missing] doesn't exist LOG end end context 'when it is configured for a different language' do include_context 'convert without logs' let(:config) do <<~CSV missing,js,#{example_alternatives}/js CSV end let(:convert_attributes) { { 'alternative_language_lookups' => config } } let(:input) { one_snippet } let(:snippet_contents) { 'GET /' } include_examples "doesn't modify the output" end context 'when it is configured' do let(:config) do <<~CSV console,js,#{example_alternatives}/js console,csharp,#{example_alternatives}/csharp console,java,#{example_alternatives}/java CSV end # Important: we have to keep a hard reference to these tempfile objects # until the test is done so they aren't deleted. let(:report_file) { Tempfile.new %w[alternatives_report .json] } let(:summary_file) { Tempfile.new %w[alternatives_summary .json] } let(:convert_attributes) do { 'alternative_language_lookups' => config, 'alternative_language_report' => report_file.path, 'alternative_language_summary' => summary_file.path, } end let(:report) do # read the result of the conversion to populate the report converted # grab the contents txt = File.read report_file.path JSON.parse txt, symbolize_names: true end let(:summary) do # read the result of the conversion to populate the summary converted # grab the contents txt = File.read summary_file.path JSON.parse txt, symbolize_names: true end context "when there aren't any alternatives" do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /no_alternatives' } it 'only adds the digest' do expect(converted).to eq <<~HTML.strip <div id="preamble"> <div class="sectionbody"> <a id="3fcdfa6097c68c04f3e175dcf3934af6"></a> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">#{snippet_contents}</code></pre> </div> </div> </div> </div> HTML end context 'the alternatives report' do it 'contains an entry for the snippet' do expect(report).to eq( [ { source_location: { file: '<stdin>', line: 2 }, digest: '3fcdfa6097c68c04f3e175dcf3934af6', lang: 'console', found: [], source: snippet_contents, }, ] ) end end context 'the summary' do it 'shows everything as missing' do expect(summary).to eq( console: { total: 1, alternatives: { js: { found: 0 }, csharp: { found: 0 }, java: { found: 0 }, }, } ) end end end context 'when there is a single alternative' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /just_js_alternative' } context 'the conversion' do it 'contains the existing alternative' do expect(converted).to include <<~HTML <div class="listingblock alternative"> <div class="content"> <pre class="highlight"><code class="language-js" data-lang="js">console.info('just js alternative');</code></pre> </div> </div> HTML end it 'contains the default' do expect(converted).to include <<~HTML <div class="listingblock default has-js"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">GET /just_js_alternative</code></pre> </div> </div> HTML end it "doesn't contain any missing alternative" do expect(converted).not_to include 'data-lang="csharp"' expect(converted).not_to include 'data-lang="java"' end end context 'the alternatives report' do it 'shows only js populated' do expect(report).to eq( [ { source_location: { file: '<stdin>', line: 2 }, digest: '39f76498cca438ba11af18a7075d24c9', lang: 'console', found: ['js'], source: snippet_contents, }, ] ) end end context 'the summary' do it 'shows only js found' do expect(summary).to eq( console: { total: 1, alternatives: { js: { found: 1 }, csharp: { found: 0 }, java: { found: 0 }, }, } ) end end end context 'when all alternatives exist' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /all_alternatives' } context 'the conversion' do it 'contains the js alternative' do expect(converted).to include <<~HTML <div class="listingblock alternative"> <div class="content"> <pre class="highlight"><code class="language-js" data-lang="js">console.info('all alternatives');</code></pre> </div> </div> HTML end it 'contains the csharp alternative' do expect(converted).to include <<~HTML <div class="listingblock alternative"> <div class="content"> <pre class="highlight"><code class="language-csharp" data-lang="csharp">Console.WriteLine("all alternatives");</code></pre> </div> </div> HTML end it 'contains the java alternative' do expect(converted).to include <<~HTML <div class="listingblock alternative"> <div class="content"> <pre class="highlight"><code class="language-java" data-lang="java">System.out.println("all alternatives");</code></pre> </div> </div> HTML end it 'contains the contains the default' do expect(converted).to include <<~HTML <div class="listingblock default has-js has-csharp has-java"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">GET /all_alternatives</code></pre> </div> </div> HTML end end context 'the alternatives report' do it 'shows all languages populated' do expect(report).to eq( [ { source_location: { file: '<stdin>', line: 2 }, digest: '5712902c12d9db15d01e8639ece9ec84', lang: 'console', found: %w[js csharp java], source: snippet_contents, }, ] ) end end context 'the summary' do it 'shows only js found' do expect(summary).to eq( console: { total: 1, alternatives: { js: { found: 1 }, csharp: { found: 1 }, java: { found: 1 }, }, } ) end end end context 'when there are alternative results' do include_context 'convert without logs' let(:input) do <<~ASCIIDOC [source,console] ---- #{snippet_contents} ---- [source,console-result] ---- #{result_contents} ---- ASCIIDOC end let(:snippet_contents) { 'GET /just_js_alternative' } let(:result_contents) { '{"just_js_result": {}}' } context 'the conversion' do it 'contain the alternative request' do expect(converted).to include <<~HTML.strip <code class="language-js" data-lang="js"> HTML end it 'contain the default request' do expect(converted).to include <<~HTML.strip <code class="language-console" data-lang="console"> HTML end it 'contain the alternative result' do expect(converted).to include <<~HTML.strip <code class="language-js-result" data-lang="js-result"> HTML end it 'contain the default result' do expect(converted).to include <<~HTML.strip <code class="language-console-result" data-lang="console-result"> HTML end end context 'the alternatives report' do it 'includes the request snippet' do expect(report).to include( source_location: { file: '<stdin>', line: 2 }, digest: '39f76498cca438ba11af18a7075d24c9', lang: 'console', found: ['js'], source: snippet_contents ) end it 'includes the result snippet' do expect(report).to include( source_location: { file: '<stdin>', line: 7 }, digest: 'c4f54085e4784ead2ef4a758d03edd16', lang: 'console-result', found: ['js'], source: result_contents ) end end context 'the summary' do it 'counts the result' do expect(summary).to eq( console: { total: 2, alternatives: { js: { found: 2 }, csharp: { found: 0 }, java: { found: 0 }, }, } ) end end end context 'when the alternative has characters that must be escaped' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /has_<' } it 'adds the alternative' do expect(converted).to include <<~HTML.strip var searchResponse = _client.Search&lt;Project&gt;(s =&gt; s .Query(q =&gt; q .QueryString(m =&gt; m .Query("foo bar") ) ) ); HTML end end context 'when the alternative includes another file' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /has_include' } it 'adds the alternative' do expect(converted).to include(<<~CSHARP.strip) Console.WriteLine("Hello World!"); CSHARP end end context 'when the alternative is in a subdirectory' do include_context 'convert without logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /in_subdir' } it 'adds the alternative' do expect(converted).to include(<<~CSHARP.strip) Console.WriteLine("In subdir"); CSHARP end end context 'when there are callouts' do include_context 'convert without logs' let(:input) do <<~ASCIIDOC [source,console] ---- GET /there_are_callouts <1> <2> ---- <1> a <2> b ASCIIDOC end it 'inserts the alternative code above the default code' do expect(converted).to include <<~HTML <pre class="highlight"><code class="language-csharp" data-lang="csharp">Console.WriteLine("there are callouts"); <b class="conum">(1)</b> <b class="conum">(2)</b></code></pre> </div> </div> <a id="9e01493a85c06a5100ff712f6b3eead4"></a> <div class="listingblock default has-csharp"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">GET /there_are_callouts <b class="conum">(1)</b> <b class="conum">(2)</b></code></pre> HTML end it 'inserts the alternative callouts above the default callouts' do expect(converted).to include <<~HTML <div class="colist arabic alternative lang-csharp"> <ol> <li> <p>csharp a</p> </li> <li> <p>csharp b</p> </li> </ol> </div> <div class="colist arabic default has-csharp lang-console"> HTML end end context 'when there is an error in the alternative' do include_context 'convert with logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /has_error' } it 'adds the alternative with the error text' do expect(converted).to include <<~HTML.strip include::missing.adoc[] HTML end it 'logs an error' do expect(logs).to eq(<<~LOG.strip) ERROR: resources/alternative_language_lookup/csharp/ded0ba409b7c66489d5833dc6aa5f696.adoc: line 3: include file not found: #{example_alternatives}/csharp/missing.adoc LOG end end context 'when the alternative has the wrong language' do include_context 'convert with logs' let(:input) { one_snippet } let(:snippet_contents) { 'GET /bad_language' } it "doesn't add the alternative" do expect(converted).not_to include('Console.WriteLine') end it 'logs a warning' do expect(logs).to eq(<<~LOG.strip) WARN: resources/alternative_language_lookup/csharp/fcac4757ba45b9b14f316eb9bda58584.adoc: line 2: Alternative language listing must have lang=csharp but was not_csharp. LOG end end context 'when the configuration has duplicates' do include_context 'convert with logs' let(:config) do <<~CSV console,js,#{example_alternatives}/js console,js,#{example_alternatives}/js CSV end let(:input) { one_snippet } let(:snippet_contents) { 'GET /will_fail' } it 'logs an error' do expect(logs).to eq(<<~LOG.strip) ERROR: invalid alternative_language_lookups, duplicate alternative_lang [js] LOG end end end end