diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-24 21:09:03 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-24 21:09:03 +0300 |
commit | c59765a50abd6a235220fd895f5de78038c243a8 (patch) | |
tree | 6cacf61d1746e2d54149c028ecd3f187128cd7da /spec/frontend | |
parent | 4c5468b40825debc2b7bbe08b975dedd2f7f1523 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
6 files changed, 183 insertions, 82 deletions
diff --git a/spec/frontend/helpers/vue_mock_directive.js b/spec/frontend/helpers/vue_mock_directive.js index 699fe3eab26..28d4708835d 100644 --- a/spec/frontend/helpers/vue_mock_directive.js +++ b/spec/frontend/helpers/vue_mock_directive.js @@ -2,13 +2,21 @@ export const getKey = name => `$_gl_jest_${name}`; export const getBinding = (el, name) => el[getKey(name)]; +const writeBindingToElement = (el, { name, value, arg, modifiers }) => { + el[getKey(name)] = { + value, + arg, + modifiers, + }; +}; + export const createMockDirective = () => ({ - bind(el, { name, value, arg, modifiers }) { - el[getKey(name)] = { - value, - arg, - modifiers, - }; + bind(el, binding) { + writeBindingToElement(el, binding); + }, + + update(el, binding) { + writeBindingToElement(el, binding); }, unbind(el, { name }) { diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index 5143a06ec0c..9ffaefc4550 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -16,6 +16,7 @@ import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue' import EmptyState from '~/monitoring/components/empty_state.vue'; import GroupEmptyState from '~/monitoring/components/group_empty_state.vue'; import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; +import GraphGroup from '~/monitoring/components/graph_group.vue'; import LinksSection from '~/monitoring/components/links_section.vue'; import { createStore } from '~/monitoring/stores'; import * as types from '~/monitoring/stores/mutation_types'; @@ -24,6 +25,7 @@ import { setupStoreWithDashboard, setMetricResult, setupStoreWithData, + setupStoreWithDataForPanelCount, setupStoreWithVariable, setupStoreWithLinks, } from '../store_utils'; @@ -157,6 +159,75 @@ describe('Dashboard', () => { }); }); + describe('panel containers layout', () => { + const findPanelLayoutWrapperAt = index => { + return wrapper + .find(GraphGroup) + .findAll('[data-testid="dashboard-panel-layout-wrapper"]') + .at(index); + }; + + beforeEach(() => { + createMountedWrapper({ hasMetrics: true }); + + return wrapper.vm.$nextTick(); + }); + + describe('when the graph group has an even number of panels', () => { + it('2 panels - all panel wrappers take half width of their parent', () => { + setupStoreWithDataForPanelCount(store, 2); + + wrapper.vm.$nextTick(() => { + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + }); + }); + + it('4 panels - all panel wrappers take half width of their parent', () => { + setupStoreWithDataForPanelCount(store, 4); + + wrapper.vm.$nextTick(() => { + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); + }); + }); + }); + + describe('when the graph group has an odd number of panels', () => { + it('1 panel - panel wrapper does not take half width of its parent', () => { + setupStoreWithDataForPanelCount(store, 1); + + wrapper.vm.$nextTick(() => { + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(false); + }); + }); + + it('3 panels - all panels but last take half width of their parents', () => { + setupStoreWithDataForPanelCount(store, 3); + + wrapper.vm.$nextTick(() => { + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(false); + }); + }); + + it('5 panels - all panels but last take half width of their parents', () => { + setupStoreWithDataForPanelCount(store, 5); + + wrapper.vm.$nextTick(() => { + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(4).classes('col-lg-6')).toBe(false); + }); + }); + }); + }); + describe('dashboard validation warning', () => { it('displays a warning if there are validation warnings', () => { createMountedWrapper({ hasMetrics: true }); diff --git a/spec/frontend/monitoring/store_utils.js b/spec/frontend/monitoring/store_utils.js index e2c71e41b6c..740dbaaa2e3 100644 --- a/spec/frontend/monitoring/store_utils.js +++ b/spec/frontend/monitoring/store_utils.js @@ -63,3 +63,24 @@ export const setupStoreWithData = store => { setEnvironmentData(store); }; + +export const setupStoreWithDataForPanelCount = (store, panelCount) => { + const payloadPanelGroup = metricsDashboardPayload.panel_groups[0]; + + const panelGroupCustom = { + ...payloadPanelGroup, + panels: payloadPanelGroup.panels.slice(0, panelCount), + }; + + const metricsDashboardPayloadCustom = { + ...metricsDashboardPayload, + panel_groups: [panelGroupCustom], + }; + + store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`, + metricsDashboardPayloadCustom, + ); + + setMetricResult({ store, result: metricsResult, panel: 0 }); +}; diff --git a/spec/frontend/static_site_editor/components/edit_area_spec.js b/spec/frontend/static_site_editor/components/edit_area_spec.js index 1689da52322..11c5abf1b08 100644 --- a/spec/frontend/static_site_editor/components/edit_area_spec.js +++ b/spec/frontend/static_site_editor/components/edit_area_spec.js @@ -52,7 +52,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => { it('renders rich content editor', () => { expect(findRichContentEditor().exists()).toBe(true); - expect(findRichContentEditor().props('value')).toBe(body); + expect(findRichContentEditor().props('content')).toBe(body); }); it('renders publish toolbar', () => { @@ -76,6 +76,15 @@ describe('~/static_site_editor/components/edit_area.vue', () => { return wrapper.vm.$nextTick(); }); + it('updates parsedSource with new content', () => { + const newContent = 'New content'; + const spySyncParsedSource = jest.spyOn(wrapper.vm.parsedSource, 'sync'); + + findRichContentEditor().vm.$emit('input', newContent); + + expect(spySyncParsedSource).toHaveBeenCalledWith(newContent, true); + }); + it('sets publish toolbar as saveable', () => { expect(findPublishToolbar().props('saveable')).toBe(true); }); @@ -103,35 +112,21 @@ describe('~/static_site_editor/components/edit_area.vue', () => { }); it.each` - initialMode | targetMode - ${EDITOR_TYPES.wysiwyg} | ${EDITOR_TYPES.markdown} - ${EDITOR_TYPES.markdown} | ${EDITOR_TYPES.wysiwyg} - `('sets editorMode from $initialMode to $targetMode', ({ initialMode, targetMode }) => { - setInitialMode(initialMode); - findRichContentEditor().vm.$emit('modeChange', targetMode); - - expect(wrapper.vm.editorMode).toBe(targetMode); - }); - - it.each` - syncFnName | initialMode | targetMode - ${'syncBodyToRaw'} | ${EDITOR_TYPES.wysiwyg} | ${EDITOR_TYPES.markdown} - ${'syncRawToBody'} | ${EDITOR_TYPES.markdown} | ${EDITOR_TYPES.wysiwyg} + initialMode | targetMode | resetValue + ${EDITOR_TYPES.wysiwyg} | ${EDITOR_TYPES.markdown} | ${content} + ${EDITOR_TYPES.markdown} | ${EDITOR_TYPES.wysiwyg} | ${body} `( - 'calls $syncFnName source before switching from $initialMode to $targetMode', - ({ syncFnName, initialMode, targetMode }) => { + 'sets editorMode from $initialMode to $targetMode', + ({ initialMode, targetMode, resetValue }) => { setInitialMode(initialMode); - const spySyncSource = jest.spyOn(wrapper.vm, 'syncSource'); - const spySyncParsedSource = jest.spyOn(wrapper.vm.parsedSource, syncFnName); + const resetInitialValue = jest.fn(); + findRichContentEditor().setMethods({ resetInitialValue }); findRichContentEditor().vm.$emit('modeChange', targetMode); - expect(spySyncSource).toHaveBeenCalled(); - expect(spySyncParsedSource).toHaveBeenCalled(); - - spySyncSource.mockReset(); - spySyncParsedSource.mockReset(); + expect(resetInitialValue).toHaveBeenCalledWith(resetValue); + expect(wrapper.vm.editorMode).toBe(targetMode); }, ); }); diff --git a/spec/frontend/static_site_editor/services/parse_source_file_spec.js b/spec/frontend/static_site_editor/services/parse_source_file_spec.js index a6c148dfd02..4588548e614 100644 --- a/spec/frontend/static_site_editor/services/parse_source_file_spec.js +++ b/spec/frontend/static_site_editor/services/parse_source_file_spec.js @@ -1,64 +1,58 @@ -import { - sourceContent as content, - sourceContentHeader as header, - sourceContentSpacing as spacing, - sourceContentBody as body, -} from '../mock_data'; +import { sourceContent as content, sourceContentBody as body } from '../mock_data'; import parseSourceFile from '~/static_site_editor/services/parse_source_file'; describe('parseSourceFile', () => { - const contentSimple = content; const contentComplex = [content, content, content].join(''); + const complexBody = [body, content, content].join(''); + const edit = 'and more'; + const newContent = `${content} ${edit}`; + const newContentComplex = `${contentComplex} ${edit}`; - describe('the editable shape and its expected values', () => { + describe('unmodified content', () => { it.each` - sourceContent | sourceHeader | sourceSpacing | sourceBody | desc - ${contentSimple} | ${header} | ${spacing} | ${body} | ${'extracts header'} - ${contentComplex} | ${header} | ${spacing} | ${[body, content, content].join('')} | ${'extracts body'} - `('$desc', ({ sourceContent, sourceHeader, sourceSpacing, sourceBody }) => { - const { editable } = parseSourceFile(sourceContent); - - expect(editable).toMatchObject({ - raw: sourceContent, - header: sourceHeader, - spacing: sourceSpacing, - body: sourceBody, - }); + parsedSource + ${parseSourceFile(content)} + ${parseSourceFile(contentComplex)} + `('returns false by default', ({ parsedSource }) => { + expect(parsedSource.isModified()).toBe(false); }); - it('returns the same front matter regardless of front matter duplication', () => { - const parsedSourceSimple = parseSourceFile(contentSimple); - const parsedSourceComplex = parseSourceFile(contentComplex); - - expect(parsedSourceSimple.editable.header).toBe(parsedSourceComplex.editable.header); - }); - }); - - describe('editable body to raw content default and changes', () => { it.each` - sourceContent | desc - ${contentSimple} | ${'returns false by default for both raw and body'} - ${contentComplex} | ${'returns false by default for both raw and body'} - `('$desc', ({ sourceContent }) => { - const parsedSource = parseSourceFile(sourceContent); + parsedSource | isBody | target + ${parseSourceFile(content)} | ${undefined} | ${content} + ${parseSourceFile(content)} | ${false} | ${content} + ${parseSourceFile(content)} | ${true} | ${body} + ${parseSourceFile(contentComplex)} | ${undefined} | ${contentComplex} + ${parseSourceFile(contentComplex)} | ${false} | ${contentComplex} + ${parseSourceFile(contentComplex)} | ${true} | ${complexBody} + `( + 'returns only the $target content when the `isBody` parameter argument is $isBody', + ({ parsedSource, isBody, target }) => { + expect(parsedSource.content(isBody)).toBe(target); + }, + ); + }); - expect(parsedSource.isModifiedRaw()).toBe(false); - expect(parsedSource.isModifiedBody()).toBe(false); - }); + describe('modified content', () => { + const newBody = `${body} ${edit}`; + const newComplexBody = `${complexBody} ${edit}`; it.each` - sourceContent | editableKey | syncKey | isModifiedKey | desc - ${contentSimple} | ${'body'} | ${'syncBodyToRaw'} | ${'isModifiedRaw'} | ${'returns true after modification and sync'} - ${contentSimple} | ${'raw'} | ${'syncRawToBody'} | ${'isModifiedBody'} | ${'returns true after modification and sync'} - ${contentComplex} | ${'body'} | ${'syncBodyToRaw'} | ${'isModifiedRaw'} | ${'returns true after modification and sync'} - ${contentComplex} | ${'raw'} | ${'syncRawToBody'} | ${'isModifiedBody'} | ${'returns true after modification and sync'} - `('$desc', ({ sourceContent, editableKey, syncKey, isModifiedKey }) => { - const parsedSource = parseSourceFile(sourceContent); - parsedSource.editable[editableKey] += 'Added content'; - parsedSource[syncKey](); - - expect(parsedSource[isModifiedKey]()).toBe(true); - }); + parsedSource | isModified | targetRaw | targetBody + ${parseSourceFile(content)} | ${false} | ${content} | ${body} + ${parseSourceFile(content)} | ${true} | ${newContent} | ${newBody} + ${parseSourceFile(contentComplex)} | ${false} | ${contentComplex} | ${complexBody} + ${parseSourceFile(contentComplex)} | ${true} | ${newContentComplex} | ${newComplexBody} + `( + 'returns $isModified after a $targetRaw sync', + ({ parsedSource, isModified, targetRaw, targetBody }) => { + parsedSource.sync(targetRaw); + + expect(parsedSource.isModified()).toBe(isModified); + expect(parsedSource.content()).toBe(targetRaw); + expect(parsedSource.content(true)).toBe(targetBody); + }, + ); }); }); diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js index 6091c757ed1..94f9764ad91 100644 --- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js +++ b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js @@ -25,13 +25,13 @@ jest.mock('~/vue_shared/components/rich_content_editor/services/editor_service', describe('Rich Content Editor', () => { let wrapper; - const value = '## Some Markdown'; + const content = '## Some Markdown'; const findEditor = () => wrapper.find({ ref: 'editor' }); const findAddImageModal = () => wrapper.find(AddImageModal); beforeEach(() => { wrapper = shallowMount(RichContentEditor, { - propsData: { value }, + propsData: { content }, }); }); @@ -41,7 +41,7 @@ describe('Rich Content Editor', () => { }); it('renders the correct content', () => { - expect(findEditor().props().initialValue).toBe(value); + expect(findEditor().props().initialValue).toBe(content); }); it('provides the correct editor options', () => { @@ -73,6 +73,18 @@ describe('Rich Content Editor', () => { }); }); + describe('when content is reset', () => { + it('should reset the content via setMarkdown', () => { + const newContent = 'Just the body content excluding the front matter for example'; + const mockInstance = { invoke: jest.fn() }; + wrapper.vm.$refs.editor = mockInstance; + + wrapper.vm.resetInitialValue(newContent); + + expect(mockInstance.invoke).toHaveBeenCalledWith('setMarkdown', newContent); + }); + }); + describe('when editor is loaded', () => { it('adds the CUSTOM_EVENTS.openAddImageModal custom event listener', () => { const mockEditorApi = { eventManager: { addEventType: jest.fn(), listen: jest.fn() } }; |