summaryrefslogtreecommitdiff
path: root/spec/scripts/lib/glfm/update_specification_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/scripts/lib/glfm/update_specification_spec.rb')
-rw-r--r--spec/scripts/lib/glfm/update_specification_spec.rb196
1 files changed, 196 insertions, 0 deletions
diff --git a/spec/scripts/lib/glfm/update_specification_spec.rb b/spec/scripts/lib/glfm/update_specification_spec.rb
new file mode 100644
index 00000000000..e8d34b13efa
--- /dev/null
+++ b/spec/scripts/lib/glfm/update_specification_spec.rb
@@ -0,0 +1,196 @@
+# frozen_string_literal: true
+require 'fast_spec_helper'
+require_relative '../../../../scripts/lib/glfm/update_specification'
+
+RSpec.describe Glfm::UpdateSpecification, '#process' do
+ subject { described_class.new }
+
+ let(:ghfm_spec_txt_uri) { described_class::GHFM_SPEC_TXT_URI }
+ let(:ghfm_spec_txt_uri_io) { StringIO.new(ghfm_spec_txt_contents) }
+ let(:ghfm_spec_txt_path) { described_class::GHFM_SPEC_TXT_PATH }
+ let(:ghfm_spec_txt_local_io) { StringIO.new(ghfm_spec_txt_contents) }
+
+ let(:glfm_intro_txt_path) { described_class::GLFM_INTRO_TXT_PATH }
+ let(:glfm_intro_txt_io) { StringIO.new(glfm_intro_txt_contents) }
+ let(:glfm_examples_txt_path) { described_class::GLFM_EXAMPLES_TXT_PATH }
+ let(:glfm_examples_txt_io) { StringIO.new(glfm_examples_txt_contents) }
+ let(:glfm_spec_txt_path) { described_class::GLFM_SPEC_TXT_PATH }
+ let(:glfm_spec_txt_io) { StringIO.new }
+
+ let(:ghfm_spec_txt_contents) do
+ <<~GHFM_SPEC_TXT_CONTENTS
+ ---
+ title: GitHub Flavored Markdown Spec
+ version: 0.29
+ date: '2019-04-06'
+ license: '[CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)'
+ ...
+
+ # Introduction
+
+ ## What is GitHub Flavored Markdown?
+
+ It's like GLFM, but with an H.
+
+ # Section with Examples
+
+ ## Strong
+
+ ```````````````````````````````` example
+ __bold__
+ .
+ <p><strong>bold</strong></p>
+ ````````````````````````````````
+
+ End of last GitHub examples section.
+
+ <!-- END TESTS -->
+
+ # Appendix
+
+ Appendix text.
+ GHFM_SPEC_TXT_CONTENTS
+ end
+
+ let(:glfm_intro_txt_contents) do
+ <<~GLFM_INTRO_TXT_CONTENTS
+ # Introduction
+
+ ## What is GitLab Flavored Markdown?
+
+ Intro text about GitLab Flavored Markdown.
+ GLFM_INTRO_TXT_CONTENTS
+ end
+
+ let(:glfm_examples_txt_contents) do
+ <<~GLFM_EXAMPLES_TXT_CONTENTS
+ # GitLab-Specific Section with Examples
+
+ Some examples.
+ GLFM_EXAMPLES_TXT_CONTENTS
+ end
+
+ before do
+ # Mock default ENV var values
+ allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_TXT').and_return(nil)
+ allow(ENV).to receive(:[]).and_call_original
+
+ # We mock out the URI and local file IO objects with real StringIO, instead of just mock
+ # objects. This gives better and more realistic coverage, while still avoiding
+ # actual network and filesystem I/O during the spec run.
+ allow(URI).to receive(:open).with(ghfm_spec_txt_uri) { ghfm_spec_txt_uri_io }
+ allow(File).to receive(:open).with(ghfm_spec_txt_path) { ghfm_spec_txt_local_io }
+ allow(File).to receive(:open).with(glfm_intro_txt_path) { glfm_intro_txt_io }
+ allow(File).to receive(:open).with(glfm_examples_txt_path) { glfm_examples_txt_io }
+ allow(File).to receive(:open).with(glfm_spec_txt_path, 'w') { glfm_spec_txt_io }
+
+ # Prevent console output when running tests
+ allow(subject).to receive(:output)
+ end
+
+ describe 'retrieving latest GHFM spec.txt' do
+ context 'when UPDATE_GHFM_SPEC_TXT is not true (default)' do
+ it 'does not download' do
+ expect(URI).not_to receive(:open).with(ghfm_spec_txt_uri)
+
+ subject.process
+
+ expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
+ end
+ end
+
+ context 'when UPDATE_GHFM_SPEC_TXT is true' do
+ let(:ghfm_spec_txt_local_io) { StringIO.new }
+
+ before do
+ allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_TXT').and_return('true')
+ allow(File).to receive(:open).with(ghfm_spec_txt_path, 'w') { ghfm_spec_txt_local_io }
+ end
+
+ context 'with success' do
+ it 'downloads and saves' do
+ subject.process
+
+ expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
+ end
+ end
+
+ context 'with error handling' do
+ context 'with a version mismatch' do
+ let(:ghfm_spec_txt_contents) do
+ <<~GHFM_SPEC_TXT_CONTENTS
+ ---
+ title: GitHub Flavored Markdown Spec
+ version: 0.30
+ ...
+ GHFM_SPEC_TXT_CONTENTS
+ end
+
+ it 'raises an error' do
+ expect { subject.process }.to raise_error /version mismatch.*expected.*29.*got.*30/i
+ end
+ end
+
+ context 'with a failed read of file lines' do
+ let(:ghfm_spec_txt_contents) { '' }
+
+ it 'raises an error if lines cannot be read' do
+ expect { subject.process }.to raise_error /unable to read lines/i
+ end
+ end
+
+ context 'with a failed re-read of file string' do
+ before do
+ allow(ghfm_spec_txt_uri_io).to receive(:read).and_return(nil)
+ end
+
+ it 'raises an error if file is blank' do
+ expect { subject.process }.to raise_error /unable to read string/i
+ end
+ end
+ end
+ end
+ end
+
+ describe 'writing GLFM spec.txt' do
+ let(:glfm_contents) { reread_io(glfm_spec_txt_io) }
+
+ before do
+ subject.process
+ end
+
+ it 'replaces the header text with the GitLab version' do
+ expect(glfm_contents).not_to match(/GitHub Flavored Markdown Spec/m)
+ expect(glfm_contents).not_to match(/^version: \d\.\d/m)
+ expect(glfm_contents).not_to match(/^date: /m)
+ expect(glfm_contents).not_to match(/^license: /m)
+ expect(glfm_contents).to match(/#{Regexp.escape(described_class::GLFM_SPEC_TXT_HEADER)}\n/mo)
+ end
+
+ it 'replaces the intro section with the GitLab version' do
+ expect(glfm_contents).not_to match(/What is GitHub Flavored Markdown/m)
+ expect(glfm_contents).to match(/#{Regexp.escape(glfm_intro_txt_contents)}/m)
+ end
+
+ it 'inserts the GitLab examples sections before the appendix section' do
+ expected = <<~GHFM_SPEC_TXT_CONTENTS
+ End of last GitHub examples section.
+
+ # GitLab-Specific Section with Examples
+
+ Some examples.
+
+ <!-- END TESTS -->
+
+ # Appendix
+ GHFM_SPEC_TXT_CONTENTS
+ expect(glfm_contents).to match(/#{Regexp.escape(expected)}/m)
+ end
+ end
+
+ def reread_io(io)
+ # Reset the io StringIO to the beginning position of the buffer
+ io.seek(0)
+ io.read
+ end
+end