# frozen_string_literal: true require 'fast_spec_helper' require_relative '../../../../scripts/lib/glfm/update_example_snapshots' RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do subject { described_class.new } # GLFM input files let(:glfm_spec_txt_path) { described_class::GLFM_SPEC_TXT_PATH } let(:glfm_spec_txt_local_io) { StringIO.new(glfm_spec_txt_contents) } let(:glfm_example_status_yml_path) { described_class::GLFM_EXAMPLE_STATUS_YML_PATH } let(:glfm_example_status_yml_io) { StringIO.new(glfm_example_status_yml_contents) } # Example Snapshot (ES) output files let(:es_examples_index_yml_path) { described_class::ES_EXAMPLES_INDEX_YML_PATH } let(:es_examples_index_yml_io) { StringIO.new } let(:es_markdown_yml_path) { described_class::ES_MARKDOWN_YML_PATH } let(:es_markdown_yml_io) { StringIO.new } let(:es_html_yml_path) { described_class::ES_HTML_YML_PATH } let(:es_html_yml_io) { StringIO.new } let(:es_prosemirror_json_yml_path) { described_class::ES_PROSEMIRROR_JSON_YML_PATH } let(:es_prosemirror_json_yml_io) { StringIO.new } # Internal tempfiles let(:static_html_tempfile_path) { Tempfile.new.path } let(:glfm_spec_txt_contents) do <<~GLFM_SPEC_TXT_CONTENTS --- title: GitLab Flavored Markdown Spec ... # Introduction GLFM intro text... # Inlines ## Strong ```````````````````````````````` example __bold__ .

bold

```````````````````````````````` ```````````````````````````````` example strikethrough __bold with more text__ .

bold with more text

````````````````````````````````
## Strikethrough (extension) GFM enables the `strikethrough` extension. ```````````````````````````````` example strikethrough ~~Hi~~ Hello, world! .

Hi Hello, world!

````````````````````````````````
End of last GitHub examples section. # First GitLab-Specific Section with Examples ## Strong but with two asterisks ```````````````````````````````` example gitlab strong **bold** .

bold

```````````````````````````````` # Second GitLab-Specific Section with Examples ## Strong but with HTML ```````````````````````````````` example gitlab strong bold .

bold

```````````````````````````````` # Appendix Appendix text. GLFM_SPEC_TXT_CONTENTS end let(:glfm_example_status_yml_contents) do <<~GLFM_EXAMPLE_STATUS_YML_CONTENTS --- - 07_01_first_gitlab_specific_section_with_examples_strong_but_with_two_asterisks: skip_update_example_snapshots: false skip_running_snapshot_static_html_tests: false skip_running_snapshot_wysiwyg_html_tests: false skip_running_snapshot_prosemirror_json_tests: false skip_running_conformance_static_tests: false skip_running_conformance_wysiwyg_tests: false - 07_02_first_gitlab_specific_section_with_examples_strong_but_with_html: skip_update_example_snapshots: false skip_running_snapshot_static_html_tests: false skip_running_snapshot_wysiwyg_html_tests: false skip_running_snapshot_prosemirror_json_tests: false skip_running_conformance_static_tests: false skip_running_conformance_wysiwyg_tests: false GLFM_EXAMPLE_STATUS_YML_CONTENTS end before do # 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. # input files allow(File).to receive(:open).with(glfm_spec_txt_path) { glfm_spec_txt_local_io } allow(File).to receive(:open).with(glfm_example_status_yml_path) { glfm_example_status_yml_io } # output files allow(File).to receive(:open).with(es_examples_index_yml_path, 'w') { es_examples_index_yml_io } allow(File).to receive(:open).with(es_html_yml_path, 'w') { es_html_yml_io } allow(File).to receive(:open).with(es_prosemirror_json_yml_path, 'w') { es_prosemirror_json_yml_io } # output files which are also input files allow(File).to receive(:open).with(es_markdown_yml_path, 'w') { es_markdown_yml_io } allow(File).to receive(:open).with(es_markdown_yml_path) { es_markdown_yml_io } # Allow normal opening of Tempfile files created during script execution. tempfile_basenames = [ described_class::MARKDOWN_TEMPFILE_BASENAME[0], described_class::STATIC_HTML_TEMPFILE_BASENAME[0], described_class::WYSIWYG_HTML_AND_JSON_TEMPFILE_BASENAME[0] ].join('|') # NOTE: This approach with a single regex seems to be the only way this can work. If you # attempt to have multiple `allow...and_call_original` with `any_args`, the mocked # parameter matching will fail to match the second one. tempfiles_regex = /(#{tempfile_basenames})/ allow(File).to receive(:open).with(tempfiles_regex, any_args).and_call_original # Prevent console output when running tests allow(subject).to receive(:output) end describe 'writing examples_index.yml' do let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) } it 'writes the correct content' do subject.process(skip_static_and_wysiwyg: true) expected = <<~ES_EXAMPLES_INDEX_YML_CONTENTS --- 02_01__inlines__strong__01: spec_txt_example_position: 1 source_specification: commonmark 02_01__inlines__strong__02: spec_txt_example_position: 2 source_specification: github 02_02__inlines__strikethrough_extension__01: spec_txt_example_position: 3 source_specification: github 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: spec_txt_example_position: 4 source_specification: gitlab 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__01: spec_txt_example_position: 5 source_specification: gitlab ES_EXAMPLES_INDEX_YML_CONTENTS expect(es_examples_index_yml_contents).to eq(expected) end end describe 'writing markdown.yml' do let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) } it 'writes the correct content' do subject.process(skip_static_and_wysiwyg: true) expected = <<~ES_MARKDOWN_YML_CONTENTS --- 02_01__inlines__strong__01: | __bold__ 02_01__inlines__strong__02: | __bold with more text__ 02_02__inlines__strikethrough_extension__01: | ~~Hi~~ Hello, world! 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: | **bold** 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__01: | bold ES_MARKDOWN_YML_CONTENTS expect(es_markdown_yml_contents).to eq(expected) end end describe 'writing html.yml and prosemirror_json.yml' do let(:es_html_yml_contents) { reread_io(es_html_yml_io) } let(:es_prosemirror_json_yml_contents) { reread_io(es_prosemirror_json_yml_io) } let(:glfm_example_status_yml_contents) do <<~GLFM_EXAMPLE_STATUS_YML_CONTENTS --- - 02_01_gitlab_specific_section_with_examples_strong_but_with_two_asterisks: skip_update_example_snapshots: false skip_running_snapshot_static_html_tests: false skip_running_snapshot_wysiwyg_html_tests: false skip_running_snapshot_prosemirror_json_tests: false skip_running_conformance_static_tests: false skip_running_conformance_wysiwyg_tests: false GLFM_EXAMPLE_STATUS_YML_CONTENTS end let(:glfm_spec_txt_contents) do <<~GLFM_SPEC_TXT_CONTENTS --- title: GitLab Flavored Markdown Spec ... # Introduction # GitLab-Specific Section with Examples ## Strong but with two asterisks ```````````````````````````````` example gitlab strong **bold** .

bold

```````````````````````````````` # Appendix Appendix text. GLFM_SPEC_TXT_CONTENTS end before do # NOTE: This is a necessary to avoid an `error Couldn't find an integrity file` error # when invoking `yarn jest ...` on CI from within an RSpec job. It could be solved by # adding `.yarn-install` to be included in the RSpec CI job, but that would be a performance # hit to all RSpec jobs. We could also make a dedicate job just for this spec. However, # since this is just a single script, those options may not be justified. described_class.new.run_external_cmd('yarn install') if ENV['CI'] end # NOTE: Both `html.yml` and `prosemirror_json.yml` generation are tested in a single example, to # avoid slower tests, because generating the static HTML is slow due to the need to invoke # the rails environment. We could have separate sections, but this would require an extra flag # to the `process` method to independently skip static vs. WYSIWYG, which is not worth the effort. it 'writes the correct content' do subject.process expected_html = <<~ES_HTML_YML_CONTENTS --- 02_01__gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: canonical: |

bold

static: |-

bold

wysiwyg: |-

bold

ES_HTML_YML_CONTENTS expected_prosemirror_json = <<~ES_PROSEMIRROR_JSON_YML_CONTENTS --- 02_01__gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: |- { "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "text", "marks": [ { "type": "bold" } ], "text": "bold" } ] } ] } ES_PROSEMIRROR_JSON_YML_CONTENTS expect(es_html_yml_contents).to eq(expected_html) expect(es_prosemirror_json_yml_contents).to eq(expected_prosemirror_json) end end def reread_io(io) # Reset the io StringIO to the beginning position of the buffer io.seek(0) io.read end end