diff options
Diffstat (limited to 'spec/scripts/lib')
-rw-r--r-- | spec/scripts/lib/glfm/parse_examples_spec.rb | 331 | ||||
-rw-r--r-- | spec/scripts/lib/glfm/shared_spec.rb | 18 | ||||
-rw-r--r-- | spec/scripts/lib/glfm/update_example_snapshots_spec.rb | 500 | ||||
-rw-r--r-- | spec/scripts/lib/glfm/update_specification_spec.rb | 21 |
4 files changed, 757 insertions, 113 deletions
diff --git a/spec/scripts/lib/glfm/parse_examples_spec.rb b/spec/scripts/lib/glfm/parse_examples_spec.rb new file mode 100644 index 00000000000..a1ee6b3f440 --- /dev/null +++ b/spec/scripts/lib/glfm/parse_examples_spec.rb @@ -0,0 +1,331 @@ +# frozen_string_literal: true +require 'fast_spec_helper' +require_relative '../../../../scripts/lib/glfm/parse_examples' + +RSpec.describe Glfm::ParseExamples, '#parse_examples' do + subject do + described_module = described_class + Class.new { include described_module }.new + end + + let(:spec_txt_contents) do + <<~MARKDOWN + --- + title: Spec + ... + + # Introduction + + intro + + # 1.0.0 H1 + + ## 1.1.0 H2 + + no extension + + ```````````````````````````````` example + example 1 md + . + html + ```````````````````````````````` + + one extension + + ```````````````````````````````` example extension_1.1.0-1 + example 2 md + . + html + ```````````````````````````````` + + ### 1.1.1 H3 with no examples + + text + + ### 1.1.2 Consecutive H3 with example + + text + + ```````````````````````````````` example disabled + example 3 md + . + html + ```````````````````````````````` + + ## 1.2.0 H2 with all disabled examples + + + ```````````````````````````````` example disabled + example 4 md + . + html + ```````````````````````````````` + + ## 1.2.0 New H2 + + + ```````````````````````````````` example extension_1.2.0-1 + example 5 md + . + html + ```````````````````````````````` + + # 2.0.0 New H1 + + ## 2.1.0 H2 + + ```````````````````````````````` example gitlab + example 6 md + . + html + ```````````````````````````````` + + ## 2.2.0 H2 which contains an H3 + + No example here, just text + + ### 2.2.1 H3 + + The CommonMark and GHFM specifications don't have any examples inside an H3, but it is + supported for the GLFM specification. + + ```````````````````````````````` example extension_2.2.1-1 + example 7 md + . + html + ```````````````````````````````` + + # 3.0.0 New H1 + + ## 3.1.0 H2 + + ```````````````````````````````` example + example 8 md + . + html + ```````````````````````````````` + + ### 3.1.1 H3 + + ```````````````````````````````` example + example 9 md + . + html + ```````````````````````````````` + + ### 3.1.1 Consecutive H3 + + ```````````````````````````````` example + example 10 md + . + html + ```````````````````````````````` + + ## 3.2.0 Another H2 + + ```````````````````````````````` example + example 11 md + . + html + ```````````````````````````````` + + <!-- END TESTS --> + + # Appendix + + Appendix text. + MARKDOWN + end + + let(:spec_txt_lines) { spec_txt_contents.split("\n") } + + describe "parsing" do + it 'correctly parses' do + examples = subject.parse_examples(spec_txt_lines) + + expected = + [ + { + disabled: false, + end_line: 19, + example: 1, + extensions: [], + headers: [ + '1.0.0 H1', + '1.1.0 H2' + ], + html: 'html', + markdown: 'example 1 md', + section: '1.1.0 H2', + start_line: 15 + }, + { + disabled: false, + end_line: 27, + example: 2, + extensions: %w[extension_1.1.0-1], + headers: [ + '1.0.0 H1', + '1.1.0 H2' + ], + html: 'html', + markdown: 'example 2 md', + section: '1.1.0 H2', + start_line: 23 + }, + { + disabled: true, + end_line: 41, + example: 3, + extensions: %w[disabled], + headers: [ + '1.0.0 H1', + '1.1.0 H2', + '1.1.2 Consecutive H3 with example' + ], + html: 'html', + markdown: 'example 3 md', + section: '1.1.2 Consecutive H3 with example', + start_line: 37 + }, + { + disabled: true, + end_line: 50, + example: 4, + extensions: %w[disabled], + headers: [ + '1.0.0 H1', + '1.2.0 H2 with all disabled examples' + ], + html: 'html', + markdown: 'example 4 md', + section: '1.2.0 H2 with all disabled examples', + start_line: 46 + }, + { + disabled: false, + end_line: 59, + example: 5, + extensions: %w[extension_1.2.0-1], + headers: [ + '1.0.0 H1', + '1.2.0 New H2' + ], + html: 'html', + markdown: 'example 5 md', + section: '1.2.0 New H2', + start_line: 55 + }, + { + disabled: false, + end_line: 69, + example: 6, + extensions: %w[gitlab], + headers: [ + '2.0.0 New H1', + '2.1.0 H2' + ], + html: 'html', + markdown: 'example 6 md', + section: '2.1.0 H2', + start_line: 65 + }, + { + disabled: false, + end_line: 84, + example: 7, + extensions: %w[extension_2.2.1-1], + headers: [ + '2.0.0 New H1', + '2.2.0 H2 which contains an H3', + '2.2.1 H3' + ], + html: 'html', + markdown: 'example 7 md', + section: '2.2.1 H3', + start_line: 80 + }, + { + disabled: false, + end_line: 94, + example: 8, + extensions: [], + headers: [ + '3.0.0 New H1', + '3.1.0 H2' + ], + html: 'html', + markdown: 'example 8 md', + section: '3.1.0 H2', + start_line: 90 + }, + { + disabled: false, + end_line: 102, + example: 9, + extensions: [], + headers: [ + '3.0.0 New H1', + '3.1.0 H2', + '3.1.1 H3' + ], + html: 'html', + markdown: 'example 9 md', + section: '3.1.1 H3', + start_line: 98 + }, + { + disabled: false, + end_line: 110, + example: 10, + extensions: [], + headers: [ + '3.0.0 New H1', + '3.1.0 H2', + '3.1.1 Consecutive H3' + ], + html: 'html', + markdown: 'example 10 md', + section: '3.1.1 Consecutive H3', + start_line: 106 + }, + { + disabled: false, + end_line: 118, + example: 11, + extensions: [], + headers: [ + '3.0.0 New H1', + '3.2.0 Another H2' + ], + html: 'html', + markdown: 'example 11 md', + section: '3.2.0 Another H2', + start_line: 114 + } + ] + + expect(examples).to eq(expected) + end + end + + describe "with incorrect header nesting" do + let(:spec_txt_contents) do + <<~MARKDOWN + --- + title: Spec + ... + + # H1 + + ### H3 + + MARKDOWN + end + + it "raises if H3 is nested directly in H1" do + expect { subject.parse_examples(spec_txt_lines) } + .to raise_error(/The H3 'H3' may not be nested directly within the H1 'H1'/) + end + end +end diff --git a/spec/scripts/lib/glfm/shared_spec.rb b/spec/scripts/lib/glfm/shared_spec.rb index f6792b93718..3ce9d44ba3d 100644 --- a/spec/scripts/lib/glfm/shared_spec.rb +++ b/spec/scripts/lib/glfm/shared_spec.rb @@ -9,6 +9,16 @@ RSpec.describe Glfm::Shared do end.new end + describe '#write_file' do + it 'works' do + filename = Dir::Tmpname.create('basename') do |path| + instance.write_file(path, 'test') + end + + expect(File.read(filename)).to eq 'test' + end + end + describe '#run_external_cmd' do it 'works' do expect(instance.run_external_cmd('echo "hello"')).to eq("hello\n") @@ -24,6 +34,14 @@ RSpec.describe Glfm::Shared do end end + describe '#dump_yaml_with_formatting' do + it 'works' do + hash = { a: 'b' } + yaml = instance.dump_yaml_with_formatting(hash, literal_scalars: true) + expect(yaml).to eq("---\na: |-\n b\n") + end + end + describe '#output' do # NOTE: The #output method is normally always mocked, to prevent output while the specs are # running. However, in order to provide code coverage for the method, we have to invoke diff --git a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb index fe815aa6f1e..f96936c0a6f 100644 --- a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb +++ b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb @@ -35,6 +35,8 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do 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) } + let(:glfm_example_metadata_yml_path) { described_class::GLFM_EXAMPLE_METADATA_YML_PATH } + let(:glfm_example_metadata_yml_io) { StringIO.new(glfm_example_metadata_yml_contents) } # Example Snapshot (ES) output files let(:es_examples_index_yml_path) { described_class::ES_EXAMPLES_INDEX_YML_PATH } @@ -52,7 +54,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do let(:static_html_tempfile_path) { Tempfile.new.path } let(:glfm_spec_txt_contents) do - <<~GLFM_SPEC_TXT_CONTENTS + <<~MARKDOWN --- title: GitLab Flavored Markdown Spec ... @@ -128,12 +130,25 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do ## Strong but with two asterisks - ```````````````````````````````` example gitlab strong + ```````````````````````````````` example gitlab **bold** . <p><strong>bold</strong></p> ```````````````````````````````` + ## H2 which contains an H3 + + ### Example in an H3 + + The CommonMark and GHFM specifications don't have any examples inside an H3, but it is + supported for the GLFM specification. + + ```````````````````````````````` example gitlab + Example in an H3 + . + <p>Example in an H3</p> + ```````````````````````````````` + # Second GitLab-Specific Section with Examples ## Strong but with HTML @@ -142,7 +157,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do `source_specification` will be `gitlab`. - ```````````````````````````````` example gitlab strong + ```````````````````````````````` example gitlab <strong> bold </strong> @@ -156,7 +171,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do ## Strong but skipped - ```````````````````````````````` example gitlab strong + ```````````````````````````````` example gitlab **this example will be skipped** . <p><strong>this example will be skipped</strong></p> @@ -164,80 +179,151 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do ## Strong but manually modified and skipped - ```````````````````````````````` example gitlab strong + ```````````````````````````````` example gitlab **This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved** . <p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p> ```````````````````````````````` + # API Request Overrides + + This section contains examples which verify that all of the fixture models which are set up + in `render_static_html.rb` are correctly configured. They exercise various `preview_markdown` + endpoints via `glfm_example_metadata.yml`. + + ## Group Upload Link + + `preview_markdown` exercising `groups` API endpoint and `UploadLinkFilter`: + + ```````````````````````````````` example gitlab + [groups-test-file](/uploads/groups-test-file) + . + <p><a href="groups-test-file">groups-test-file</a></p> + ```````````````````````````````` + + ## Project Repo Link + + `preview_markdown` exercising `projects` API endpoint and `RepositoryLinkFilter`: + + ```````````````````````````````` example gitlab + [projects-test-file](projects-test-file) + . + <p><a href="projects-test-file">projects-test-file</a></p> + ```````````````````````````````` + + ## Project Snippet Ref + + `preview_markdown` exercising `projects` API endpoint and `SnippetReferenceFilter`: + + ```````````````````````````````` example gitlab + This project snippet ID reference IS filtered: $88888 + . + <p>This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888">$88888</a> + ```````````````````````````````` + + ## Personal Snippet Ref + + `preview_markdown` exercising personal (non-project) `snippets` API endpoint. This is + only used by the comment field on personal snippets. It has no unique custom markdown + extension behavior, and specifically does not render snippet references via + `SnippetReferenceFilter`, even if the ID is valid. + + ```````````````````````````````` example gitlab + This personal snippet ID reference is NOT filtered: $99999 + . + <p>This personal snippet ID reference is NOT filtered: $99999</p> + ```````````````````````````````` + + ## Project Wiki Link + + `preview_markdown` exercising project `wikis` API endpoint and `WikiLinkFilter`: + + ```````````````````````````````` example gitlab + [project-wikis-test-file](project-wikis-test-file) + . + <p><a href="project-wikis-test-file">project-wikis-test-file</a></p> + ```````````````````````````````` + <!-- END TESTS --> # Appendix Appendix text. - GLFM_SPEC_TXT_CONTENTS + MARKDOWN end let(:glfm_example_status_yml_contents) do - # language=YAML - <<~GLFM_EXAMPLE_STATUS_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__001: + 02_01_00__inlines__strong__001: # The skip_update_example_snapshots key is present, but false, so this example is not skipped skip_update_example_snapshots: false - 02_01__inlines__strong__002: + 02_01_00__inlines__strong__002: # It is OK to have an empty (nil) value for an example statuses entry, it means they will all be false. - 05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: + 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: # Always skip this example skip_update_example_snapshots: 'skipping this example because it is very bad' - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: # Always skip this example, but preserve the existing manual modifications skip_update_example_snapshots: 'skipping this example because we have manually modified it' - GLFM_EXAMPLE_STATUS_YML_CONTENTS + YAML + end + + let(:glfm_example_metadata_yml_contents) do + <<~YAML + --- + 06_01_00__api_request_overrides__group_upload_link__001: + api_request_override_path: /groups/glfm_group/preview_markdown + 06_02_00__api_request_overrides__project_repo_link__001: + api_request_override_path: /glfm_group/glfm_project/preview_markdown + 06_03_00__api_request_overrides__project_snippet_ref__001: + api_request_override_path: /glfm_group/glfm_project/preview_markdown + 06_04_00__api_request_overrides__personal_snippet_ref__001: + api_request_override_path: /-/snippets/preview_markdown + 06_05_00__api_request_overrides__project_wiki_link__001: + api_request_override_path: /glfm_group/glfm_project/-/wikis/new_page/preview_markdown + YAML end let(:es_html_yml_io_existing_contents) do - # language=YAML - <<~ES_HTML_YML_IO_EXISTING_CONTENTS + <<~YAML --- - 00_00__obsolete_entry_to_be_deleted__001: + 00_00_00__obsolete_entry_to_be_deleted__001: canonical: | - This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted. + This entry is no longer exists in the spec.txt, so it will be deleted. static: |- - This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted. + This entry is no longer exists in the spec.txt, so it will be deleted. wysiwyg: |- - This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted. - 02_01__inlines__strong__001: + This entry is no longer exists in the spec.txt, so it will be deleted. + 02_01_00__inlines__strong__001: canonical: | This entry is existing, but not skipped, so it will be overwritten. static: |- This entry is existing, but not skipped, so it will be overwritten. wysiwyg: |- This entry is existing, but not skipped, so it will be overwritten. - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: canonical: | <p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p> static: |- <p>This is the manually modified static HTML which will be preserved</p> wysiwyg: |- <p>This is the manually modified WYSIWYG HTML which will be preserved</p> - ES_HTML_YML_IO_EXISTING_CONTENTS + YAML end let(:es_prosemirror_json_yml_io_existing_contents) do - # language=YAML - <<~ES_PROSEMIRROR_JSON_YML_IO_EXISTING_CONTENTS + <<~YAML --- - 00_00__obsolete_entry_to_be_deleted__001: + 00_00_00__obsolete_entry_to_be_deleted__001: |- { "obsolete": "This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted." } - 02_01__inlines__strong__001: |- + 02_01_00__inlines__strong__001: |- { "existing": "This entry is existing, but not skipped, so it will be overwritten." } - # 02_01__inlines__strong__002: is omitted from the existing file and skipped, to test that scenario. - 02_03__inlines__strikethrough_extension__001: |- + 02_03_00__inlines__strikethrough_extension__001: |- { "type": "doc", "content": [ @@ -252,15 +338,15 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do } ] } - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |- + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |- { "existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy" } - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |- + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |- { "existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy" } - ES_PROSEMIRROR_JSON_YML_IO_EXISTING_CONTENTS + YAML end before do @@ -271,6 +357,9 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do # 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 } + allow(File).to receive(:open).with(glfm_example_metadata_yml_path) do + glfm_example_metadata_yml_io + end # output files allow(File).to receive(:open).with(es_examples_index_yml_path, 'w') { es_examples_index_yml_io } @@ -286,6 +375,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do # Allow normal opening of Tempfile files created during script execution. tempfile_basenames = [ described_class::MARKDOWN_TEMPFILE_BASENAME[0], + described_class::METADATA_TEMPFILE_BASENAME[0], described_class::STATIC_HTML_TEMPFILE_BASENAME[0], described_class::WYSIWYG_HTML_AND_JSON_TEMPFILE_BASENAME[0] ].join('|') @@ -299,40 +389,41 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do allow(subject).to receive(:output) end - describe 'when skip_update_example_snapshots is truthy' do - let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) } - let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) } - let(:expected_unskipped_example) do - /05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001/ - end - - it 'still writes the example to examples_index.yml' do - subject.process(skip_static_and_wysiwyg: true) + describe 'glfm_example_status.yml' do + describe 'when skip_update_example_snapshots entry is truthy' do + let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) } + let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) } + let(:expected_unskipped_example) do + /05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001/ + end - expect(es_examples_index_yml_contents).to match(expected_unskipped_example) - end + it 'still writes the example to examples_index.yml' do + subject.process(skip_static_and_wysiwyg: true) - it 'still writes the example to markdown.yml' do - subject.process(skip_static_and_wysiwyg: true) + expect(es_examples_index_yml_contents).to match(expected_unskipped_example) + end - expect(es_markdown_yml_contents).to match(expected_unskipped_example) - end + it 'still writes the example to markdown.yml' do + subject.process(skip_static_and_wysiwyg: true) - describe 'when any other skip_update_example_* is also truthy' do - let(:glfm_example_status_yml_contents) do - # language=YAML - <<~GLFM_EXAMPLE_STATUS_YML_CONTENTS - --- - 02_01__inlines__strong__001: - skip_update_example_snapshots: 'if the skip_update_example_snapshots key is truthy...' - skip_update_example_snapshot_html_static: '...then no other skip_update_example_* keys can be truthy' - GLFM_EXAMPLE_STATUS_YML_CONTENTS + expect(es_markdown_yml_contents).to match(expected_unskipped_example) end - it 'raises an error' do - expected_msg = "Error: '02_01__inlines__strong__001' must not have any 'skip_update_example_snapshot_*' " \ + describe 'when any other skip_update_example_snapshot_* is also truthy' do + let(:glfm_example_status_yml_contents) do + <<~YAML + --- + 02_01_00__inlines__strong__001: + skip_update_example_snapshots: 'if the skip_update_example_snapshots key is truthy...' + skip_update_example_snapshot_html_static: '...then no other skip_update_example_* keys can be truthy' + YAML + end + + it 'raises an error' do + expected_msg = "Error: '02_01_00__inlines__strong__001' must not have any 'skip_update_example_snapshot_*' " \ "values specified if 'skip_update_example_snapshots' is truthy" - expect { subject.process }.to raise_error(/#{Regexp.escape(expected_msg)}/) + expect { subject.process }.to raise_error(/#{Regexp.escape(expected_msg)}/) + end end end end @@ -340,31 +431,48 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do describe 'writing examples_index.yml' do let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) } let(:expected_examples_index_yml_contents) do - # language=YAML - <<~ES_EXAMPLES_INDEX_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__001: + 02_01_00__inlines__strong__001: spec_txt_example_position: 1 source_specification: commonmark - 02_01__inlines__strong__002: + 02_01_00__inlines__strong__002: spec_txt_example_position: 2 source_specification: github - 02_03__inlines__strikethrough_extension__001: + 02_03_00__inlines__strikethrough_extension__001: spec_txt_example_position: 4 source_specification: github - 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: + 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: spec_txt_example_position: 5 source_specification: gitlab - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: + 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: spec_txt_example_position: 6 source_specification: gitlab - 05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: spec_txt_example_position: 7 source_specification: gitlab - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: spec_txt_example_position: 8 source_specification: gitlab - ES_EXAMPLES_INDEX_YML_CONTENTS + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + spec_txt_example_position: 9 + source_specification: gitlab + 06_01_00__api_request_overrides__group_upload_link__001: + spec_txt_example_position: 10 + source_specification: gitlab + 06_02_00__api_request_overrides__project_repo_link__001: + spec_txt_example_position: 11 + source_specification: gitlab + 06_03_00__api_request_overrides__project_snippet_ref__001: + spec_txt_example_position: 12 + source_specification: gitlab + 06_04_00__api_request_overrides__personal_snippet_ref__001: + spec_txt_example_position: 13 + source_specification: gitlab + 06_05_00__api_request_overrides__project_wiki_link__001: + spec_txt_example_position: 14 + source_specification: gitlab + YAML end it 'writes the correct content' do @@ -377,26 +485,37 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do describe 'writing markdown.yml' do let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) } let(:expected_markdown_yml_contents) do - # language=YAML - <<~ES_MARKDOWN_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__001: | + 02_01_00__inlines__strong__001: | __bold__ - 02_01__inlines__strong__002: | + 02_01_00__inlines__strong__002: | __bold with more text__ - 02_03__inlines__strikethrough_extension__001: | + 02_03_00__inlines__strikethrough_extension__001: | ~~Hi~~ Hello, world! - 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: | + 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: | **bold** - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: | + 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: | + Example in an H3 + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: | <strong> bold </strong> - 05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: | + 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: | **this example will be skipped** - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: | + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: | **This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved** - ES_MARKDOWN_YML_CONTENTS + 06_01_00__api_request_overrides__group_upload_link__001: | + [groups-test-file](/uploads/groups-test-file) + 06_02_00__api_request_overrides__project_repo_link__001: | + [projects-test-file](projects-test-file) + 06_03_00__api_request_overrides__project_snippet_ref__001: | + This project snippet ID reference IS filtered: $88888 + 06_04_00__api_request_overrides__personal_snippet_ref__001: | + This personal snippet ID reference is NOT filtered: $99999 + 06_05_00__api_request_overrides__project_wiki_link__001: | + [project-wikis-test-file](project-wikis-test-file) + YAML end it 'writes the correct content' do @@ -406,6 +525,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do end end + # rubocop:disable RSpec/MultipleMemoizedHelpers 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) } @@ -413,54 +533,64 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do # NOTE: This example_status.yml is crafted in conjunction with expected_html_yml_contents # to test the behavior of the `skip_update_*` flags let(:glfm_example_status_yml_contents) do - # language=YAML - <<~GLFM_EXAMPLE_STATUS_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__002: + 02_01_00__inlines__strong__002: + # NOTE: 02_01_00__inlines__strong__002: is omitted from the existing prosemirror_json.yml file, and is also + # skipped here, to show that an example does not need to exist in order to be skipped. + # TODO: This should be changed to raise an error instead, to enforce that there cannot be orphaned + # entries in glfm_example_status.yml. This task is captured in + # https://gitlab.com/gitlab-org/gitlab/-/issues/361241#other-cleanup-tasks skip_update_example_snapshot_prosemirror_json: "skipping because JSON isn't cool enough" - 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: + 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: skip_update_example_snapshot_html_static: "skipping because there's too much static" - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: skip_update_example_snapshot_html_wysiwyg: 'skipping because what you see is NOT what you get' skip_update_example_snapshot_prosemirror_json: "skipping because JSON still isn't cool enough" - 05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: + 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: skip_update_example_snapshots: 'skipping this example because it is very bad' - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: skip_update_example_snapshots: 'skipping this example because we have manually modified it' - GLFM_EXAMPLE_STATUS_YML_CONTENTS + YAML end let(:expected_html_yml_contents) do - # language=YAML - <<~ES_HTML_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__001: + 02_01_00__inlines__strong__001: canonical: | <p><strong>bold</strong></p> static: |- <p data-sourcepos="1:1-1:8" dir="auto"><strong>bold</strong></p> wysiwyg: |- <p><strong>bold</strong></p> - 02_01__inlines__strong__002: + 02_01_00__inlines__strong__002: canonical: | <p><strong>bold with more text</strong></p> static: |- <p data-sourcepos="1:1-1:23" dir="auto"><strong>bold with more text</strong></p> wysiwyg: |- <p><strong>bold with more text</strong></p> - 02_03__inlines__strikethrough_extension__001: + 02_03_00__inlines__strikethrough_extension__001: canonical: | <p><del>Hi</del> Hello, world!</p> static: |- <p data-sourcepos="1:1-1:20" dir="auto"><del>Hi</del> Hello, world!</p> wysiwyg: |- <p><s>Hi</s> Hello, world!</p> - 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: + 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: canonical: | <p><strong>bold</strong></p> wysiwyg: |- <p><strong>bold</strong></p> - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: + 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: + canonical: | + <p>Example in an H3</p> + static: |- + <p data-sourcepos="1:1-1:16" dir="auto">Example in an H3</p> + wysiwyg: |- + <p>Example in an H3</p> + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: canonical: | <p><strong> bold @@ -469,21 +599,55 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do <strong> bold </strong> - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: canonical: | <p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p> static: |- <p>This is the manually modified static HTML which will be preserved</p> wysiwyg: |- <p>This is the manually modified WYSIWYG HTML which will be preserved</p> - ES_HTML_YML_CONTENTS + 06_01_00__api_request_overrides__group_upload_link__001: + canonical: | + <p><a href="groups-test-file">groups-test-file</a></p> + static: |- + <p data-sourcepos="1:1-1:45" dir="auto"><a href="/groups/glfm_group/-/uploads/groups-test-file" data-canonical-src="/uploads/groups-test-file" data-link="true" class="gfm">groups-test-file</a></p> + wysiwyg: |- + <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uploads/groups-test-file">groups-test-file</a></p> + 06_02_00__api_request_overrides__project_repo_link__001: + canonical: | + <p><a href="projects-test-file">projects-test-file</a></p> + static: |- + <p data-sourcepos="1:1-1:40" dir="auto"><a href="/glfm_group/glfm_project/-/blob/master/projects-test-file">projects-test-file</a></p> + wysiwyg: |- + <p><a target="_blank" rel="noopener noreferrer nofollow" href="projects-test-file">projects-test-file</a></p> + 06_03_00__api_request_overrides__project_snippet_ref__001: + canonical: | + <p>This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888">$88888</a> + static: |- + <p data-sourcepos="1:1-1:53" dir="auto">This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888" data-reference-type="snippet" data-original="$88888" data-link="false" data-link-reference="false" data-project="77777" data-snippet="88888" data-container="body" data-placement="top" title="glfm_project_snippet" class="gfm gfm-snippet has-tooltip">$88888</a></p> + wysiwyg: |- + <p>This project snippet ID reference IS filtered: $88888</p> + 06_04_00__api_request_overrides__personal_snippet_ref__001: + canonical: | + <p>This personal snippet ID reference is NOT filtered: $99999</p> + static: |- + <p data-sourcepos="1:1-1:58" dir="auto">This personal snippet ID reference is NOT filtered: $99999</p> + wysiwyg: |- + <p>This personal snippet ID reference is NOT filtered: $99999</p> + 06_05_00__api_request_overrides__project_wiki_link__001: + canonical: | + <p><a href="project-wikis-test-file">project-wikis-test-file</a></p> + static: |- + <p data-sourcepos="1:1-1:50" dir="auto"><a href="/glfm_group/glfm_project/-/wikis/project-wikis-test-file" data-canonical-src="project-wikis-test-file">project-wikis-test-file</a></p> + wysiwyg: |- + <p><a target="_blank" rel="noopener noreferrer nofollow" href="project-wikis-test-file">project-wikis-test-file</a></p> + YAML end let(:expected_prosemirror_json_contents) do - # language=YAML - <<~ES_PROSEMIRROR_JSON_YML_CONTENTS + <<~YAML --- - 02_01__inlines__strong__001: |- + 02_01_00__inlines__strong__001: |- { "type": "doc", "content": [ @@ -503,7 +667,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do } ] } - 02_03__inlines__strikethrough_extension__001: |- + 02_03_00__inlines__strikethrough_extension__001: |- { "type": "doc", "content": [ @@ -527,7 +691,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do } ] } - 03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |- + 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |- { "type": "doc", "content": [ @@ -547,15 +711,144 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do } ] } - 04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |- + 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Example in an H3" + } + ] + } + ] + } + 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |- { "existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy" } - 05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |- + 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |- { "existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy" } - ES_PROSEMIRROR_JSON_YML_CONTENTS + 06_01_00__api_request_overrides__group_upload_link__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "marks": [ + { + "type": "link", + "attrs": { + "href": "/uploads/groups-test-file", + "target": "_blank", + "class": null, + "title": null, + "canonicalSrc": "/uploads/groups-test-file", + "isReference": false + } + } + ], + "text": "groups-test-file" + } + ] + } + ] + } + 06_02_00__api_request_overrides__project_repo_link__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "marks": [ + { + "type": "link", + "attrs": { + "href": "projects-test-file", + "target": "_blank", + "class": null, + "title": null, + "canonicalSrc": "projects-test-file", + "isReference": false + } + } + ], + "text": "projects-test-file" + } + ] + } + ] + } + 06_03_00__api_request_overrides__project_snippet_ref__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "This project snippet ID reference IS filtered: $88888" + } + ] + } + ] + } + 06_04_00__api_request_overrides__personal_snippet_ref__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "This personal snippet ID reference is NOT filtered: $99999" + } + ] + } + ] + } + 06_05_00__api_request_overrides__project_wiki_link__001: |- + { + "type": "doc", + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "marks": [ + { + "type": "link", + "attrs": { + "href": "project-wikis-test-file", + "target": "_blank", + "class": null, + "title": null, + "canonicalSrc": "project-wikis-test-file", + "isReference": false + } + } + ], + "text": "project-wikis-test-file" + } + ] + } + ] + } + YAML end before do @@ -581,6 +874,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do expect(es_prosemirror_json_yml_contents).to eq(expected_prosemirror_json_contents) end end + # rubocop:enable RSpec/MultipleMemoizedHelpers def reread_io(io) # Reset the io StringIO to the beginning position of the buffer diff --git a/spec/scripts/lib/glfm/update_specification_spec.rb b/spec/scripts/lib/glfm/update_specification_spec.rb index e8d34b13efa..9fb671e0016 100644 --- a/spec/scripts/lib/glfm/update_specification_spec.rb +++ b/spec/scripts/lib/glfm/update_specification_spec.rb @@ -18,7 +18,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do let(:glfm_spec_txt_io) { StringIO.new } let(:ghfm_spec_txt_contents) do - <<~GHFM_SPEC_TXT_CONTENTS + <<~MARKDOWN --- title: GitHub Flavored Markdown Spec version: 0.29 @@ -49,25 +49,26 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do # Appendix Appendix text. - GHFM_SPEC_TXT_CONTENTS + MARKDOWN end let(:glfm_intro_txt_contents) do - <<~GLFM_INTRO_TXT_CONTENTS + # language=Markdown + <<~MARKDOWN # Introduction ## What is GitLab Flavored Markdown? Intro text about GitLab Flavored Markdown. - GLFM_INTRO_TXT_CONTENTS + MARKDOWN end let(:glfm_examples_txt_contents) do - <<~GLFM_EXAMPLES_TXT_CONTENTS + <<~MARKDOWN # GitLab-Specific Section with Examples Some examples. - GLFM_EXAMPLES_TXT_CONTENTS + MARKDOWN end before do @@ -118,12 +119,12 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do context 'with error handling' do context 'with a version mismatch' do let(:ghfm_spec_txt_contents) do - <<~GHFM_SPEC_TXT_CONTENTS + <<~MARKDOWN --- title: GitHub Flavored Markdown Spec version: 0.30 ... - GHFM_SPEC_TXT_CONTENTS + MARKDOWN end it 'raises an error' do @@ -173,7 +174,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do end it 'inserts the GitLab examples sections before the appendix section' do - expected = <<~GHFM_SPEC_TXT_CONTENTS + expected = <<~MARKDOWN End of last GitHub examples section. # GitLab-Specific Section with Examples @@ -183,7 +184,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do <!-- END TESTS --> # Appendix - GHFM_SPEC_TXT_CONTENTS + MARKDOWN expect(glfm_contents).to match(/#{Regexp.escape(expected)}/m) end end |