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<Project>(s => s
.Query(q => q
.QueryString(m => 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