diff options
Diffstat (limited to 'spec/frontend/content_editor/components/wrappers/code_block_spec.js')
-rw-r--r-- | spec/frontend/content_editor/components/wrappers/code_block_spec.js | 239 |
1 files changed, 236 insertions, 3 deletions
diff --git a/spec/frontend/content_editor/components/wrappers/code_block_spec.js b/spec/frontend/content_editor/components/wrappers/code_block_spec.js index cbeea90dcb4..e802681dfc6 100644 --- a/spec/frontend/content_editor/components/wrappers/code_block_spec.js +++ b/spec/frontend/content_editor/components/wrappers/code_block_spec.js @@ -6,11 +6,26 @@ import eventHubFactory from '~/helpers/event_hub_factory'; import SandboxedMermaid from '~/behaviors/components/sandboxed_mermaid.vue'; import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight'; import Diagram from '~/content_editor/extensions/diagram'; +import CodeSuggestion from '~/content_editor/extensions/code_suggestion'; import CodeBlockWrapper from '~/content_editor/components/wrappers/code_block.vue'; import codeBlockLanguageLoader from '~/content_editor/services/code_block_language_loader'; -import { emitEditorEvent, createTestEditor } from '../../test_utils'; +import { emitEditorEvent, createTestEditor, mockChainedCommands } from '../../test_utils'; + +const SAMPLE_README_CONTENT = `# Sample README + +This is a sample README. + +## Usage + +\`\`\`yaml +foo: bar +\`\`\` +`; jest.mock('~/content_editor/services/code_block_language_loader'); +jest.mock('~/content_editor/services/utils', () => ({ + memoizedGet: jest.fn().mockResolvedValue(SAMPLE_README_CONTENT), +})); describe('content/components/wrappers/code_block', () => { const language = 'yaml'; @@ -21,7 +36,7 @@ describe('content/components/wrappers/code_block', () => { let eventHub; const buildEditor = () => { - tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight, Diagram] }); + tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight, Diagram, CodeSuggestion] }); contentEditor = { renderDiagram: jest.fn().mockResolvedValue('url/to/some/diagram') }; eventHub = eventHubFactory(); }; @@ -76,7 +91,7 @@ describe('content/components/wrappers/code_block', () => { it('renders label indicating that code block is frontmatter', () => { createWrapper({ isFrontmatter: true, language }); - const label = wrapper.find('[data-testid="frontmatter-label"]'); + const label = wrapper.findByTestId('frontmatter-label'); expect(label.text()).toEqual('frontmatter:yaml'); expect(label.classes()).toEqual(['gl-absolute', 'gl-top-0', 'gl-right-3']); @@ -143,4 +158,222 @@ describe('content/components/wrappers/code_block', () => { expect(wrapper.find('img').exists()).toBe(false); }); }); + + describe('code suggestions', () => { + const nodeAttrs = { language: 'suggestion', isCodeSuggestion: true, langParams: '-0+0' }; + const findCodeSuggestionBoxText = () => + wrapper.findByTestId('code-suggestion-box').text().replace(/\s+/gm, ' '); + const findCodeDeleted = () => + wrapper + .findByTestId('suggestion-deleted') + .findAll('code') + .wrappers.map((w) => w.html()) + .join('\n'); + const findCodeAdded = () => + wrapper + .findByTestId('suggestion-added') + .findAll('code') + .wrappers.map((w) => w.html()) + .join('\n'); + + let commands; + + const clickButton = async ({ button, expectedLangParams }) => { + await button.trigger('click'); + + expect(commands.updateAttributes).toHaveBeenCalledWith('codeSuggestion', { + langParams: expectedLangParams, + }); + expect(commands.run).toHaveBeenCalled(); + + await wrapper.setProps({ node: { attrs: { ...nodeAttrs, langParams: expectedLangParams } } }); + await emitEditorEvent({ event: 'transaction', tiptapEditor }); + }; + + beforeEach(async () => { + contentEditor = { + codeSuggestionsConfig: { + canSuggest: true, + line: { new_line: 5 }, + lines: [{ new_line: 5 }], + showPopover: false, + diffFile: { + view_path: + '/gitlab-org/gitlab-test/-/blob/468abc807a2b2572f43e72c743b76cee6db24025/README.md', + }, + }, + }; + + commands = mockChainedCommands(tiptapEditor, ['updateAttributes', 'run']); + + createWrapper(nodeAttrs); + await emitEditorEvent({ event: 'transaction', tiptapEditor }); + }); + + it('shows a code suggestion block', () => { + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 5 to 5'); + expect(findCodeDeleted()).toMatchInlineSnapshot( + `"<code data-line-number=\\"5\\">## Usage\u200b</code>"`, + ); + expect(findCodeAdded()).toMatchInlineSnapshot( + `"<code data-line-number=\\"5\\">\u200b</code>"`, + ); + }); + + describe('decrement line start button', () => { + let button; + + beforeEach(() => { + button = wrapper.findByTestId('decrement-line-start'); + }); + + it('decrements the start line number', async () => { + await clickButton({ button, expectedLangParams: '-1+0' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 4 to 5'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"4\\">\u200b + </code> + <code data-line-number=\\"5\\">## Usage\u200b</code>" + `); + }); + + it('is disabled if the start line is already 1', async () => { + expect(button.attributes('disabled')).toBeUndefined(); + + await clickButton({ button, expectedLangParams: '-1+0' }); + await clickButton({ button, expectedLangParams: '-2+0' }); + await clickButton({ button, expectedLangParams: '-3+0' }); + await clickButton({ button, expectedLangParams: '-4+0' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 1 to 5'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"1\\"># Sample README\u200b + </code> + <code data-line-number=\\"2\\">\u200b + </code> + <code data-line-number=\\"3\\">This is a sample README.\u200b + </code> + <code data-line-number=\\"4\\">\u200b + </code> + <code data-line-number=\\"5\\">## Usage\u200b</code>" + `); + + expect(button.attributes('disabled')).toBe('disabled'); + }); + }); + + describe('increment line start button', () => { + let decrementButton; + let button; + + beforeEach(() => { + decrementButton = wrapper.findByTestId('decrement-line-start'); + button = wrapper.findByTestId('increment-line-start'); + }); + + it('is disabled if the start line is already the current line', async () => { + expect(button.attributes('disabled')).toBe('disabled'); + + // decrement once, increment once + await clickButton({ button: decrementButton, expectedLangParams: '-1+0' }); + expect(button.attributes('disabled')).toBeUndefined(); + await clickButton({ button, expectedLangParams: '-0+0' }); + + expect(button.attributes('disabled')).toBe('disabled'); + }); + + it('increments the start line number', async () => { + // decrement twice, increment once + await clickButton({ button: decrementButton, expectedLangParams: '-1+0' }); + await clickButton({ button: decrementButton, expectedLangParams: '-2+0' }); + await clickButton({ button, expectedLangParams: '-1+0' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 4 to 5'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"4\\">\u200b + </code> + <code data-line-number=\\"5\\">## Usage\u200b</code>" + `); + }); + }); + + describe('decrement line end button', () => { + let incrementButton; + let button; + + beforeEach(() => { + incrementButton = wrapper.findByTestId('increment-line-end'); + button = wrapper.findByTestId('decrement-line-end'); + }); + + it('is disabled if the line end is already the current line', async () => { + expect(button.attributes('disabled')).toBe('disabled'); + + // increment once, decrement once + await clickButton({ button: incrementButton, expectedLangParams: '-0+1' }); + expect(button.attributes('disabled')).toBeUndefined(); + await clickButton({ button, expectedLangParams: '-0+0' }); + + expect(button.attributes('disabled')).toBe('disabled'); + }); + + it('increments the end line number', async () => { + // increment twice, decrement once + await clickButton({ button: incrementButton, expectedLangParams: '-0+1' }); + await clickButton({ button: incrementButton, expectedLangParams: '-0+2' }); + await clickButton({ button, expectedLangParams: '-0+1' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 5 to 6'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"5\\">## Usage\u200b + </code> + <code data-line-number=\\"6\\">\u200b</code>" + `); + }); + }); + + describe('increment line end button', () => { + let button; + + beforeEach(() => { + button = wrapper.findByTestId('increment-line-end'); + }); + + it('decrements the start line number', async () => { + await clickButton({ button, expectedLangParams: '-0+1' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 5 to 6'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"5\\">## Usage\u200b + </code> + <code data-line-number=\\"6\\">\u200b</code>" + `); + }); + + it('is disabled if the end line is EOF', async () => { + expect(button.attributes('disabled')).toBeUndefined(); + + await clickButton({ button, expectedLangParams: '-0+1' }); + await clickButton({ button, expectedLangParams: '-0+2' }); + await clickButton({ button, expectedLangParams: '-0+3' }); + await clickButton({ button, expectedLangParams: '-0+4' }); + + expect(findCodeSuggestionBoxText()).toContain('Suggested change From line 5 to 9'); + expect(findCodeDeleted()).toMatchInlineSnapshot(` + "<code data-line-number=\\"5\\">## Usage\u200b + </code> + <code data-line-number=\\"6\\">\u200b + </code> + <code data-line-number=\\"7\\">\`\`\`yaml\u200b + </code> + <code data-line-number=\\"8\\">foo: bar\u200b + </code> + <code data-line-number=\\"9\\">\`\`\`\u200b</code>" + `); + + expect(button.attributes('disabled')).toBe('disabled'); + }); + }); + }); }); |