diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-14 21:12:38 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-14 21:12:38 +0300 |
commit | 283c7bb302510ed1fc55f0d333c484ce7fa781fd (patch) | |
tree | adbb03e34cc91f339395f6417502c075ee84b8bb /spec/frontend/vue_shared/components/source_viewer | |
parent | a2b7b398c7855bccee5d2f0f9a021b2efea0838e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/vue_shared/components/source_viewer')
4 files changed, 182 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/source_viewer/components/__snapshots__/chunk_spec.js.snap b/spec/frontend/vue_shared/components/source_viewer/components/__snapshots__/chunk_spec.js.snap new file mode 100644 index 00000000000..26c9a6f8d5a --- /dev/null +++ b/spec/frontend/vue_shared/components/source_viewer/components/__snapshots__/chunk_spec.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Chunk component rendering isHighlighted is true renders line numbers 1`] = ` +<div + class="gl-p-0! gl-z-index-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers" + data-testid="line-numbers" +> + <a + class="gl-user-select-none gl-shadow-none! file-line-blame" + href="some/blame/path.js#L71" + /> + + <a + class="gl-user-select-none gl-shadow-none! file-line-num" + data-line-number="71" + href="#L71" + id="L71" + > + + 71 + + </a> +</div> +`; diff --git a/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js b/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js new file mode 100644 index 00000000000..95ef11d776a --- /dev/null +++ b/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js @@ -0,0 +1,87 @@ +import { nextTick } from 'vue'; +import { GlIntersectionObserver } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import Chunk from '~/vue_shared/components/source_viewer/components/chunk.vue'; +import { CHUNK_1, CHUNK_2 } from '../mock_data'; + +describe('Chunk component', () => { + let wrapper; + let idleCallbackSpy; + + const createComponent = (props = {}) => { + wrapper = shallowMountExtended(Chunk, { + propsData: { ...CHUNK_1, ...props }, + provide: { glFeatures: { fileLineBlame: true } }, + }); + }; + + const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver); + const findLineNumbers = () => wrapper.findAllByTestId('line-numbers'); + const findContent = () => wrapper.findByTestId('content'); + + beforeEach(() => { + idleCallbackSpy = jest.spyOn(window, 'requestIdleCallback').mockImplementation((fn) => fn()); + createComponent(); + }); + + afterEach(() => wrapper.destroy()); + + describe('Intersection observer', () => { + it('renders an Intersection observer component', () => { + expect(findIntersectionObserver().exists()).toBe(true); + }); + + it('renders highlighted content if appear event is emitted', async () => { + createComponent({ chunkIndex: 1, isHighlighted: false }); + findIntersectionObserver().vm.$emit('appear'); + + await nextTick(); + + expect(findContent().exists()).toBe(true); + }); + }); + + describe('rendering', () => { + it('does not register window.requestIdleCallback for the first chunk, renders content immediately', () => { + jest.clearAllMocks(); + + expect(window.requestIdleCallback).not.toHaveBeenCalled(); + expect(findContent().text()).toBe(CHUNK_1.highlightedContent); + }); + + it('does not render content if browser is not in idle state', () => { + idleCallbackSpy.mockRestore(); + createComponent({ chunkIndex: 1, ...CHUNK_2 }); + + expect(findLineNumbers()).toHaveLength(0); + expect(findContent().exists()).toBe(false); + }); + + describe('isHighlighted is false', () => { + beforeEach(() => createComponent(CHUNK_2)); + + it('does not render line numbers', () => { + expect(findLineNumbers()).toHaveLength(0); + }); + + it('renders raw content', () => { + expect(findContent().text()).toBe(CHUNK_2.rawContent); + }); + }); + + describe('isHighlighted is true', () => { + beforeEach(() => createComponent({ ...CHUNK_2, isHighlighted: true })); + + it('renders line numbers', () => { + expect(findLineNumbers()).toHaveLength(CHUNK_2.totalLines); + + // Opted for a snapshot test here since the output is simple and verifies native HTML elements + expect(findLineNumbers().at(0).element).toMatchSnapshot(); + }); + + it('renders highlighted content', () => { + expect(findContent().text()).toBe(CHUNK_2.highlightedContent); + }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/source_viewer/mock_data.js b/spec/frontend/vue_shared/components/source_viewer/mock_data.js new file mode 100644 index 00000000000..f35e9607d5c --- /dev/null +++ b/spec/frontend/vue_shared/components/source_viewer/mock_data.js @@ -0,0 +1,24 @@ +const path = 'some/path.js'; +const blamePath = 'some/blame/path.js'; + +export const LANGUAGE_MOCK = 'docker'; + +export const BLOB_DATA_MOCK = { language: LANGUAGE_MOCK, path, blamePath }; + +export const CHUNK_1 = { + isHighlighted: true, + rawContent: 'chunk 1 raw', + highlightedContent: 'chunk 1 highlighted', + totalLines: 70, + startingFrom: 0, + blamePath, +}; + +export const CHUNK_2 = { + isHighlighted: false, + rawContent: 'chunk 2 raw', + highlightedContent: 'chunk 2 highlighted', + totalLines: 40, + startingFrom: 70, + blamePath, +}; 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 new file mode 100644 index 00000000000..1c75442b4a8 --- /dev/null +++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js @@ -0,0 +1,47 @@ +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue'; +import Chunk from '~/vue_shared/components/source_viewer/components/chunk.vue'; +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/blob_links_tracking'); + +describe('Source Viewer component', () => { + let wrapper; + const CHUNKS_MOCK = [CHUNK_1, CHUNK_2]; + + const createComponent = () => { + wrapper = shallowMountExtended(SourceViewer, { + propsData: { blob: BLOB_DATA_MOCK, chunks: CHUNKS_MOCK }, + }); + }; + + const findChunks = () => wrapper.findAllComponents(Chunk); + + beforeEach(() => { + jest.spyOn(Tracking, 'event'); + return createComponent(); + }); + + afterEach(() => wrapper.destroy()); + + describe('event tracking', () => { + it('fires a tracking event when the component is created', () => { + const eventData = { label: EVENT_LABEL_VIEWER, property: LANGUAGE_MOCK }; + expect(Tracking.event).toHaveBeenCalledWith(undefined, EVENT_ACTION, eventData); + }); + + it('adds blob links tracking', () => { + expect(addBlobLinksTracking).toHaveBeenCalled(); + }); + }); + + describe('rendering', () => { + it('renders a Chunk component for each chunk', () => { + expect(findChunks().at(0).props()).toMatchObject(CHUNK_1); + expect(findChunks().at(1).props()).toMatchObject(CHUNK_2); + }); + }); +}); |