diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js | 156 |
1 files changed, 13 insertions, 143 deletions
diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js index 5461d38599d..1c75442b4a8 100644 --- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js +++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js @@ -1,70 +1,27 @@ -import hljs from 'highlight.js/lib/core'; -import Vue from 'vue'; -import VueRouter from 'vue-router'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue'; -import { registerPlugins } from '~/vue_shared/components/source_viewer/plugins/index'; import Chunk from '~/vue_shared/components/source_viewer/components/chunk.vue'; -import { - EVENT_ACTION, - EVENT_LABEL_VIEWER, - EVENT_LABEL_FALLBACK, - ROUGE_TO_HLJS_LANGUAGE_MAP, - LINES_PER_CHUNK, -} from '~/vue_shared/components/source_viewer/constants'; -import waitForPromises from 'helpers/wait_for_promises'; -import LineHighlighter from '~/blob/line_highlighter'; -import eventHub from '~/notes/event_hub'; +import { EVENT_ACTION, EVENT_LABEL_VIEWER } from '~/vue_shared/components/source_viewer/constants'; import Tracking from '~/tracking'; +import addBlobLinksTracking from '~/blob/blob_links_tracking'; +import { BLOB_DATA_MOCK, CHUNK_1, CHUNK_2, LANGUAGE_MOCK } from './mock_data'; -jest.mock('~/blob/line_highlighter'); -jest.mock('highlight.js/lib/core'); -jest.mock('~/vue_shared/components/source_viewer/plugins/index'); -Vue.use(VueRouter); -const router = new VueRouter(); - -const generateContent = (content, totalLines = 1, delimiter = '\n') => { - let generatedContent = ''; - for (let i = 0; i < totalLines; i += 1) { - generatedContent += `Line: ${i + 1} = ${content}${delimiter}`; - } - return generatedContent; -}; - -const execImmediately = (callback) => callback(); +jest.mock('~/blob/blob_links_tracking'); describe('Source Viewer component', () => { let wrapper; - const language = 'docker'; - const mappedLanguage = ROUGE_TO_HLJS_LANGUAGE_MAP[language]; - const chunk1 = generateContent('// Some source code 1', 70); - const chunk2 = generateContent('// Some source code 2', 70); - const chunk3 = generateContent('// Some source code 3', 70, '\r\n'); - const chunk3Result = generateContent('// Some source code 3', 70, '\n'); - const content = chunk1 + chunk2 + chunk3; - const path = 'some/path.js'; - const blamePath = 'some/blame/path.js'; - const fileType = 'javascript'; - const DEFAULT_BLOB_DATA = { language, rawTextBlob: content, path, blamePath, fileType }; - const highlightedContent = `<span data-testid='test-highlighted' id='LC1'>${content}</span><span id='LC2'></span>`; + const CHUNKS_MOCK = [CHUNK_1, CHUNK_2]; - const createComponent = async (blob = {}) => { + const createComponent = () => { wrapper = shallowMountExtended(SourceViewer, { - router, - propsData: { blob: { ...DEFAULT_BLOB_DATA, ...blob } }, + propsData: { blob: BLOB_DATA_MOCK, chunks: CHUNKS_MOCK }, }); - await waitForPromises(); }; const findChunks = () => wrapper.findAllComponents(Chunk); beforeEach(() => { - hljs.highlight.mockImplementation(() => ({ value: highlightedContent })); - hljs.highlightAuto.mockImplementation(() => ({ value: highlightedContent })); - jest.spyOn(window, 'requestIdleCallback').mockImplementation(execImmediately); - jest.spyOn(eventHub, '$emit'); jest.spyOn(Tracking, 'event'); - return createComponent(); }); @@ -72,106 +29,19 @@ describe('Source Viewer component', () => { describe('event tracking', () => { it('fires a tracking event when the component is created', () => { - const eventData = { label: EVENT_LABEL_VIEWER, property: language }; + const eventData = { label: EVENT_LABEL_VIEWER, property: LANGUAGE_MOCK }; expect(Tracking.event).toHaveBeenCalledWith(undefined, EVENT_ACTION, eventData); }); - it('does not emit an error event when the language is supported', () => { - expect(wrapper.emitted('error')).toBeUndefined(); - }); - - it('fires a tracking event and emits an error when the language is not supported', () => { - const unsupportedLanguage = 'apex'; - const eventData = { label: EVENT_LABEL_FALLBACK, property: unsupportedLanguage }; - createComponent({ language: unsupportedLanguage }); - - expect(Tracking.event).toHaveBeenCalledWith(undefined, EVENT_ACTION, eventData); - expect(wrapper.emitted('error')).toHaveLength(1); - }); - }); - - describe('legacy fallbacks', () => { - it('tracks a fallback event and emits an error when viewing python files', () => { - const fallbackLanguage = 'python'; - const eventData = { label: EVENT_LABEL_FALLBACK, property: fallbackLanguage }; - createComponent({ language: fallbackLanguage }); - - expect(Tracking.event).toHaveBeenCalledWith(undefined, EVENT_ACTION, eventData); - expect(wrapper.emitted('error')).toHaveLength(1); - }); - }); - - describe('highlight.js', () => { - beforeEach(() => createComponent({ language: mappedLanguage })); - - it('registers our plugins for Highlight.js', () => { - expect(registerPlugins).toHaveBeenCalledWith(hljs, fileType, content); - }); - - it('registers the language definition', async () => { - const languageDefinition = await import(`highlight.js/lib/languages/${mappedLanguage}`); - - expect(hljs.registerLanguage).toHaveBeenCalledWith( - mappedLanguage, - languageDefinition.default, - ); - }); - - it('registers json language definition if fileType is package_json', async () => { - await createComponent({ language: 'json', fileType: 'package_json' }); - const languageDefinition = await import(`highlight.js/lib/languages/json`); - - expect(hljs.registerLanguage).toHaveBeenCalledWith('json', languageDefinition.default); - }); - - it('correctly maps languages starting with uppercase', async () => { - await createComponent({ language: 'Ruby' }); - const languageDefinition = await import(`highlight.js/lib/languages/ruby`); - - expect(hljs.registerLanguage).toHaveBeenCalledWith('ruby', languageDefinition.default); - }); - - it('highlights the first chunk', () => { - expect(hljs.highlight).toHaveBeenCalledWith(chunk1.trim(), { language: mappedLanguage }); - expect(findChunks().at(0).props('isFirstChunk')).toBe(true); - }); - - describe('auto-detects if a language cannot be loaded', () => { - beforeEach(() => createComponent({ language: 'some_unknown_language' })); - - it('highlights the content with auto-detection', () => { - expect(hljs.highlightAuto).toHaveBeenCalledWith(chunk1.trim()); - }); + it('adds blob links tracking', () => { + expect(addBlobLinksTracking).toHaveBeenCalled(); }); }); describe('rendering', () => { - it.each` - chunkIndex | chunkContent | totalChunks - ${0} | ${chunk1} | ${0} - ${1} | ${chunk2} | ${3} - ${2} | ${chunk3Result} | ${3} - `('renders chunk $chunkIndex', ({ chunkIndex, chunkContent, totalChunks }) => { - const chunk = findChunks().at(chunkIndex); - - expect(chunk.props('content')).toContain(chunkContent.trim()); - - expect(chunk.props()).toMatchObject({ - totalLines: LINES_PER_CHUNK, - startingFrom: LINES_PER_CHUNK * chunkIndex, - totalChunks, - }); - }); - - it('emits showBlobInteractionZones on the eventHub when chunk appears', () => { - findChunks().at(0).vm.$emit('appear'); - expect(eventHub.$emit).toHaveBeenCalledWith('showBlobInteractionZones', path); - }); - }); - - describe('LineHighlighter', () => { - it('instantiates the lineHighlighter class', async () => { - expect(LineHighlighter).toHaveBeenCalledWith({ scrollBehavior: 'auto' }); + it('renders a Chunk component for each chunk', () => { + expect(findChunks().at(0).props()).toMatchObject(CHUNK_1); + expect(findChunks().at(1).props()).toMatchObject(CHUNK_2); }); }); }); |