diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-20 03:14:01 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-20 03:14:01 +0300 |
commit | d6085b68c5dcc2bd4dc884d2fa6b75831f85c883 (patch) | |
tree | 8b122dde681ec2acdde572b0d20979516c4abfa9 /spec/frontend | |
parent | 652d8b33ee36e9977c03d1ed7da12ddc03292cf4 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r-- | spec/frontend/content_editor/markdown_processing_examples.js | 27 | ||||
-rw-r--r-- | spec/frontend/content_editor/markdown_processing_spec.js | 27 | ||||
-rw-r--r-- | spec/frontend/content_editor/markdown_processing_spec_helper.js | 75 | ||||
-rw-r--r-- | spec/frontend/fixtures/api_markdown.rb | 65 | ||||
-rw-r--r-- | spec/frontend/fixtures/api_markdown.yml | 289 |
5 files changed, 88 insertions, 395 deletions
diff --git a/spec/frontend/content_editor/markdown_processing_examples.js b/spec/frontend/content_editor/markdown_processing_examples.js deleted file mode 100644 index da895970289..00000000000 --- a/spec/frontend/content_editor/markdown_processing_examples.js +++ /dev/null @@ -1,27 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import jsYaml from 'js-yaml'; -// eslint-disable-next-line import/no-deprecated -import { getJSONFixture } from 'helpers/fixtures'; - -export const loadMarkdownApiResult = (testName) => { - const fixturePathPrefix = `api/markdown/${testName}.json`; - - // eslint-disable-next-line import/no-deprecated - const fixture = getJSONFixture(fixturePathPrefix); - return fixture.body || fixture.html; -}; - -export const loadMarkdownApiExamples = () => { - const apiMarkdownYamlPath = path.join(__dirname, '..', 'fixtures', 'api_markdown.yml'); - const apiMarkdownYamlText = fs.readFileSync(apiMarkdownYamlPath); - const apiMarkdownExampleObjects = jsYaml.safeLoad(apiMarkdownYamlText); - - return apiMarkdownExampleObjects.map(({ name, context, markdown }) => [name, context, markdown]); -}; - -export const loadMarkdownApiExample = (testName) => { - return loadMarkdownApiExamples().find(([name, context]) => { - return (context ? `${context}_${name}` : name) === testName; - })[2]; -}; diff --git a/spec/frontend/content_editor/markdown_processing_spec.js b/spec/frontend/content_editor/markdown_processing_spec.js index 71565768558..4bbe5b4bcf4 100644 --- a/spec/frontend/content_editor/markdown_processing_spec.js +++ b/spec/frontend/content_editor/markdown_processing_spec.js @@ -1,20 +1,19 @@ -import { createContentEditor } from '~/content_editor'; -import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples'; +import path from 'path'; +import { createSharedExamples, loadMarkdownApiExamples } from './markdown_processing_spec_helper'; jest.mock('~/emoji'); -describe('markdown processing', () => { +// See spec/fixtures/markdown/markdown_golden_master_examples.yml for documentation on how this spec works. +describe('markdown processing in ContentEditor', () => { // Ensure we generate same markdown that was provided to Markdown API. - it.each(loadMarkdownApiExamples())( - 'correctly handles %s (context: %s)', - async (name, context, markdown) => { - const testName = context ? `${context}_${name}` : name; - const contentEditor = createContentEditor({ - renderMarkdown: () => loadMarkdownApiResult(testName), - }); - await contentEditor.setSerializedContent(markdown); - - expect(contentEditor.getSerializedContent()).toBe(markdown); - }, + const markdownYamlPath = path.join( + __dirname, + '..', + '..', + 'fixtures', + 'markdown', + 'markdown_golden_master_examples.yml', ); + // eslint-disable-next-line jest/valid-describe + describe.each(loadMarkdownApiExamples(markdownYamlPath))('%s', createSharedExamples); }); diff --git a/spec/frontend/content_editor/markdown_processing_spec_helper.js b/spec/frontend/content_editor/markdown_processing_spec_helper.js new file mode 100644 index 00000000000..66eccbe8a4e --- /dev/null +++ b/spec/frontend/content_editor/markdown_processing_spec_helper.js @@ -0,0 +1,75 @@ +import fs from 'fs'; +import jsYaml from 'js-yaml'; +import { memoize } from 'lodash'; +import { createContentEditor } from '~/content_editor'; +import { setTestTimeoutOnce } from 'helpers/timeout'; + +const getFocusedMarkdownExamples = memoize( + () => process.env.FOCUSED_MARKDOWN_EXAMPLES?.split(',') || [], +); + +const includeExample = ({ name }) => { + const focusedMarkdownExamples = getFocusedMarkdownExamples(); + if (!focusedMarkdownExamples.length) { + return true; + } + return focusedMarkdownExamples.includes(name); +}; + +const getPendingReason = (pendingStringOrObject) => { + if (!pendingStringOrObject) { + return null; + } + if (typeof pendingStringOrObject === 'string') { + return pendingStringOrObject; + } + if (pendingStringOrObject.frontend) { + return pendingStringOrObject.frontend; + } + + return null; +}; + +// eslint-disable-next-line jest/no-export +export const loadMarkdownApiExamples = (markdownYamlPath) => { + const apiMarkdownYamlText = fs.readFileSync(markdownYamlPath); + const apiMarkdownExampleObjects = jsYaml.safeLoad(apiMarkdownYamlText); + + return apiMarkdownExampleObjects + .filter(includeExample) + .map(({ name, pending, markdown, html }) => [ + name, + { pendingReason: getPendingReason(pending), markdown, html }, + ]); +}; + +const testSerializesHtmlToMarkdownForElement = async ({ markdown, html }) => { + const contentEditor = createContentEditor({ + // Overwrite renderMarkdown to always return this specific html + renderMarkdown: () => html, + }); + + await contentEditor.setSerializedContent(markdown); + + // This serializes the ContentEditor document, which was based on the HTML, to markdown + const serializedContent = contentEditor.getSerializedContent(); + + // Assert that the markdown we ended up with after sending it through all the ContentEditor + // plumbing matches the original markdown from the YAML. + expect(serializedContent).toBe(markdown); +}; + +// eslint-disable-next-line jest/no-export +export const createSharedExamples = (name, { pendingReason, ...example }) => { + const exampleName = 'correctly serializes HTML to markdown'; + if (pendingReason) { + it.todo(`${exampleName}: ${pendingReason}`); + } else { + it(exampleName, async () => { + if (name === 'frontmatter_toml') { + setTestTimeoutOnce(2000); + } + await testSerializesHtmlToMarkdownForElement(example); + }); + } +}; diff --git a/spec/frontend/fixtures/api_markdown.rb b/spec/frontend/fixtures/api_markdown.rb deleted file mode 100644 index 89f012a5110..00000000000 --- a/spec/frontend/fixtures/api_markdown.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do - include ApiHelpers - include WikiHelpers - include JavaScriptFixturesHelpers - - let_it_be(:user) { create(:user, username: 'gitlab') } - - let_it_be(:group) { create(:group, :public) } - let_it_be(:project) { create(:project, :public, :repository, group: group) } - - let_it_be(:label) { create(:label, project: project, title: 'bug') } - let_it_be(:milestone) { create(:milestone, project: project, title: '1.1') } - let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:merge_request) { create(:merge_request, source_project: project) } - - let_it_be(:project_wiki) { create(:project_wiki, project: project, user: user) } - - let(:project_wiki_page) { create(:wiki_page, wiki: project_wiki) } - - before(:all) do - group.add_owner(user) - project.add_maintainer(user) - end - - before do - sign_in(user) - end - - markdown_examples = begin - yaml_file_path = File.expand_path('api_markdown.yml', __dir__) - yaml = File.read(yaml_file_path) - YAML.safe_load(yaml, symbolize_names: true) - end - - markdown_examples.each do |markdown_example| - context = markdown_example.fetch(:context, '') - name = markdown_example.fetch(:name) - - context "for #{name}#{!context.empty? ? " (context: #{context})" : ''}" do - let(:markdown) { markdown_example.fetch(:markdown) } - - name = "#{context}_#{name}" unless context.empty? - - it "api/markdown/#{name}.json" do - api_url = case context - when 'project' - "/#{project.full_path}/preview_markdown" - when 'group' - "/groups/#{group.full_path}/preview_markdown" - when 'project_wiki' - "/#{project.full_path}/-/wikis/#{project_wiki_page.slug}/preview_markdown" - else - api "/markdown" - end - - post api_url, params: { text: markdown, gfm: true } - expect(response).to be_successful - end - end - end -end diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml deleted file mode 100644 index 8fd6a5531db..00000000000 --- a/spec/frontend/fixtures/api_markdown.yml +++ /dev/null @@ -1,289 +0,0 @@ -# This data file drives the specs in -# spec/frontend/fixtures/api_markdown.rb and -# spec/frontend/content_editor/extensions/markdown_processing_spec.js ---- -- name: attachment_image - context: group - markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)' -- name: attachment_image - context: project - markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)' -- name: attachment_image - context: project_wiki - markdown: '![test-file](test-file.png)' -- name: attachment_link - context: group - markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)' -- name: attachment_link - context: project - markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)' -- name: attachment_link - context: project_wiki - markdown: '[test-file](test-file.zip)' -- name: audio - markdown: '![Sample Audio](https://gitlab.com/gitlab.mp3)' -- name: audio_and_video_in_lists - markdown: |- - * ![Sample Audio](https://gitlab.com/1.mp3) - * ![Sample Video](https://gitlab.com/2.mp4) - - 1. ![Sample Video](https://gitlab.com/1.mp4) - 2. ![Sample Audio](https://gitlab.com/2.mp3) - - * [x] ![Sample Audio](https://gitlab.com/1.mp3) - * [x] ![Sample Audio](https://gitlab.com/2.mp3) - * [x] ![Sample Video](https://gitlab.com/3.mp4) -- name: blockquote - markdown: |- - > This is a blockquote - > - > This is another one -- name: bold - markdown: '**bold**' -- name: bullet_list_style_1 - markdown: |- - * list item 1 - * list item 2 - * embedded list item 3 -- name: bullet_list_style_2 - markdown: |- - - list item 1 - - list item 2 - * embedded list item 3 -- name: bullet_list_style_3 - markdown: |- - + list item 1 - + list item 2 - - embedded list item 3 -- name: code_block - markdown: |- - ```javascript - console.log('hello world') - ``` -- name: color_chips - markdown: |- - - `#F00` - - `#F00A` - - `#FF0000` - - `#FF0000AA` - - `RGB(0,255,0)` - - `RGB(0%,100%,0%)` - - `RGBA(0,255,0,0.3)` - - `HSL(540,70%,50%)` - - `HSLA(540,70%,50%,0.3)` -- name: description_list - markdown: |- - <dl> - <dt>Frog</dt> - <dd>Wet green thing</dd> - <dt>Rabbit</dt> - <dd>Warm fluffy thing</dd> - <dt>Punt</dt> - <dd>Kick a ball</dd> - <dd>Take a bet</dd> - <dt>Color</dt> - <dt>Colour</dt> - <dd> - - Any hue except _white_ or **black** - - </dd> - </dl> -- name: details - markdown: |- - <details> - <summary>Apply this patch</summary> - - ```diff - diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml - index 8433efaf00c..69b12c59d46 100644 - --- a/spec/frontend/fixtures/api_markdown.yml - +++ b/spec/frontend/fixtures/api_markdown.yml - @@ -33,6 +33,13 @@ - * <ruby>漢<rt>ㄏㄢˋ</rt></ruby> - * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O - * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>.The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var> - +- name: details - + markdown: |- - + <details> - + <summary>Apply this patch</summary> - + - + 🐶 much meta, 🐶 many patch - + 🐶 such diff, 🐶 very meme - + 🐶 wow! - + </details> - - name: link - markdown: '[GitLab](https://gitlab.com)' - - name: attachment_link - ``` - - </details> -- name: div - markdown: |- - <div>plain text</div> - <div> - - just a plain ol' div, not much to _expect_! - - </div> -- name: emoji - markdown: ':sparkles: :heart: :100:' -- name: emphasis - markdown: '_emphasized text_' -- name: figure - markdown: |- - <figure> - - ![Elephant at sunset](elephant-sunset.jpg) - - <figcaption>An elephant at sunset</figcaption> - </figure> - <figure> - - ![A crocodile wearing crocs](croc-crocs.jpg) - - <figcaption> - - A crocodile wearing _crocs_! - - </figcaption> - </figure> -- name: frontmatter_json - markdown: |- - ;;; - { - "title": "Page title" - } - ;;; -- name: frontmatter_toml - markdown: |- - +++ - title = "Page title" - +++ -- name: frontmatter_yaml - markdown: |- - --- - title: Page title - --- -- name: hard_break - markdown: |- - This is a line after a\ - hard break -- name: headings - markdown: |- - # Heading 1 - - ## Heading 2 - - ### Heading 3 - - #### Heading 4 - - ##### Heading 5 - - ###### Heading 6 -- name: horizontal_rule - markdown: '---' -- name: html_marks - markdown: |- - * Content editor is ~~great~~<ins>amazing</ins>. - * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>. - * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">אה, אני אוהב להיות ליד חוף הים</span>. In the computer's memory, this is stored as <bdo dir="ltr">אה, אני אוהב להיות ליד חוף הים</bdo>. - * <cite>The Scream</cite> by Edvard Munch. Painted in 1893. - * <dfn>HTML</dfn> is the standard markup language for creating web pages. - * Do not forget to buy <mark>milk</mark> today. - * This is a paragraph and <small>smaller text goes here</small>. - * The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>. - * Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows). - * WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed. - * The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp> - * The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height. - * <ruby>漢<rt>ㄏㄢˋ</rt></ruby> - * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O - * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var> -- name: image - markdown: '![alt text](https://gitlab.com/logo.png)' -- name: inline_code - markdown: '`code`' -- name: inline_diff - markdown: |- - * {-deleted-} - * {+added+} -- name: link - markdown: '[GitLab](https://gitlab.com)' -- name: math - markdown: |- - This math is inline $`a^2+b^2=c^2`$. - - This is on a separate line: - - ```math - a^2+b^2=c^2 - ``` -- name: ordered_list - markdown: |- - 1. list item 1 - 2. list item 2 - 3. list item 3 -- name: ordered_list_with_start_order - markdown: |- - 134. list item 1 - 135. list item 2 - 136. list item 3 -- name: ordered_task_list - markdown: |- - 1. [x] hello - 2. [x] world - 3. [ ] example - 1. [ ] of nested - 1. [x] task list - 2. [ ] items -- name: ordered_task_list_with_order - markdown: |- - 4893. [x] hello - 4894. [x] world - 4895. [ ] example -- name: reference - context: project_wiki - markdown: |- - Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1 -- name: strike - markdown: '~~del~~' -- name: table - markdown: |- - | header | header | - |--------|--------| - | `code` | cell with **bold** | - | ~~strike~~ | cell with _italic_ | - - # content after table -- name: table_of_contents - markdown: |- - [[_TOC_]] - - # Lorem - - Well, that's just like... your opinion.. man. - - ## Ipsum - - ### Dolar - - # Sit amit - - ### I don't know -- name: task_list - markdown: |- - * [x] hello - * [x] world - * [ ] example - * [ ] of nested - * [x] task list - * [ ] items -- name: thematic_break - markdown: |- - --- -- name: video - markdown: '![Sample Video](https://gitlab.com/gitlab.mp4)' -- name: word_break - markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz |