@gitlab/ui 46.1.0 → 47.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/base/breadcrumb/breadcrumb.js +1 -1
  3. package/dist/components/base/datepicker/datepicker.js +17 -11
  4. package/dist/components/base/dropdown/dropdown.js +22 -5
  5. package/dist/components/base/filtered_search/filtered_search.js +1 -1
  6. package/dist/components/base/form/form_checkbox_tree/form_checkbox_tree.js +1 -1
  7. package/dist/components/base/form/form_checkbox_tree/models/tree.js +0 -1
  8. package/dist/components/base/infinite_scroll/infinite_scroll.js +17 -26
  9. package/dist/components/base/pagination/pagination.js +3 -1
  10. package/dist/components/base/search_box_by_click/search_box_by_click.js +1 -1
  11. package/dist/components/base/sorting/sorting_item.js +9 -2
  12. package/dist/components/charts/column/column.js +0 -1
  13. package/dist/components/utilities/intersperse/intersperse.js +1 -1
  14. package/dist/utility_classes.css +1 -1
  15. package/dist/utility_classes.css.map +1 -1
  16. package/package.json +7 -7
  17. package/src/components/base/alert/alert.spec.js +3 -3
  18. package/src/components/base/breadcrumb/breadcrumb.spec.js +0 -2
  19. package/src/components/base/breadcrumb/breadcrumb.vue +1 -1
  20. package/src/components/base/datepicker/datepicker.vue +18 -11
  21. package/src/components/base/daterange_picker/daterange_picker.spec.js +1 -3
  22. package/src/components/base/dropdown/dropdown.spec.js +37 -0
  23. package/src/components/base/dropdown/dropdown.stories.js +24 -1
  24. package/src/components/base/dropdown/dropdown.vue +22 -3
  25. package/src/components/base/filtered_search/filtered_search.vue +29 -30
  26. package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.vue +1 -1
  27. package/src/components/base/form/form_checkbox_tree/models/tree.js +0 -1
  28. package/src/components/base/form/form_group/form_group.spec.js +1 -0
  29. package/src/components/base/infinite_scroll/infinite_scroll.vue +15 -24
  30. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +1 -0
  31. package/src/components/base/new_dropdowns/listbox/listbox.spec.js +1 -0
  32. package/src/components/base/new_dropdowns/listbox/listbox.stories.js +64 -99
  33. package/src/components/base/pagination/pagination.spec.js +1 -1
  34. package/src/components/base/pagination/pagination.vue +6 -4
  35. package/src/components/base/search_box_by_click/search_box_by_click.spec.js +6 -5
  36. package/src/components/base/search_box_by_click/search_box_by_click.vue +1 -1
  37. package/src/components/base/sorting/sorting.spec.js +0 -17
  38. package/src/components/base/sorting/sorting_item.spec.js +3 -1
  39. package/src/components/base/sorting/sorting_item.vue +9 -10
  40. package/src/components/base/tabs/tab/tab.spec.js +2 -3
  41. package/src/components/base/tabs/tabs/scrollable_tabs.spec.js +3 -1
  42. package/src/components/charts/column/column.vue +1 -1
  43. package/src/components/utilities/intersection_observer/intersection_observer.spec.js +1 -1
  44. package/src/components/utilities/intersperse/intersperse.vue +1 -1
  45. package/src/components/utilities/sprintf/sprintf.spec.js +1 -5
  46. package/src/components/utilities/truncate/truncate.spec.js +4 -5
  47. package/src/directives/hover_load/hover_load.spec.js +1 -1
  48. package/src/directives/safe_link/safe_link.spec.js +11 -13
  49. package/src/scss/utilities.scss +2 -12
  50. package/src/scss/utility-mixins/spacing.scss +1 -8
@@ -61,37 +61,45 @@ const generateProps = ({
61
61
  startOpened,
62
62
  });
63
63
 
64
+ const makeBindings = (overrides = {}) =>
65
+ Object.entries({
66
+ ':items': 'items',
67
+ ':category': 'category',
68
+ ':variant': 'variant',
69
+ ':size': 'size',
70
+ ':disabled': 'disabled',
71
+ ':loading': 'loading',
72
+ ':searchable': 'searchable',
73
+ ':searching': 'searching',
74
+ ':no-results-text': 'noResultsText',
75
+ ':no-caret': 'noCaret',
76
+ ':right': 'right',
77
+ ':toggle-text': 'toggleText',
78
+ ':text-sr-only': 'textSrOnly',
79
+ ':icon': 'icon',
80
+ ':multiple': 'multiple',
81
+ ':is-check-centered': 'isCheckCentered',
82
+ ':toggle-aria-labelled-by': 'toggleAriaLabelledBy',
83
+ ':list-aria-labelled-by': 'listAriaLabelledBy',
84
+ ...overrides,
85
+ })
86
+ .map(([key, value]) => `${key}="${value}"`)
87
+ .join('\n');
88
+
64
89
  function openListbox(component) {
65
90
  component.$nextTick(() => {
66
91
  component.$refs.listbox.open();
67
92
  });
68
93
  }
69
94
 
70
- const template = (content, label = '') => `
95
+ const template = (content, { label = '', bindingOverrides = {} } = {}) => `
71
96
  <div>
72
97
  ${label}
73
- <br/>
98
+ ${label && '<br/>'}
74
99
  <gl-listbox
75
100
  ref="listbox"
76
101
  v-model="selected"
77
- :items="items"
78
- :category="category"
79
- :variant="variant"
80
- :size="size"
81
- :disabled="disabled"
82
- :loading="loading"
83
- :searchable="searchable"
84
- :searching="searching"
85
- :no-results-text="noResultsText"
86
- :no-caret="noCaret"
87
- :right="right"
88
- :toggle-text="toggleText"
89
- :text-sr-only="textSrOnly"
90
- :icon="icon"
91
- :multiple="multiple"
92
- :is-check-centered="isCheckCentered"
93
- :toggle-aria-labelled-by="toggleAriaLabelledBy"
94
- :list-aria-labelled-by="listAriaLabelledBy"
102
+ ${makeBindings(bindingOverrides)}
95
103
  >
96
104
  ${content}
97
105
  </gl-listbox>
@@ -113,7 +121,9 @@ export const Default = (args, { argTypes }) => ({
113
121
  openListbox(this);
114
122
  }
115
123
  },
116
- template: template('', `<span class="gl-my-0" id="listbox-label">Select a department</span>`),
124
+ template: template('', {
125
+ label: `<span class="gl-my-0" id="listbox-label">Select a department</span>`,
126
+ }),
117
127
  });
118
128
  Default.args = generateProps({ toggleAriaLabelledBy: 'listbox-label' });
119
129
  Default.decorators = [makeContainer({ height: '370px' })];
@@ -181,36 +191,14 @@ export const CustomListItem = (args, { argTypes }) => ({
181
191
  }
182
192
  },
183
193
  computed: {
184
- headerText() {
194
+ customToggleText() {
185
195
  return this.selected.length !== 1
186
196
  ? `${this.selected.length} assignees`
187
197
  : this.items.find(({ value }) => value === this.selected[0]).text;
188
198
  },
189
199
  },
190
- template: `
191
- <gl-listbox
192
- ref="listbox"
193
- v-model="selected"
194
- :items="items"
195
- :category="category"
196
- :variant="variant"
197
- :size="size"
198
- :disabled="disabled"
199
- :loading="loading"
200
- :searchable="searchable"
201
- :searching="searching"
202
- :no-results-text="noResultsText"
203
- :no-caret="noCaret"
204
- :right="right"
205
- :toggle-text="headerText"
206
- :text-sr-only="textSrOnly"
207
- :icon="icon"
208
- :multiple="multiple"
209
- :is-check-centered="isCheckCentered"
210
- :toggle-aria-labelled-by="toggleAriaLabelledBy"
211
- :list-aria-labelled-by="listAriaLabelledBy"
212
- >
213
- <template #list-item="{ item }">
200
+ template: template(
201
+ `<template #list-item="{ item }">
214
202
  <span class="gl-display-flex gl-align-items-center">
215
203
  <gl-avatar :size="32" class-="gl-mr-3"/>
216
204
  <span class="gl-display-flex gl-flex-direction-column">
@@ -219,8 +207,13 @@ export const CustomListItem = (args, { argTypes }) => ({
219
207
  </span>
220
208
  </span>
221
209
  </template>
222
- </gl-listbox>
223
210
  `,
211
+ {
212
+ bindingOverrides: {
213
+ ':toggle-text': 'customToggleText',
214
+ },
215
+ }
216
+ ),
224
217
  });
225
218
 
226
219
  CustomListItem.args = generateProps({
@@ -364,31 +357,8 @@ export const Searchable = (args, { argTypes }) => ({
364
357
  return this.filteredItems.length === 1 ? '1 result' : `${this.filteredItems.length} results`;
365
358
  },
366
359
  },
367
- template: `
368
- <gl-listbox
369
- ref="listbox"
370
- v-model="selected"
371
- :items="filteredItems"
372
- :category="category"
373
- :variant="variant"
374
- :size="size"
375
- :disabled="disabled"
376
- :loading="loading"
377
- :no-caret="noCaret"
378
- :right="right"
379
- :toggle-text="customToggleText"
380
- :text-sr-only="textSrOnly"
381
- :icon="icon"
382
- :multiple="multiple"
383
- :is-check-centered="isCheckCentered"
384
- :toggle-aria-labelled-by="toggleAriaLabelledBy"
385
- :list-aria-labelled-by="headerId"
386
- :searchable="searchable"
387
- :searching="searchInProgress"
388
- :no-results-text="noResultsText"
389
- @search="filterList"
390
- >
391
- <template #header>
360
+ template: template(
361
+ `<template #header>
392
362
  <p :id="headerId"
393
363
  class="gl-font-weight-bold gl-font-sm gl-m-0 gl-text-center gl-py-2 gl-border-1 gl-border-b-solid gl-border-gray-200">
394
364
  Assign to department</p>
@@ -396,8 +366,17 @@ export const Searchable = (args, { argTypes }) => ({
396
366
  <template #search-summary-sr-only>
397
367
  {{ numberOfSearchResults }}
398
368
  </template>
399
- </gl-listbox>
400
369
  `,
370
+ {
371
+ bindingOverrides: {
372
+ ':items': 'filteredItems',
373
+ ':list-aria-labelled-by': 'headerId',
374
+ ':toggle-text': 'customToggleText',
375
+ ':searching': 'searchInProgress',
376
+ '@search': 'filterList',
377
+ },
378
+ }
379
+ ),
401
380
  });
402
381
  Searchable.args = generateProps({ searchable: true });
403
382
  Searchable.decorators = [makeContainer({ height: '370px' })];
@@ -470,31 +449,8 @@ export const SearchableGroups = (args, { argTypes }) => ({
470
449
  }, 2000);
471
450
  },
472
451
  },
473
- template: `
474
- <gl-listbox
475
- ref="listbox"
476
- v-model="selected"
477
- :items="filteredGroupOptions"
478
- :category="category"
479
- :variant="variant"
480
- :size="size"
481
- :disabled="disabled"
482
- :loading="loading"
483
- :no-caret="noCaret"
484
- :right="right"
485
- :toggle-text="customToggleText"
486
- :text-sr-only="textSrOnly"
487
- :icon="icon"
488
- :multiple="multiple"
489
- :is-check-centered="isCheckCentered"
490
- :toggle-aria-labelled-by="toggleAriaLabelledBy"
491
- :list-aria-labelled-by="headerId"
492
- :searching="searchInProgress"
493
- :no-results-text="noResultsText"
494
- :searchable="searchable"
495
- @search="filterList"
496
- >
497
- <template #header>
452
+ template: template(
453
+ `<template #header>
498
454
  <p :id="headerId"
499
455
  class="gl-font-weight-bold gl-font-sm gl-m-0 gl-text-center gl-py-2 gl-border-1 gl-border-b-solid gl-border-gray-200">
500
456
  Assign to department</p>
@@ -502,8 +458,17 @@ export const SearchableGroups = (args, { argTypes }) => ({
502
458
  <template #search-summary-sr-only>
503
459
  {{ numberOfSearchResults }}
504
460
  </template>
505
- </gl-listbox>
506
461
  `,
462
+ {
463
+ bindingOverrides: {
464
+ ':items': 'filteredGroupOptions',
465
+ ':list-aria-labelled-by': 'headerId',
466
+ ':toggle-text': 'customToggleText',
467
+ ':searching': 'searchInProgress',
468
+ '@search': 'filterList',
469
+ },
470
+ }
471
+ ),
507
472
  });
508
473
  SearchableGroups.args = generateProps({ searchable: true, items: mockGroups });
509
474
  SearchableGroups.decorators = [makeContainer({ height: '370px' })];
@@ -63,7 +63,7 @@ describe('pagination component', () => {
63
63
  });
64
64
  await wrapper.vm.$nextTick();
65
65
 
66
- expect(wrapper.html()).toBe('');
66
+ expect(wrapper.text()).toBe('');
67
67
  });
68
68
 
69
69
  it('supports slots customization', () => {
@@ -339,6 +339,8 @@ export default {
339
339
  slot: `ellipsis-${side}`,
340
340
  component: 'span',
341
341
  disabled: true,
342
+ slotData: {},
343
+ listeners: {},
342
344
  };
343
345
  },
344
346
  handleClick(event, value) {
@@ -395,8 +397,8 @@ export default {
395
397
  :href="prevPageHref"
396
398
  @click="handlePrevious($event, value - 1)"
397
399
  >
398
- <!--
399
- @slot Content for the "previous" button. Overrides the "prevText" prop.
400
+ <!--
401
+ @slot Content for the "previous" button. Overrides the "prevText" prop.
400
402
  @binding {boolean} active
401
403
  @binding {boolean} disabled
402
404
  @binding {number} number
@@ -458,8 +460,8 @@ export default {
458
460
  :href="nextPageHref"
459
461
  @click="handleNext($event, value + 1)"
460
462
  >
461
- <!--
462
- @slot Content for the "next" button. Overrides the "nextText" prop.
463
+ <!--
464
+ @slot Content for the "next" button. Overrides the "nextText" prop.
463
465
  @binding {boolean} active
464
466
  @binding {boolean} disabled
465
467
  @binding {number} number
@@ -125,17 +125,19 @@ describe('search box by click component', () => {
125
125
 
126
126
  it('displays disabled history dropdown', () => {
127
127
  expect(wrapper.findComponent({ ref: 'historyDropdown' }).exists()).toBe(true);
128
- expect(wrapper.findComponent({ ref: 'historyDropdown' }).attributes('disabled')).toBe('true');
128
+ expect(
129
+ wrapper.findComponent({ ref: 'historyDropdown' }).attributes('disabled')
130
+ ).toBeDefined();
129
131
  });
130
132
 
131
133
  it('displays disabled input', () => {
132
134
  expect(wrapper.findComponent({ ref: 'input' }).exists()).toBe(true);
133
- expect(wrapper.findComponent({ ref: 'input' }).attributes('disabled')).toBe('true');
135
+ expect(wrapper.findComponent({ ref: 'input' }).attributes('disabled')).toBeDefined();
134
136
  });
135
137
 
136
138
  it('displays disabled search button', () => {
137
139
  expect(findSearchButton().exists()).toBe(true);
138
- expect(findSearchButton().attributes('disabled')).toBe('true');
140
+ expect(findSearchButton().attributes('disabled')).toBeDefined();
139
141
  });
140
142
 
141
143
  it('does not render clear icon even with value', () => {
@@ -146,9 +148,8 @@ describe('search box by click component', () => {
146
148
  it('emits submit event when Enter key is pressed', async () => {
147
149
  createComponent({ value: 'some-input' });
148
150
 
149
- wrapper.findComponent(GlFormInput).vm.$emit('keydown', { type: 'key', keyCode: 13 });
151
+ await wrapper.findComponent(GlFormInput).trigger('keydown.enter');
150
152
 
151
- await wrapper.vm.$nextTick();
152
153
  expect(wrapper.emitted('submit')[0]).toEqual(['some-input']);
153
154
  });
154
155
 
@@ -258,7 +258,7 @@ export default {
258
258
  :disabled="disabled"
259
259
  @focus="isFocused = true"
260
260
  @blur="isFocused = false"
261
- @keydown.enter="search(currentValue)"
261
+ @keydown.enter.native="search(currentValue)"
262
262
  />
263
263
  </slot>
264
264
  <gl-clear-icon-button
@@ -1,9 +1,7 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import GlDropdown from '../dropdown/dropdown.vue';
3
- import GlDropdownItem from '../dropdown/dropdown_item.vue';
4
3
  import GlIcon from '../icon/icon.vue';
5
4
  import GlSorting from './sorting.vue';
6
- import GlSortingItem from './sorting_item.vue';
7
5
 
8
6
  describe('sorting component', () => {
9
7
  let wrapper;
@@ -22,25 +20,10 @@ describe('sorting component', () => {
22
20
 
23
21
  const createComponent = (propsData) => {
24
22
  wrapper = mount(GlSorting, {
25
- attachTo: document.body,
26
- components: {
27
- GlSortingItem,
28
- },
29
- slots: {
30
- default: [
31
- '<gl-sorting-item :active="true">First item</gl-sorting-item>',
32
- '<gl-sorting-item>Second item</gl-sorting-item>',
33
- '<gl-sorting-item>Third item</gl-sorting-item>',
34
- ],
35
- },
36
23
  propsData: {
37
24
  ...defaultProps,
38
25
  ...propsData,
39
26
  },
40
- stubs: {
41
- GlSortingItem,
42
- GlDropdownItem,
43
- },
44
27
  });
45
28
  };
46
29
 
@@ -15,12 +15,14 @@ describe('sorting item component', () => {
15
15
  const createComponent = (propsData) => {
16
16
  wrapper = shallowMount(GlSortingItem, {
17
17
  context: {
18
- children: [sortingItemText],
19
18
  props: {
20
19
  ...defaultProps,
21
20
  ...propsData,
22
21
  },
23
22
  },
23
+ slots: {
24
+ default: sortingItemText,
25
+ },
24
26
  stubs: {
25
27
  GlDropdownItem,
26
28
  },
@@ -39,7 +39,7 @@ export default {
39
39
  * The content of the item.
40
40
  * @slot default
41
41
  */
42
- render(createElement, { children, data, props = {} }) {
42
+ render(createElement, { scopedSlots, data, props = {} }) {
43
43
  const classNames = `gl-sorting-item js-active-icon gl-flex-shrink-0 gl-mr-2 ${
44
44
  props.active ? '' : 'inactive gl-visibility-hidden'
45
45
  }`;
@@ -52,16 +52,15 @@ export default {
52
52
  },
53
53
  });
54
54
 
55
- return createElement(
56
- GlDropdownItem,
57
- {
58
- ...data,
59
- attrs: {
60
- ...props,
61
- },
55
+ return createElement(GlDropdownItem, {
56
+ ...data,
57
+ attrs: {
58
+ ...props,
59
+ },
60
+ scopedSlots: {
61
+ default: () => [icon, scopedSlots.default?.()],
62
62
  },
63
- [icon, children]
64
- );
63
+ });
65
64
  },
66
65
  };
67
66
  </script>
@@ -1,4 +1,5 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
+ import { BTab } from 'bootstrap-vue';
2
3
  import { DEFAULT_TAB_TITLE_LINK_CLASS } from '../constants';
3
4
  import GlTab from './tab.vue';
4
5
 
@@ -27,9 +28,7 @@ describe('Tab component', () => {
27
28
  },
28
29
  });
29
30
 
30
- expect(wrapper.html()).toBe(
31
- `<b-tab-stub tag="div" title="" titlelinkclass="${expectedProp}"></b-tab-stub>`
32
- );
31
+ expect(wrapper.findComponent(BTab).props('titleLinkClass')).toStrictEqual(expectedProp);
33
32
  }
34
33
  );
35
34
  });
@@ -58,7 +58,9 @@ describe('GlScrollableTabs', () => {
58
58
  ...props,
59
59
  },
60
60
  slots: {
61
- default: `<gl-tab v-for="tab in tabs" :key="tab.key" :title="tab.title">{{ tab.content }}</gl-tab>`,
61
+ default: {
62
+ template: `<div><gl-tab v-for="tab in tabs" :key="tab.key" :title="tab.title">{{ tab.content }}</gl-tab></div>`,
63
+ },
62
64
  },
63
65
  stubs: {
64
66
  'gl-tab': GlTab,
@@ -96,7 +96,7 @@ export default {
96
96
  barSeries() {
97
97
  return this.bars.map(({ name, data }, index) => {
98
98
  const color = colorFromDefaultPalette(index);
99
- return generateBarSeries({ stack: this.groupBy, name, data, color });
99
+ return generateBarSeries({ name, data, color });
100
100
  });
101
101
  },
102
102
  lineSeries() {
@@ -47,7 +47,7 @@ describe('IntersectionObserver', () => {
47
47
  });
48
48
 
49
49
  it('renders slot', () => {
50
- expect(wrapper.element.innerHTML).toEqual(TEST_SLOT);
50
+ expect(wrapper.html()).toContain(TEST_SLOT);
51
51
  });
52
52
 
53
53
  it('creates 1 intersection observer', () => {
@@ -7,7 +7,7 @@ import filter from 'lodash/fp/filter';
7
7
  import { intersperse, insert } from '../../../utils/data_utils';
8
8
 
9
9
  const containsWhitespaceOnly = (vNode) => vNode.text.trim() === '';
10
- const isTag = (vNode) => vNode.tag !== undefined;
10
+ const isTag = (vNode) => typeof vNode.tag === 'string';
11
11
  const filterWhitespaceNodes = filter((vNode) => isTag(vNode) || !containsWhitespaceOnly(vNode));
12
12
 
13
13
  const insertAfterSecondLastItem = insert(-1);
@@ -89,11 +89,7 @@ describe('sprintf component', () => {
89
89
  });
90
90
 
91
91
  it('should work with a default slot', () => {
92
- createComponent(
93
- `<sprintf message="Written by %{default}">
94
- <template>Author</template>
95
- </sprintf>`
96
- );
92
+ createComponent(`<sprintf message="Written by %{default}">Author</sprintf>`);
97
93
 
98
94
  expect(wrapper.element.innerHTML).toBe('Written by Author');
99
95
  });
@@ -1,5 +1,5 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
- import { createMockDirective, getBinding } from '~helpers/vue_mock_directive';
2
+ import { getBinding } from '~helpers/vue_mock_directive';
3
3
  import { POSITION } from './constants';
4
4
  import Truncate from './truncate.vue';
5
5
 
@@ -17,10 +17,9 @@ describe('Truncate component', () => {
17
17
  };
18
18
 
19
19
  const createComponent = (props) => {
20
- wrapper = shallowMount(
21
- { extends: Truncate, directives: { GlTooltip: createMockDirective('gl-tooltip') } },
22
- { propsData: { ...defaultProps, ...props } }
23
- );
20
+ wrapper = shallowMount(Truncate, {
21
+ propsData: { ...defaultProps, ...props },
22
+ });
24
23
  };
25
24
 
26
25
  describe('All', () => {
@@ -5,7 +5,7 @@ jest.useFakeTimers();
5
5
 
6
6
  describe('hover load directive', () => {
7
7
  let wrapper;
8
- const findTarget = () => wrapper.find('.target');
8
+ const findTarget = () => wrapper.findComponent('.target');
9
9
 
10
10
  const createComponent = (handleLoad) => {
11
11
  const component = {
@@ -17,20 +17,18 @@ describe('safe link directive', () => {
17
17
  mountFn = shallowMount,
18
18
  } = {}) => {
19
19
  const component = {
20
+ props: {
21
+ href: { type: String },
22
+ safeLinkConfig: { type: Object },
23
+ },
20
24
  directives: {
21
25
  SafeLink: SafeLinkDirective,
22
26
  },
23
27
  components,
24
- data() {
25
- return {
26
- href,
27
- safeLinkConfig,
28
- };
29
- },
30
28
  template,
31
29
  };
32
30
 
33
- wrapper = mountFn(component);
31
+ wrapper = mountFn(component, { propsData: { href, safeLinkConfig } });
34
32
  };
35
33
 
36
34
  describe('default', () => {
@@ -64,7 +62,7 @@ describe('safe link directive', () => {
64
62
  describe('valid urls', () => {
65
63
  const validUrls = [...absoluteUrls, ...relativeUrls, ...encodedJavaScriptUrls];
66
64
  /* Note:
67
- /* Encoded JavaScript URLs are safe urls in Vue context, since
65
+ /* Encoded JavaScript URLs are safe urls in Vue context, since
68
66
  /* Vue attribute bindings are also automatically escaped
69
67
  /* https://vuejs.org/v2/guide/security.html#Injecting-URLs
70
68
  */
@@ -99,13 +97,13 @@ describe('safe link directive', () => {
99
97
  expect(wrapper.attributes('href')).toBe('about:blank');
100
98
 
101
99
  // set href to a valid url
102
- wrapper.setData({ href: 'https://gitlab.com' });
103
- await Vue.nextTick();
100
+ await wrapper.setProps({ href: 'https://gitlab.com' });
104
101
  expect(wrapper.attributes('href')).toBe('https://gitlab.com');
105
102
 
106
103
  // set href to back to an invalid url
107
- wrapper.setData({ href: javascriptUrls[1] });
104
+ await wrapper.setProps({ href: javascriptUrls[1] });
108
105
  await Vue.nextTick();
106
+
109
107
  expect(wrapper.attributes('href')).toBe('about:blank');
110
108
  });
111
109
 
@@ -123,12 +121,12 @@ describe('safe link directive', () => {
123
121
  expect(wrapper.attributes('href')).toBe(url);
124
122
 
125
123
  // set href to a valid url
126
- wrapper.setData({ href: 'https://gitlab.com' });
124
+ await wrapper.setProps({ href: 'https://gitlab.com' });
127
125
  await Vue.nextTick();
128
126
  expect(wrapper.attributes('href')).toBe('https://gitlab.com');
129
127
 
130
128
  // set href to back to an invalid url
131
- wrapper.setData({ href: url });
129
+ await wrapper.setProps({ href: url });
132
130
  await Vue.nextTick();
133
131
  expect(wrapper.attributes('href')).toBe(url);
134
132
  });
@@ -6633,12 +6633,12 @@
6633
6633
  }
6634
6634
  }
6635
6635
  .gl-sm-pr-2 {
6636
- @include gl-media-breakpoint-down(sm) {
6636
+ @include gl-media-breakpoint-up(sm) {
6637
6637
  padding-right: $gl-spacing-scale-2;
6638
6638
  }
6639
6639
  }
6640
6640
  .gl-sm-pr-2\! {
6641
- @include gl-media-breakpoint-down(sm) {
6641
+ @include gl-media-breakpoint-up(sm) {
6642
6642
  padding-right: $gl-spacing-scale-2 !important;
6643
6643
  }
6644
6644
  }
@@ -6762,16 +6762,6 @@
6762
6762
  padding-right: $gl-spacing-scale-1 !important;
6763
6763
  }
6764
6764
  }
6765
- .gl-md-pr-2 {
6766
- @include gl-media-breakpoint-up(md) {
6767
- padding-right: $gl-spacing-scale-2;
6768
- }
6769
- }
6770
- .gl-md-pr-2\! {
6771
- @include gl-media-breakpoint-up(md) {
6772
- padding-right: $gl-spacing-scale-2 !important;
6773
- }
6774
- }
6775
6765
  .gl-md-pr-3 {
6776
6766
  @include gl-media-breakpoint-up(md) {
6777
6767
  padding-right: $gl-spacing-scale-3;
@@ -1061,8 +1061,7 @@
1061
1061
  */
1062
1062
 
1063
1063
  @mixin gl-sm-pr-2 {
1064
- // stylelint-disable-next-line @gitlab/no-gl-media-breakpoint-down
1065
- @include gl-media-breakpoint-down(sm) {
1064
+ @include gl-media-breakpoint-up(sm) {
1066
1065
  @include gl-pr-2;
1067
1066
  }
1068
1067
  }
@@ -1143,12 +1142,6 @@
1143
1142
  }
1144
1143
  }
1145
1144
 
1146
- @mixin gl-md-pr-2 {
1147
- @include gl-media-breakpoint-up(md) {
1148
- @include gl-pr-2;
1149
- }
1150
- }
1151
-
1152
1145
  @mixin gl-md-pr-3 {
1153
1146
  @include gl-media-breakpoint-up(md) {
1154
1147
  @include gl-pr-3;