diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-31 06:10:52 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-31 06:10:52 +0300 |
commit | 2f3007bc70786204d82739e0775ad0f6707ddbc1 (patch) | |
tree | c4597f5283fca092d3e903cc43a508571fd96e24 /spec/frontend | |
parent | a3df40b2c393e1540d237938240ee12d2774cd13 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r-- | spec/frontend/drawio/drawio_editor_spec.js | 5 | ||||
-rw-r--r-- | spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js | 69 |
2 files changed, 61 insertions, 13 deletions
diff --git a/spec/frontend/drawio/drawio_editor_spec.js b/spec/frontend/drawio/drawio_editor_spec.js index 5a77b9d4689..0b863edc13b 100644 --- a/spec/frontend/drawio/drawio_editor_spec.js +++ b/spec/frontend/drawio/drawio_editor_spec.js @@ -5,6 +5,7 @@ import { DRAWIO_IFRAME_TIMEOUT, DIAGRAM_MAX_SIZE, } from '~/drawio/constants'; +import { base64EncodeUnicode } from '~/lib/utils/text_utility'; import { createAlert, VARIANT_SUCCESS } from '~/alert'; const DRAWIO_EDITOR_URL = @@ -19,8 +20,8 @@ describe('drawio/drawio_editor', () => { let editorFacade; let drawioIFrameReceivedMessages; const diagramURL = `${window.location.origin}/uploads/diagram.drawio.svg`; - const testSvg = '<svg></svg>'; - const testEncodedSvg = `data:image/svg+xml;base64,${btoa(testSvg)}`; + const testSvg = '<svg>😀</svg>'; + const testEncodedSvg = `data:image/svg+xml;base64,${base64EncodeUnicode(testSvg)}`; const filename = 'diagram.drawio.svg'; const findDrawioIframe = () => document.getElementById(DRAWIO_FRAME_ID); diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js index fc8155bd381..6a3337aa046 100644 --- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js +++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js @@ -3,6 +3,10 @@ import { shallowMount } from '@vue/test-utils'; import { handleBlobRichViewer } from '~/blob/viewer'; import RichViewer from '~/vue_shared/components/blob_viewers/rich_viewer.vue'; import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue'; +import { + MARKUP_FILE_TYPE, + CONTENT_LOADED_EVENT, +} from '~/vue_shared/components/blob_viewers/constants'; import { handleLocationHash } from '~/lib/utils/common_utils'; jest.mock('~/blob/viewer'); @@ -10,10 +14,10 @@ jest.mock('~/lib/utils/common_utils'); describe('Blob Rich Viewer component', () => { let wrapper; - const content = '<h1 id="markdown">Foo Bar</h1>'; + const dummyContent = '<h1 id="markdown">Foo Bar</h1>'; const defaultType = 'markdown'; - function createComponent(type = defaultType, richViewer) { + function createComponent(type = defaultType, richViewer, content = dummyContent) { wrapper = shallowMount(RichViewer, { propsData: { richViewer, @@ -23,26 +27,69 @@ describe('Blob Rich Viewer component', () => { }); } - beforeEach(() => { - const execImmediately = (callback) => callback(); - jest.spyOn(window, 'requestIdleCallback').mockImplementation(execImmediately); + beforeEach(() => createComponent()); - createComponent(); - }); + describe('Markdown content', () => { + const generateDummyContent = (contentLength) => { + let generatedContent = ''; + for (let i = 0; i < contentLength; i += 1) { + generatedContent += `<span>Line: ${i + 1}</span>\n`; + } + + generatedContent += '<img src="x" onerror="alert(`XSS`)">'; // for testing against XSS + return `<div class="js-markup-content">${generatedContent}</div>`; + }; + + describe('Large file', () => { + const content = generateDummyContent(50); + beforeEach(() => createComponent(MARKUP_FILE_TYPE, null, content)); + + it('renders the top of the file immediately and does not emit a content loaded event', () => { + expect(wrapper.text()).toContain('Line: 10'); + expect(wrapper.text()).not.toContain('Line: 50'); + expect(wrapper.emitted(CONTENT_LOADED_EVENT)).toBeUndefined(); + }); + + it('renders the rest of the file later and emits a content loaded event', () => { + jest.runAllTimers(); + + expect(wrapper.text()).toContain('Line: 10'); + expect(wrapper.text()).toContain('Line: 50'); + expect(wrapper.emitted(CONTENT_LOADED_EVENT)).toHaveLength(1); + }); - it('listens to requestIdleCallback', () => { - expect(window.requestIdleCallback).toHaveBeenCalled(); + it('sanitizes the content', () => { + jest.runAllTimers(); + + expect(wrapper.html()).toContain('<img src="x">'); + }); + }); + + describe('Small file', () => { + const content = generateDummyContent(5); + beforeEach(() => createComponent(MARKUP_FILE_TYPE, null, content)); + + it('renders the entire file immediately and emits a content loaded event', () => { + expect(wrapper.text()).toContain('Line: 5'); + expect(wrapper.emitted(CONTENT_LOADED_EVENT)).toHaveLength(1); + }); + + it('sanitizes the content', () => { + expect(wrapper.html()).toContain('<img src="x">'); + }); + }); }); it('renders the passed content without transformations', () => { - expect(wrapper.html()).toContain(content); + expect(wrapper.html()).toContain(dummyContent); }); - it('renders the richViewer if one is present', async () => { + it('renders the richViewer if one is present and emits a content loaded event', async () => { const richViewer = '<div class="js-pdf-viewer"></div>'; createComponent('pdf', richViewer); await nextTick(); expect(wrapper.html()).toContain(richViewer); + expect(wrapper.emitted(CONTENT_LOADED_EVENT)).toHaveLength(1); }); it('queries for advanced viewer', () => { |