diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/rich_content_editor/services')
15 files changed, 0 insertions, 817 deletions
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js deleted file mode 100644 index a823d04024d..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js +++ /dev/null @@ -1,32 +0,0 @@ -import buildCustomHTMLRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer'; - -describe('Build Custom Renderer Service', () => { - describe('buildCustomHTMLRenderer', () => { - it('should return an object with the default renderer functions when lacking arguments', () => { - expect(buildCustomHTMLRenderer()).toEqual( - expect.objectContaining({ - htmlBlock: expect.any(Function), - htmlInline: expect.any(Function), - heading: expect.any(Function), - item: expect.any(Function), - paragraph: expect.any(Function), - text: expect.any(Function), - softbreak: expect.any(Function), - }), - ); - }); - - it('should return an object with both custom and default renderer functions when passed customRenderers', () => { - const mockHtmlCustomRenderer = jest.fn(); - const customRenderers = { - html: [mockHtmlCustomRenderer], - }; - - expect(buildCustomHTMLRenderer(customRenderers)).toEqual( - expect.objectContaining({ - html: expect.any(Function), - }), - ); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js deleted file mode 100644 index 3caf03dabba..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js +++ /dev/null @@ -1,218 +0,0 @@ -import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer'; -import { attributeDefinition } from './renderers/mock_data'; - -describe('rich_content_editor/services/html_to_markdown_renderer', () => { - let baseRenderer; - let htmlToMarkdownRenderer; - let fakeNode; - - beforeEach(() => { - baseRenderer = { - trim: jest.fn((input) => `trimmed ${input}`), - getSpaceCollapsedText: jest.fn((input) => `space collapsed ${input}`), - getSpaceControlled: jest.fn((input) => `space controlled ${input}`), - convert: jest.fn(), - }; - - fakeNode = { nodeValue: 'mock_node', dataset: {} }; - }); - - afterEach(() => { - htmlToMarkdownRenderer = null; - }); - - describe('TEXT_NODE visitor', () => { - it('composes getSpaceControlled, getSpaceCollapsedText, and trim services', () => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - - expect(htmlToMarkdownRenderer.TEXT_NODE(fakeNode)).toBe( - `space controlled trimmed space collapsed ${fakeNode.nodeValue}`, - ); - }); - }); - - describe('LI OL, LI UL visitor', () => { - const oneLevelNestedList = '\n * List item 1\n * List item 2'; - const twoLevelNestedList = '\n * List item 1\n * List item 2'; - const spaceInContentList = '\n * List item 1\n * List item 2'; - - it.each` - list | indentSpaces | result - ${oneLevelNestedList} | ${2} | ${'\n * List item 1\n * List item 2'} - ${oneLevelNestedList} | ${3} | ${'\n * List item 1\n * List item 2'} - ${oneLevelNestedList} | ${6} | ${'\n * List item 1\n * List item 2'} - ${twoLevelNestedList} | ${4} | ${'\n * List item 1\n * List item 2'} - ${spaceInContentList} | ${1} | ${'\n * List item 1\n * List item 2'} - `('changes the list indentation to $indentSpaces spaces', ({ list, indentSpaces, result }) => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, { - subListIndentSpaces: indentSpaces, - }); - - baseRenderer.convert.mockReturnValueOnce(list); - - expect(htmlToMarkdownRenderer['LI OL, LI UL'](fakeNode, list)).toBe(result); - expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, list); - }); - }); - - describe('UL LI visitor', () => { - it.each` - listItem | unorderedListBulletChar | result | bulletChar - ${'* list item'} | ${undefined} | ${'- list item'} | ${'default'} - ${' - list item'} | ${'*'} | ${' * list item'} | ${'*'} - ${' * list item'} | ${'-'} | ${' - list item'} | ${'-'} - `( - 'uses $bulletChar bullet char in unordered list items when $unorderedListBulletChar is set in config', - ({ listItem, unorderedListBulletChar, result }) => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, { - unorderedListBulletChar, - }); - baseRenderer.convert.mockReturnValueOnce(listItem); - - expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result); - expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, listItem); - }, - ); - - it('detects attribute definitions and attaches them to the list item', () => { - const listItem = '- list item'; - const result = `${listItem}\n${attributeDefinition}\n`; - - fakeNode.dataset.attributeDefinition = attributeDefinition; - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - baseRenderer.convert.mockReturnValueOnce(`${listItem}\n`); - - expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result); - }); - }); - - describe('OL LI visitor', () => { - it.each` - listItem | result | incrementListMarker | action - ${'2. list item'} | ${'1. list item'} | ${false} | ${'increments'} - ${' 3. list item'} | ${' 1. list item'} | ${false} | ${'increments'} - ${' 123. list item'} | ${' 1. list item'} | ${false} | ${'increments'} - ${'3. list item'} | ${'3. list item'} | ${true} | ${'does not increment'} - `( - '$action a list item counter when incrementListMaker is $incrementListMarker', - ({ listItem, result, incrementListMarker }) => { - const subContent = null; - - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, { - incrementListMarker, - }); - baseRenderer.convert.mockReturnValueOnce(listItem); - - expect(htmlToMarkdownRenderer['OL LI'](fakeNode, subContent)).toBe(result); - expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, subContent); - }, - ); - }); - - describe('STRONG, B visitor', () => { - it.each` - input | strongCharacter | result - ${'**strong text**'} | ${'_'} | ${'__strong text__'} - ${'__strong text__'} | ${'*'} | ${'**strong text**'} - `( - 'converts $input to $result when strong character is $strongCharacter', - ({ input, strongCharacter, result }) => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, { - strong: strongCharacter, - }); - - baseRenderer.convert.mockReturnValueOnce(input); - - expect(htmlToMarkdownRenderer['STRONG, B'](fakeNode, input)).toBe(result); - expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input); - }, - ); - }); - - describe('EM, I visitor', () => { - it.each` - input | emphasisCharacter | result - ${'*strong text*'} | ${'_'} | ${'_strong text_'} - ${'_strong text_'} | ${'*'} | ${'*strong text*'} - `( - 'converts $input to $result when emphasis character is $emphasisCharacter', - ({ input, emphasisCharacter, result }) => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, { - emphasis: emphasisCharacter, - }); - - baseRenderer.convert.mockReturnValueOnce(input); - - expect(htmlToMarkdownRenderer['EM, I'](fakeNode, input)).toBe(result); - expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input); - }, - ); - }); - - describe('H1, H2, H3, H4, H5, H6 visitor', () => { - it('detects attribute definitions and attaches them to the heading', () => { - const heading = 'heading text'; - const result = `${heading.trimRight()}\n${attributeDefinition}\n\n`; - - fakeNode.dataset.attributeDefinition = attributeDefinition; - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - baseRenderer.convert.mockReturnValueOnce(`${heading}\n\n`); - - expect(htmlToMarkdownRenderer['H1, H2, H3, H4, H5, H6'](fakeNode, heading)).toBe(result); - }); - }); - - describe('PRE CODE', () => { - let node; - const subContent = 'sub content'; - const originalConverterResult = 'base result'; - - beforeEach(() => { - node = document.createElement('PRE'); - - node.innerText = 'reference definition content'; - node.dataset.sseReferenceDefinition = true; - - baseRenderer.convert.mockReturnValueOnce(originalConverterResult); - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - }); - - it('returns raw text when pre node has sse-reference-definitions class', () => { - expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe( - `\n\n${node.innerText}\n\n`, - ); - }); - - it('returns base result when pre node does not have sse-reference-definitions class', () => { - delete node.dataset.sseReferenceDefinition; - - expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(originalConverterResult); - }); - }); - - describe('IMG', () => { - const originalSrc = 'path/to/image.png'; - const alt = 'alt text'; - let node; - - beforeEach(() => { - node = document.createElement('img'); - node.alt = alt; - node.src = originalSrc; - }); - - it('returns an image with its original src of the `original-src` attribute is preset', () => { - node.dataset.originalSrc = originalSrc; - node.src = 'modified/path/to/image.png'; - - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - - expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`); - }); - - it('fallback to `src` if no `original-src` is specified on the image', () => { - htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer); - expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js deleted file mode 100644 index 7a7e3055520..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js +++ /dev/null @@ -1,88 +0,0 @@ -import { - buildTextToken, - buildUneditableOpenTokens, - buildUneditableCloseToken, - buildUneditableCloseTokens, - buildUneditableBlockTokens, - buildUneditableInlineTokens, - buildUneditableHtmlAsTextTokens, -} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token'; - -import { - originInlineToken, - originToken, - uneditableOpenTokens, - uneditableCloseToken, - uneditableCloseTokens, - uneditableBlockTokens, - uneditableInlineTokens, - uneditableTokens, -} from './mock_data'; - -describe('Build Uneditable Token renderer helper', () => { - describe('buildTextToken', () => { - it('returns an object literal representing a text token', () => { - const text = originToken.content; - expect(buildTextToken(text)).toStrictEqual(originToken); - }); - }); - - describe('buildUneditableOpenTokens', () => { - it('returns a 2-item array of tokens with the originToken appended to an open token', () => { - const result = buildUneditableOpenTokens(originToken); - - expect(result).toHaveLength(2); - expect(result).toStrictEqual(uneditableOpenTokens); - }); - }); - - describe('buildUneditableCloseToken', () => { - it('returns an object literal representing the uneditable close token', () => { - expect(buildUneditableCloseToken()).toStrictEqual(uneditableCloseToken); - }); - }); - - describe('buildUneditableCloseTokens', () => { - it('returns a 2-item array of tokens with the originToken prepended to a close token', () => { - const result = buildUneditableCloseTokens(originToken); - - expect(result).toHaveLength(2); - expect(result).toStrictEqual(uneditableCloseTokens); - }); - }); - - describe('buildUneditableBlockTokens', () => { - it('returns a 3-item array of tokens with the originToken wrapped in the middle of block tokens', () => { - const result = buildUneditableBlockTokens(originToken); - - expect(result).toHaveLength(3); - expect(result).toStrictEqual(uneditableTokens); - }); - }); - - describe('buildUneditableInlineTokens', () => { - it('returns a 3-item array of tokens with the originInlineToken wrapped in the middle of inline tokens', () => { - const result = buildUneditableInlineTokens(originInlineToken); - - expect(result).toHaveLength(3); - expect(result).toStrictEqual(uneditableInlineTokens); - }); - }); - - describe('buildUneditableHtmlAsTextTokens', () => { - it('returns a 3-item array of tokens with the htmlBlockNode wrapped as a text token in the middle of block tokens', () => { - const htmlBlockNode = { - type: 'htmlBlock', - literal: '<div data-tomark-pass ><h1>Some header</h1><p>Some paragraph</p></div>', - }; - const result = buildUneditableHtmlAsTextTokens(htmlBlockNode); - const { type, content } = result[1]; - - expect(type).toBe('text'); - expect(content).not.toMatch(/ data-tomark-pass /); - - expect(result).toHaveLength(3); - expect(result).toStrictEqual(uneditableBlockTokens); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js deleted file mode 100644 index 407072fb596..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js +++ /dev/null @@ -1,54 +0,0 @@ -// Node spec helpers - -export const buildMockTextNode = (literal) => ({ literal, type: 'text' }); - -export const normalTextNode = buildMockTextNode('This is just normal text.'); - -// Token spec helpers - -const buildMockUneditableOpenToken = (type) => { - return { - type: 'openTag', - tagName: type, - attributes: { contenteditable: false }, - classNames: [ - 'gl-px-4 gl-py-2 gl-my-5 gl-opacity-5 gl-bg-gray-100 gl-user-select-none gl-cursor-not-allowed', - ], - }; -}; - -const buildMockTextToken = (content) => { - return { - type: 'text', - tagName: null, - content, - }; -}; - -const buildMockUneditableCloseToken = (type) => ({ type: 'closeTag', tagName: type }); - -export const originToken = buildMockTextToken('{:.no_toc .hidden-md .hidden-lg}'); -const uneditableOpenToken = buildMockUneditableOpenToken('div'); -export const uneditableOpenTokens = [uneditableOpenToken, originToken]; -export const uneditableCloseToken = buildMockUneditableCloseToken('div'); -export const uneditableCloseTokens = [originToken, uneditableCloseToken]; -export const uneditableTokens = [...uneditableOpenTokens, uneditableCloseToken]; - -export const originInlineToken = { - type: 'text', - content: '<i>Inline</i> content', -}; - -export const uneditableInlineTokens = [ - buildMockUneditableOpenToken('a'), - originInlineToken, - buildMockUneditableCloseToken('a'), -]; - -export const uneditableBlockTokens = [ - uneditableOpenToken, - buildMockTextToken('<div><h1>Some header</h1><p>Some paragraph</p></div>'), - uneditableCloseToken, -]; - -export const attributeDefinition = '{:.no_toc .hidden-md .hidden-lg}'; diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js deleted file mode 100644 index 69fd9a67a21..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js +++ /dev/null @@ -1,25 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition'; -import { attributeDefinition } from './mock_data'; - -describe('rich_content_editor/renderers/render_attribute_definition', () => { - describe('canRender', () => { - it.each` - input | result - ${{ literal: attributeDefinition }} | ${true} - ${{ literal: `FOO${attributeDefinition}` }} | ${false} - ${{ literal: `${attributeDefinition}BAR` }} | ${false} - ${{ literal: 'foobar' }} | ${false} - `('returns $result when input is $input', ({ input, result }) => { - expect(renderer.canRender(input)).toBe(result); - }); - }); - - describe('render', () => { - it('returns an empty HTML comment', () => { - expect(renderer.render()).toEqual({ - type: 'html', - content: '<!-- sse-attribute-definition -->', - }); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js deleted file mode 100644 index 0c59d9f569b..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js +++ /dev/null @@ -1,24 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text'; -import { renderUneditableLeaf } from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils'; - -import { buildMockTextNode, normalTextNode } from './mock_data'; - -const embeddedRubyTextNode = buildMockTextNode('<%= partial("some/path") %>'); - -describe('Render Embedded Ruby Text renderer', () => { - describe('canRender', () => { - it('should return true when the argument `literal` has embedded ruby syntax', () => { - expect(renderer.canRender(embeddedRubyTextNode)).toBe(true); - }); - - it('should return false when the argument `literal` lacks embedded ruby syntax', () => { - expect(renderer.canRender(normalTextNode)).toBe(false); - }); - }); - - describe('render', () => { - it('should delegate rendering to the renderUneditableLeaf util', () => { - expect(renderer.render).toBe(renderUneditableLeaf); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js deleted file mode 100644 index c1aaed6f0c3..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token'; -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline'; - -import { normalTextNode } from './mock_data'; - -const fontAwesomeInlineHtmlNode = { - firstChild: null, - literal: '<i class="far fa-paper-plane" id="biz-tech-icons">', - type: 'html', -}; - -describe('Render Font Awesome Inline HTML renderer', () => { - describe('canRender', () => { - it('should return true when the argument `literal` has font awesome inline html syntax', () => { - expect(renderer.canRender(fontAwesomeInlineHtmlNode)).toBe(true); - }); - - it('should return false when the argument `literal` lacks font awesome inline html syntax', () => { - expect(renderer.canRender(normalTextNode)).toBe(false); - }); - }); - - describe('render', () => { - it('should return uneditable inline tokens', () => { - const token = { type: 'text', tagName: null, content: fontAwesomeInlineHtmlNode.literal }; - const context = { origin: () => token }; - - expect(renderer.render(fontAwesomeInlineHtmlNode, context)).toStrictEqual( - buildUneditableInlineTokens(token), - ); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js deleted file mode 100644 index 76abc1ec3d8..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js +++ /dev/null @@ -1,12 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_heading'; -import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils'; - -describe('rich_content_editor/renderers/render_heading', () => { - it('canRender delegates to renderUtils.willAlwaysRender', () => { - expect(renderer.canRender).toBe(renderUtils.willAlwaysRender); - }); - - it('render delegates to renderUtils.renderWithAttributeDefinitions', () => { - expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js deleted file mode 100644 index 234f6a4d4ca..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import { buildUneditableHtmlAsTextTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token'; -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_html_block'; - -describe('rich_content_editor/services/renderers/render_html_block', () => { - const htmlBlockNode = { - literal: '<div><h1>Heading</h1><p>Paragraph.</p></div>', - type: 'htmlBlock', - }; - - describe('canRender', () => { - it.each` - input | result - ${htmlBlockNode} | ${true} - ${{ literal: '<iframe></iframe>', type: 'htmlBlock' }} | ${true} - ${{ literal: '<iframe src="https://www.youtube.com"></iframe>', type: 'htmlBlock' }} | ${false} - ${{ literal: '<iframe></iframe>', type: 'text' }} | ${false} - `('returns $result when input=$input', ({ input, result }) => { - expect(renderer.canRender(input)).toBe(result); - }); - }); - - describe('render', () => { - const htmlBlockNodeToMark = { - firstChild: null, - literal: '<div data-to-mark ></div>', - type: 'htmlBlock', - }; - - it.each` - node - ${htmlBlockNode} - ${htmlBlockNodeToMark} - `('should return uneditable tokens wrapping the $node as a token', ({ node }) => { - expect(renderer.render(node)).toStrictEqual(buildUneditableHtmlAsTextTokens(node)); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js deleted file mode 100644 index 425d0f41bcd..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js +++ /dev/null @@ -1,55 +0,0 @@ -import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token'; -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text'; - -import { buildMockTextNode, normalTextNode } from './mock_data'; - -const mockTextStart = 'Majority example '; -const mockTextMiddle = '[environment terraform plans][terraform]'; -const mockTextEnd = '.'; -const identifierInstanceStartTextNode = buildMockTextNode(mockTextStart); -const identifierInstanceEndTextNode = buildMockTextNode(mockTextEnd); - -describe('Render Identifier Instance Text renderer', () => { - describe('canRender', () => { - it.each` - node | target - ${normalTextNode} | ${false} - ${identifierInstanceStartTextNode} | ${false} - ${identifierInstanceEndTextNode} | ${false} - ${buildMockTextNode(mockTextMiddle)} | ${true} - ${buildMockTextNode('Minority example [environment terraform plans][]')} | ${true} - ${buildMockTextNode('Minority example [environment terraform plans]')} | ${true} - `( - 'should return $target when the $node validates against identifier instance syntax', - ({ node, target }) => { - expect(renderer.canRender(node)).toBe(target); - }, - ); - }); - - describe('render', () => { - it.each` - start | middle | end - ${mockTextStart} | ${mockTextMiddle} | ${mockTextEnd} - ${mockTextStart} | ${'[environment terraform plans][]'} | ${mockTextEnd} - ${mockTextStart} | ${'[environment terraform plans]'} | ${mockTextEnd} - `( - 'should return inline editable, uneditable, and editable tokens in sequence', - ({ start, middle, end }) => { - const buildMockTextToken = (content) => ({ type: 'text', tagName: null, content }); - - const startToken = buildMockTextToken(start); - const middleToken = buildMockTextToken(middle); - const endToken = buildMockTextToken(end); - - const content = `${start}${middle}${end}`; - const contentToken = buildMockTextToken(content); - const contentNode = buildMockTextNode(content); - const context = { origin: jest.fn().mockReturnValueOnce(contentToken) }; - expect(renderer.render(contentNode, context)).toStrictEqual( - [startToken, buildUneditableInlineTokens(middleToken), endToken].flat(), - ); - }, - ); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js deleted file mode 100644 index 470cf9bddaa..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js +++ /dev/null @@ -1,84 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph'; - -import { buildMockTextNode } from './mock_data'; - -const buildMockParagraphNode = (literal) => { - return { - firstChild: buildMockTextNode(literal), - type: 'paragraph', - }; -}; - -const normalParagraphNode = buildMockParagraphNode( - 'This is just normal paragraph. It has multiple sentences.', -); -const identifierParagraphNode = buildMockParagraphNode( - `[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example2.com`, -); - -describe('rich_content_editor/renderers_render_identifier_paragraph', () => { - describe('canRender', () => { - it.each` - node | paragraph | target - ${identifierParagraphNode} | ${'[Some text]: https://link.com'} | ${true} - ${normalParagraphNode} | ${'Normal non-identifier text. Another sentence.'} | ${false} - `( - 'should return $target when the $node matches $paragraph syntax', - ({ node, paragraph, target }) => { - const context = { - entering: true, - getChildrenText: jest.fn().mockReturnValueOnce(paragraph), - }; - - expect(renderer.canRender(node, context)).toBe(target); - }, - ); - }); - - describe('render', () => { - let context; - let result; - - beforeEach(() => { - const node = { - firstChild: { - type: 'text', - literal: '[Some text]: https://link.com', - next: { - type: 'linebreak', - next: { - type: 'text', - literal: '[identifier]: http://example1.com "title"', - }, - }, - }, - }; - context = { skipChildren: jest.fn() }; - result = renderer.render(node, context); - }); - - it('renders the reference definitions as a code block', () => { - expect(result).toEqual([ - { - type: 'openTag', - tagName: 'pre', - classNames: ['code-block', 'language-markdown'], - attributes: { - 'data-sse-reference-definition': true, - }, - }, - { type: 'openTag', tagName: 'code' }, - { - type: 'text', - content: '[Some text]: https://link.com\n[identifier]: http://example1.com "title"', - }, - { type: 'closeTag', tagName: 'code' }, - { type: 'closeTag', tagName: 'pre' }, - ]); - }); - - it('skips the reference definition node children from rendering', () => { - expect(context.skipChildren).toHaveBeenCalled(); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js deleted file mode 100644 index c1ab700535b..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js +++ /dev/null @@ -1,12 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_list_item'; -import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils'; - -describe('rich_content_editor/renderers/render_list_item', () => { - it('canRender delegates to renderUtils.willAlwaysRender', () => { - expect(renderer.canRender).toBe(renderUtils.willAlwaysRender); - }); - - it('render delegates to renderUtils.renderWithAttributeDefinitions', () => { - expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js deleted file mode 100644 index 3c3d2354cb9..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js +++ /dev/null @@ -1,23 +0,0 @@ -import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_softbreak'; - -describe('Render softbreak renderer', () => { - describe('canRender', () => { - it.each` - node | parentType | result - ${{ parent: { type: 'emph' } }} | ${'emph'} | ${true} - ${{ parent: { type: 'strong' } }} | ${'strong'} | ${true} - ${{ parent: { type: 'paragraph' } }} | ${'paragraph'} | ${false} - `('returns $result when node parent type is $parentType ', ({ node, result }) => { - expect(renderer.canRender(node)).toBe(result); - }); - }); - - describe('render', () => { - it('returns text node with a break line', () => { - expect(renderer.render()).toEqual({ - type: 'text', - content: ' ', - }); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js deleted file mode 100644 index 7c1809c290c..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import { - buildUneditableBlockTokens, - buildUneditableOpenTokens, -} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token'; -import { - renderUneditableLeaf, - renderUneditableBranch, - renderWithAttributeDefinitions, - willAlwaysRender, -} from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils'; - -import { originToken, uneditableCloseToken, attributeDefinition } from './mock_data'; - -describe('rich_content_editor/renderers/render_utils', () => { - describe('renderUneditableLeaf', () => { - it('should return uneditable block tokens around an origin token', () => { - const context = { origin: jest.fn().mockReturnValueOnce(originToken) }; - const result = renderUneditableLeaf({}, context); - - expect(result).toStrictEqual(buildUneditableBlockTokens(originToken)); - }); - }); - - describe('renderUneditableBranch', () => { - let origin; - - beforeEach(() => { - origin = jest.fn().mockReturnValueOnce(originToken); - }); - - it('should return uneditable block open token followed by the origin token when entering', () => { - const context = { entering: true, origin }; - const result = renderUneditableBranch({}, context); - - expect(result).toStrictEqual(buildUneditableOpenTokens(originToken)); - }); - - it('should return uneditable block closing token when exiting', () => { - const context = { entering: false, origin }; - const result = renderUneditableBranch({}, context); - - expect(result).toStrictEqual(uneditableCloseToken); - }); - }); - - describe('willAlwaysRender', () => { - it('always returns true', () => { - expect(willAlwaysRender()).toBe(true); - }); - }); - - describe('renderWithAttributeDefinitions', () => { - let openTagToken; - let closeTagToken; - let node; - const attributes = { - 'data-attribute-definition': attributeDefinition, - }; - - beforeEach(() => { - openTagToken = { type: 'openTag' }; - closeTagToken = { type: 'closeTag' }; - node = { - next: { - firstChild: { - literal: attributeDefinition, - }, - }, - }; - }); - - describe('when token type is openTag', () => { - it('attaches attributes when attributes exist in the node’s next sibling', () => { - const context = { origin: () => openTagToken }; - - expect(renderWithAttributeDefinitions(node, context)).toEqual({ - ...openTagToken, - attributes, - }); - }); - - it('attaches attributes when attributes exist in the node’s children', () => { - const context = { origin: () => openTagToken }; - node = { - firstChild: { - firstChild: { - next: { - next: { - literal: attributeDefinition, - }, - }, - }, - }, - }; - - expect(renderWithAttributeDefinitions(node, context)).toEqual({ - ...openTagToken, - attributes, - }); - }); - }); - - it('does not attach attributes when token type is "closeTag"', () => { - const context = { origin: () => closeTagToken }; - - expect(renderWithAttributeDefinitions({}, context)).toBe(closeTagToken); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js deleted file mode 100644 index f2182ef60d7..00000000000 --- a/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js +++ /dev/null @@ -1,11 +0,0 @@ -import sanitizeHTML from '~/vue_shared/components/rich_content_editor/services/sanitize_html'; - -describe('rich_content_editor/services/sanitize_html', () => { - it.each` - input | result - ${'<iframe src="https://www.youtube.com"></iframe>'} | ${'<iframe src="https://www.youtube.com"></iframe>'} - ${'<iframe src="https://gitlab.com"></iframe>'} | ${''} - `('removes iframes if the iframe source origin is not allowed', ({ input, result }) => { - expect(sanitizeHTML(input)).toBe(result); - }); -}); |