diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-29 03:10:57 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-29 03:10:57 +0300 |
commit | e064cd3f07fbc239fb46106a1eaf71379ea01603 (patch) | |
tree | eb1f478d6f6d5e73bc50639f7af7a99b4d34a392 /spec/frontend/behaviors | |
parent | 9037472904908109f5622a8a1e808c6225eced56 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/behaviors')
-rw-r--r-- | spec/frontend/behaviors/components/json_table_spec.js | 162 | ||||
-rw-r--r-- | spec/frontend/behaviors/markdown/render_json_table_spec.js | 119 |
2 files changed, 281 insertions, 0 deletions
diff --git a/spec/frontend/behaviors/components/json_table_spec.js b/spec/frontend/behaviors/components/json_table_spec.js new file mode 100644 index 00000000000..42b4a051d4d --- /dev/null +++ b/spec/frontend/behaviors/components/json_table_spec.js @@ -0,0 +1,162 @@ +import { GlTable, GlFormInput } from '@gitlab/ui'; +import { nextTick } from 'vue'; +import { merge } from 'lodash'; +import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper'; +import { stubComponent, RENDER_ALL_SLOTS_TEMPLATE } from 'helpers/stub_component'; +import JSONTable from '~/behaviors/components/json_table.vue'; + +const TEST_FIELDS = [ + 'A', + { + key: 'B', + label: 'Second', + sortable: true, + other: 'foo', + }, + { + key: 'C', + label: 'Third', + }, + 'D', +]; +const TEST_ITEMS = [ + { A: 1, B: 'lorem', C: 2, D: null, E: 'dne' }, + { A: 2, B: 'ipsum', C: 2, D: null, E: 'dne' }, + { A: 3, B: 'dolar', C: 2, D: null, E: 'dne' }, +]; + +describe('behaviors/components/json_table', () => { + let wrapper; + + const buildWrapper = ({ + fields = [], + items = [], + filter = undefined, + caption = undefined, + } = {}) => { + wrapper = shallowMountExtended(JSONTable, { + propsData: { + fields, + items, + hasFilter: filter, + caption, + }, + stubs: { + GlTable: merge(stubComponent(GlTable), { + props: { + fields: { + type: Array, + required: true, + }, + items: { + type: Array, + required: true, + }, + }, + template: RENDER_ALL_SLOTS_TEMPLATE, + }), + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findTable = () => wrapper.findComponent(GlTable); + const findTableCaption = () => wrapper.findByTestId('slot-table-caption'); + const findFilterInput = () => wrapper.findComponent(GlFormInput); + + describe('default', () => { + beforeEach(() => { + buildWrapper(); + }); + + it('renders gltable', () => { + expect(findTable().props()).toEqual({ + fields: [], + items: [], + }); + expect(findTable().attributes()).toMatchObject({ + filter: '', + 'show-empty': '', + }); + }); + + it('does not render filter input', () => { + expect(findFilterInput().exists()).toBe(false); + }); + + it('renders caption', () => { + expect(findTableCaption().text()).toBe('Generated with JSON data'); + }); + }); + + describe('with filter', () => { + beforeEach(() => { + buildWrapper({ + filter: true, + }); + }); + + it('renders filter input', () => { + expect(findFilterInput().attributes()).toMatchObject({ + value: '', + placeholder: 'Type to search', + }); + }); + + it('when input is changed, updates table filter', async () => { + findFilterInput().vm.$emit('input', 'New value!'); + + await nextTick(); + + expect(findTable().attributes('filter')).toBe('New value!'); + }); + }); + + describe('with fields', () => { + beforeEach(() => { + buildWrapper({ + fields: TEST_FIELDS, + items: TEST_ITEMS, + }); + }); + + it('passes cleaned fields and items to table', () => { + expect(findTable().props()).toEqual({ + fields: [ + 'A', + { + key: 'B', + label: 'Second', + sortable: true, + }, + { + key: 'C', + label: 'Third', + sortable: false, + }, + 'D', + ], + items: TEST_ITEMS, + }); + }); + }); + + describe('with full mount', () => { + beforeEach(() => { + wrapper = mountExtended(JSONTable, { + propsData: { + fields: [], + items: [], + }, + }); + }); + + // We want to make sure all the props are passed down nicely in integration + it('renders table without errors', () => { + expect(findTable().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/behaviors/markdown/render_json_table_spec.js b/spec/frontend/behaviors/markdown/render_json_table_spec.js new file mode 100644 index 00000000000..488492479f3 --- /dev/null +++ b/spec/frontend/behaviors/markdown/render_json_table_spec.js @@ -0,0 +1,119 @@ +import { nextTick } from 'vue'; +import { renderJSONTable } from '~/behaviors/markdown/render_json_table'; + +describe('behaviors/markdown/render_json_table', () => { + let element; + + const TEST_DATA = { + fields: [ + { label: 'Field 1', key: 'a' }, + { label: 'F 2', key: 'b' }, + { label: 'F 3', key: 'c' }, + ], + items: [ + { + a: '1', + b: 'b', + c: 'c', + }, + { + a: '2', + b: 'd', + c: 'e', + }, + ], + }; + const TEST_LABELS = TEST_DATA.fields.map((x) => x.label); + + const tableAsData = (table) => ({ + head: Array.from(table.querySelectorAll('thead th')).map((td) => td.textContent), + body: Array.from(table.querySelectorAll('tbody > tr')).map((tr) => + Array.from(tr.querySelectorAll('td')).map((x) => x.textContent), + ), + }); + + const createTestSubject = async (json) => { + if (element) { + throw new Error('element has already been initialized'); + } + + const parent = document.createElement('div'); + const pre = document.createElement('pre'); + + pre.textContent = json; + parent.appendChild(pre); + + document.body.appendChild(parent); + renderJSONTable([parent]); + + element = parent; + + jest.runAllTimers(); + + await nextTick(); + }; + + const findPres = () => document.querySelectorAll('pre'); + const findTables = () => document.querySelectorAll('table'); + const findAlerts = () => document.querySelectorAll('.gl-alert'); + const findInputs = () => document.querySelectorAll('.gl-form-input'); + + afterEach(() => { + document.body.innerHTML = ''; + element = null; + }); + + describe('default', () => { + beforeEach(async () => { + await createTestSubject(JSON.stringify(TEST_DATA, null, 2)); + }); + + it('removes pre', () => { + expect(findPres()).toHaveLength(0); + }); + + it('replaces pre with table', () => { + const tables = findTables(); + + expect(tables).toHaveLength(1); + expect(tableAsData(tables[0])).toEqual({ + head: TEST_LABELS, + body: [ + ['1', 'b', 'c'], + ['2', 'd', 'e'], + ], + }); + }); + + it('does not show filter', () => { + expect(findInputs()).toHaveLength(0); + }); + }); + + describe('with invalid json', () => { + beforeEach(() => { + createTestSubject('funky but not json'); + }); + + it('preserves pre', () => { + expect(findPres()).toHaveLength(1); + }); + + it('shows alert', () => { + const alerts = findAlerts(); + + expect(alerts).toHaveLength(1); + expect(alerts[0].textContent).toMatchInterpolatedText('Unable to parse JSON'); + }); + }); + + describe('with filter set', () => { + beforeEach(() => { + createTestSubject(JSON.stringify({ ...TEST_DATA, filter: true })); + }); + + it('shows filter', () => { + expect(findInputs()).toHaveLength(1); + }); + }); +}); |