Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-24 21:09:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-24 21:09:03 +0300
commitc59765a50abd6a235220fd895f5de78038c243a8 (patch)
tree6cacf61d1746e2d54149c028ecd3f187128cd7da /spec/frontend
parent4c5468b40825debc2b7bbe08b975dedd2f7f1523 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/helpers/vue_mock_directive.js20
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js71
-rw-r--r--spec/frontend/monitoring/store_utils.js21
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js43
-rw-r--r--spec/frontend/static_site_editor/services/parse_source_file_spec.js92
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js18
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() } };