diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/frontend/content_editor | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/frontend/content_editor')
5 files changed, 129 insertions, 47 deletions
diff --git a/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap index 178c7d749c8..7abd6b422ad 100644 --- a/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap +++ b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap @@ -19,7 +19,7 @@ exports[`content_editor/components/toolbar_link_button renders dropdown componen <div placeholder=\\"Link URL\\"> <div role=\\"group\\" class=\\"input-group\\"> <!----> - <!----> <input type=\\"text\\" placeholder=\\"Link URL\\" class=\\"gl-form-input form-control\\"> + <!----> <input type=\\"text\\" placeholder=\\"Link URL\\" class=\\"form-control gl-form-input\\"> <div class=\\"input-group-append\\"><button type=\\"button\\" class=\\"btn btn-confirm btn-md gl-button\\"> <!----> <!----> <span class=\\"gl-button-text\\">Apply</span></button></div> 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..3930f47289a 100644 --- a/spec/frontend/content_editor/markdown_processing_spec.js +++ b/spec/frontend/content_editor/markdown_processing_spec.js @@ -1,20 +1,16 @@ -import { createContentEditor } from '~/content_editor'; -import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples'; +import path from 'path'; +import { describeMarkdownProcessing } from 'jest/content_editor/markdown_processing_spec_helper'; jest.mock('~/emoji'); -describe('markdown processing', () => { - // 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); +const markdownYamlPath = path.join( + __dirname, + '..', + '..', + 'fixtures', + 'markdown', + 'markdown_golden_master_examples.yml', +); - expect(contentEditor.getSerializedContent()).toBe(markdown); - }, - ); -}); +// See spec/fixtures/markdown/markdown_golden_master_examples.yml for documentation on how this spec works. +describeMarkdownProcessing('CE markdown processing in ContentEditor', markdownYamlPath); 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..bb7ec0030a2 --- /dev/null +++ b/spec/frontend/content_editor/markdown_processing_spec_helper.js @@ -0,0 +1,86 @@ +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; +}; + +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); +}; + +// describeMarkdownProcesssing +// +// This is used to dynamically generate examples (for both CE and EE) to ensure +// we generate same markdown that was provided to Markdown API. +// +// eslint-disable-next-line jest/no-export +export const describeMarkdownProcessing = (description, markdownYamlPath) => { + const examples = loadMarkdownApiExamples(markdownYamlPath); + + describe(description, () => { + describe.each(examples)('%s', (name, { pendingReason, ...example }) => { + const exampleName = 'correctly serializes HTML to markdown'; + if (pendingReason) { + it.todo(`${exampleName}: ${pendingReason}`); + return; + } + + it(exampleName, async () => { + if (name === 'frontmatter_toml') { + setTestTimeoutOnce(2000); + } + await testSerializesHtmlToMarkdownForElement(example); + }); + }); + }); +}; diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js index cfd93c2df10..97f6d8f6334 100644 --- a/spec/frontend/content_editor/services/markdown_serializer_spec.js +++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js @@ -11,6 +11,9 @@ import Division from '~/content_editor/extensions/division'; import Emoji from '~/content_editor/extensions/emoji'; import Figure from '~/content_editor/extensions/figure'; import FigureCaption from '~/content_editor/extensions/figure_caption'; +import FootnoteDefinition from '~/content_editor/extensions/footnote_definition'; +import FootnoteReference from '~/content_editor/extensions/footnote_reference'; +import FootnotesSection from '~/content_editor/extensions/footnotes_section'; import HardBreak from '~/content_editor/extensions/hard_break'; import Heading from '~/content_editor/extensions/heading'; import HorizontalRule from '~/content_editor/extensions/horizontal_rule'; @@ -28,7 +31,6 @@ import TableHeader from '~/content_editor/extensions/table_header'; import TableRow from '~/content_editor/extensions/table_row'; import TaskItem from '~/content_editor/extensions/task_item'; import TaskList from '~/content_editor/extensions/task_list'; -import Text from '~/content_editor/extensions/text'; import markdownSerializer from '~/content_editor/services/markdown_serializer'; import { createTestEditor, createDocBuilder } from '../test_utils'; @@ -47,6 +49,9 @@ const tiptapEditor = createTestEditor({ DetailsContent, Division, Emoji, + FootnoteDefinition, + FootnoteReference, + FootnotesSection, Figure, FigureCaption, HardBreak, @@ -58,7 +63,6 @@ const tiptapEditor = createTestEditor({ Link, ListItem, OrderedList, - Paragraph, Strike, Table, TableCell, @@ -66,7 +70,6 @@ const tiptapEditor = createTestEditor({ TableRow, TaskItem, TaskList, - Text, ], }); @@ -84,6 +87,9 @@ const { descriptionItem, descriptionList, emoji, + footnoteDefinition, + footnoteReference, + footnotesSection, figure, figureCaption, heading, @@ -120,6 +126,9 @@ const { emoji: { markType: Emoji.name }, figure: { nodeType: Figure.name }, figureCaption: { nodeType: FigureCaption.name }, + footnoteDefinition: { nodeType: FootnoteDefinition.name }, + footnoteReference: { nodeType: FootnoteReference.name }, + footnotesSection: { nodeType: FootnotesSection.name }, hardBreak: { nodeType: HardBreak.name }, heading: { nodeType: Heading.name }, horizontalRule: { nodeType: HorizontalRule.name }, @@ -1108,4 +1117,22 @@ there `.trim(), ); }); + + it('correctly serializes footnotes', () => { + expect( + serialize( + paragraph( + 'Oranges are orange ', + footnoteReference({ footnoteId: '1', footnoteNumber: '1' }), + ), + footnotesSection(footnoteDefinition(paragraph('Oranges are fruits'))), + ), + ).toBe( + ` +Oranges are orange [^1] + +[^1]: Oranges are fruits + `.trim(), + ); + }); }); |