From 494da5670513a70b83b88b02ea65d948d46a33cd Mon Sep 17 00:00:00 2001 From: Paul Gascou-Vaillancourt <pgascouvaillancourt@gitlab.com> Date: Fri, 17 Jun 2022 14:04:23 +0000 Subject: [PATCH] Enable prefer-dom-node-dataset ESLint rule This enables the unicorn/prefer-dom-node-dataset ESLint rule to prevent using attributes APIs when manipulating data- attributes. --- .eslintrc.yml | 2 ++ .../behaviors/markdown/render_kroki.js | 4 ++-- .../behaviors/markdown/render_math.js | 4 ++-- .../blob/blob_line_permalink_updater.js | 5 +++-- app/assets/javascripts/blob/viewer/index.js | 17 +++++++++-------- app/assets/javascripts/breadcrumb.js | 2 +- .../javascripts/code_navigation/utils/index.js | 4 ++-- .../deprecated_jquery_dropdown/render.js | 8 ++++---- app/assets/javascripts/diff.js | 3 ++- .../available_dropdown_mappings.js | 4 ++-- .../filtered_search/dropdown_hint.js | 4 ++-- .../filtered_search/dropdown_operator.js | 2 +- .../filtered_search/dropdown_user.js | 4 ++-- .../filtered_search/dropdown_utils.js | 2 ++ .../filtered_search/droplab/drop_down.js | 4 ++-- .../filtered_search/filtered_search_manager.js | 2 +- .../image_diff/helpers/dom_helper.js | 2 +- .../issues/create_merge_request_dropdown.js | 5 +---- .../issues/show/components/description.vue | 2 +- app/assets/javascripts/lazy_loader.js | 9 +++++---- .../confirm_via_gl_modal.js | 2 +- .../members/components/table/role_dropdown.vue | 2 +- .../pages/shared/nav/sidebar_tracking.js | 10 +++++----- .../pages/users/activity_calendar.js | 2 +- .../commits/components/author_select.vue | 2 +- .../javascripts/sidebar/mount_sidebar.js | 7 +++++-- app/assets/javascripts/terraform/index.js | 2 +- .../javascripts/whats_new/components/app.vue | 2 +- .../whats_new/utils/notification.js | 2 +- .../analytics/productivity_analytics/index.js | 8 ++++---- .../javascripts/event_tracking/navbar.js | 2 +- .../init_arkose_labs_script_spec.js | 2 +- .../components/table_header_spec.js | 4 +--- .../compliance_frameworks/init_form_spec.js | 10 +++++----- ee/spec/frontend/members/index_spec.js | 2 +- ee/spec/frontend/status_checks/mount_spec.js | 4 ++-- .../__helpers__/init_vue_mr_page_helper.js | 18 +++++++++--------- .../matchers/to_have_sprite_icon.js | 2 +- spec/frontend/admin/users/index_spec.js | 8 ++++---- .../two_factor_auth/index_spec.js | 4 ++-- .../blob/components/table_contents_spec.js | 4 ++-- spec/frontend/blob/viewer/index_spec.js | 6 +++--- .../components/lock_popovers_spec.js | 10 +++++----- .../code_navigation/store/actions_spec.js | 12 ++++++------ spec/frontend/confirm_modal_spec.js | 6 +++--- .../helpers/startup_css_helper_spec.js | 7 ++++--- .../create_merge_request_dropdown_spec.js | 4 ++-- .../frontend/labels/delete_label_modal_spec.js | 6 +++--- spec/frontend/lazy_loader_spec.js | 4 ++-- spec/frontend/members/index_spec.js | 2 +- spec/frontend/members/utils_spec.js | 2 +- spec/frontend/notebook/cells/markdown_spec.js | 4 ++-- spec/frontend/notes/stores/actions_spec.js | 10 +++++----- spec/frontend/performance_bar/index_spec.js | 10 +++++----- spec/frontend/search_autocomplete_spec.js | 2 +- spec/frontend/user_popovers_spec.js | 2 +- spec/frontend/users_select/test_helper.js | 8 ++++---- .../components/states/mr_widget_merged_spec.js | 4 +--- .../vue_mr_widget/mr_widget_options_spec.js | 2 +- .../ide/helpers/ide_helper.js | 4 ++-- 60 files changed, 149 insertions(+), 144 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 97c24d99871ce..7505d864e6fcd 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -114,6 +114,8 @@ rules: message: 'Migrate to GlSkeletonLoader, or import GlDeprecatedSkeletonLoading.' # See https://gitlab.com/gitlab-org/gitlab/-/issues/360551 vue/multi-word-component-names: off + unicorn/prefer-dom-node-dataset: + - error overrides: - files: - '{,ee/,jh/}spec/frontend*/**/*' diff --git a/app/assets/javascripts/behaviors/markdown/render_kroki.js b/app/assets/javascripts/behaviors/markdown/render_kroki.js index abe71694d735f..5fd910dd6cca7 100644 --- a/app/assets/javascripts/behaviors/markdown/render_kroki.js +++ b/app/assets/javascripts/behaviors/markdown/render_kroki.js @@ -55,8 +55,8 @@ export function renderKroki(krokiImages) { // A single Kroki image is processed multiple times for some reason, // so this condition ensures we only create one alert per Kroki image - if (!parent.hasAttribute('data-kroki-processed')) { - parent.setAttribute('data-kroki-processed', 'true'); + if (!Object.prototype.hasOwnProperty.call(parent.dataset, 'krokiProcessed')) { + parent.dataset.krokiProcessed = 'true'; parent.after(createAlert(krokiImage)); } }); diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js index fd1a99acf9927..af7aac4cf36dd 100644 --- a/app/assets/javascripts/behaviors/markdown/render_math.js +++ b/app/assets/javascripts/behaviors/markdown/render_math.js @@ -112,7 +112,7 @@ class SafeMathRenderer { try { displayContainer.innerHTML = this.katex.renderToString(text, { - displayMode: el.getAttribute('data-math-style') === 'display', + displayMode: el.dataset.mathStyle === 'display', throwOnError: true, maxSize: 20, maxExpand: 20, @@ -145,7 +145,7 @@ class SafeMathRenderer { this.elements.forEach((el) => { const placeholder = document.createElement('span'); placeholder.style.display = 'none'; - placeholder.setAttribute('data-math-style', el.getAttribute('data-math-style')); + placeholder.dataset.mathStyle = el.dataset.mathStyle; placeholder.textContent = el.textContent; el.parentNode.replaceChild(placeholder, el); this.queue.push(placeholder); diff --git a/app/assets/javascripts/blob/blob_line_permalink_updater.js b/app/assets/javascripts/blob/blob_line_permalink_updater.js index a3dd241604d58..0a5bcf326a1af 100644 --- a/app/assets/javascripts/blob/blob_line_permalink_updater.js +++ b/app/assets/javascripts/blob/blob_line_permalink_updater.js @@ -9,10 +9,11 @@ const updateLineNumbersOnBlobPermalinks = (linksToUpdate) => { [].concat(Array.prototype.slice.call(linksToUpdate)).forEach((permalinkButton) => { const baseHref = - permalinkButton.getAttribute('data-original-href') || + permalinkButton.dataset.originalHref || (() => { const href = permalinkButton.getAttribute('href'); - permalinkButton.setAttribute('data-original-href', href); + // eslint-disable-next-line no-param-reassign + permalinkButton.dataset.originalHref = href; return href; })(); permalinkButton.setAttribute('href', `${baseHref}${hashUrlString}`); diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index a6eed4ecae333..a0d4f7ef4f20f 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -36,19 +36,19 @@ const loadRichBlobViewer = (type) => { const loadViewer = (viewerParam) => { const viewer = viewerParam; - const url = viewer.getAttribute('data-url'); + const { url } = viewer.dataset; - if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) { + if (!url || viewer.dataset.loaded || viewer.dataset.loading) { return Promise.resolve(viewer); } - viewer.setAttribute('data-loading', 'true'); + viewer.dataset.loading = 'true'; return axios.get(url).then(({ data }) => { viewer.innerHTML = data.html; window.requestIdleCallback(() => { - viewer.removeAttribute('data-loading'); + delete viewer.dataset.loading; }); return viewer; @@ -108,7 +108,7 @@ export class BlobViewer { switchToInitialViewer() { const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)'); - let initialViewerName = initialViewer.getAttribute('data-type'); + let initialViewerName = initialViewer.dataset.type; if (this.switcher && window.location.hash.indexOf('#L') === 0) { initialViewerName = 'simple'; @@ -138,12 +138,12 @@ export class BlobViewer { e.preventDefault(); - this.switchToViewer(target.getAttribute('data-viewer')); + this.switchToViewer(target.dataset.viewer); } toggleCopyButtonState() { if (!this.copySourceBtn) return; - if (this.simpleViewer.getAttribute('data-loaded')) { + if (this.simpleViewer.dataset.loaded) { this.copySourceBtnTooltip.setAttribute('title', __('Copy file contents')); this.copySourceBtn.classList.remove('disabled'); } else if (this.activeViewer === this.simpleViewer) { @@ -199,7 +199,8 @@ export class BlobViewer { this.$fileHolder.trigger('highlight:line'); handleLocationHash(); - viewer.setAttribute('data-loaded', 'true'); + // eslint-disable-next-line no-param-reassign + viewer.dataset.loaded = 'true'; this.toggleCopyButtonState(); eventHub.$emit('showBlobInteractionZones', viewer.dataset.path); }); diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js index b9d3742974ce3..113840dbc52a3 100644 --- a/app/assets/javascripts/breadcrumb.js +++ b/app/assets/javascripts/breadcrumb.js @@ -5,7 +5,7 @@ export const addTooltipToEl = (el) => { if (textEl && textEl.scrollWidth > textEl.offsetWidth) { el.setAttribute('title', el.textContent); - el.setAttribute('data-container', 'body'); + el.dataset.container = 'body'; el.classList.add('has-tooltip'); } }; diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js index 0d72153d8fe82..46038df2f864e 100644 --- a/app/assets/javascripts/code_navigation/utils/index.js +++ b/app/assets/javascripts/code_navigation/utils/index.js @@ -32,8 +32,8 @@ export const addInteractionClass = ({ path, d, wrapTextNodes }) => { }); if (el && !isTextNode(el)) { - el.setAttribute('data-char-index', d.start_char); - el.setAttribute('data-line-index', d.start_line); + el.dataset.charIndex = d.start_char; + el.dataset.lineIndex = d.start_line; el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation'); el.closest('.line').classList.add('code-navigation-line'); } diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/render.js b/app/assets/javascripts/deprecated_jquery_dropdown/render.js index 37287b9d98184..f10c2d82b61df 100644 --- a/app/assets/javascripts/deprecated_jquery_dropdown/render.js +++ b/app/assets/javascripts/deprecated_jquery_dropdown/render.js @@ -107,10 +107,10 @@ function createLink(data, selected, options, index) { } if (options.trackSuggestionClickedLabel) { - link.setAttribute('data-track-action', 'click_text'); - link.setAttribute('data-track-label', options.trackSuggestionClickedLabel); - link.setAttribute('data-track-value', index); - link.setAttribute('data-track-property', slugify(data.category || 'no-category')); + link.dataset.trackAction = 'click_text'; + link.dataset.trackLabel = options.trackSuggestionClickedLabel; + link.dataset.trackValue = index; + link.dataset.trackProperty = slugify(data.category || 'no-category'); } link.classList.toggle('is-active', selected); diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js index a12829f8420b9..9f3fb7151509d 100644 --- a/app/assets/javascripts/diff.js +++ b/app/assets/javascripts/diff.js @@ -26,7 +26,8 @@ export default class Diff { FilesCommentButton.init($diffFile); const firstFile = $('.files').first().get(0); - const canCreateNote = firstFile && firstFile.hasAttribute('data-can-create-note'); + const canCreateNote = + firstFile && Object.prototype.hasOwnProperty.call(firstFile.dataset, 'canCreateNote'); $diffFile.each((index, file) => initImageDiffHelper.initImageDiff(file, canCreateNote)); if (!isBound) { diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js index b57db73a86e03..3913e4e8d812f 100644 --- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js +++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js @@ -197,10 +197,10 @@ export default class AvailableDropdownMappings { } getGroupId() { - return this.filteredSearchInput.getAttribute('data-group-id') || ''; + return this.filteredSearchInput.dataset.groupId || ''; } getProjectId() { - return this.filteredSearchInput.getAttribute('data-project-id') || ''; + return this.filteredSearchInput.dataset.projectId || ''; } } diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js index 9d29782c9a7ba..10c3a6a36d59c 100644 --- a/app/assets/javascripts/filtered_search/dropdown_hint.js +++ b/app/assets/javascripts/filtered_search/dropdown_hint.js @@ -25,9 +25,9 @@ export default class DropdownHint extends FilteredSearchDropdown { const { selected } = e.detail; if (selected.tagName === 'LI') { - if (selected.hasAttribute('data-value')) { + if (Object.prototype.hasOwnProperty.call(selected.dataset, 'value')) { this.dismissDropdown(); - } else if (selected.getAttribute('data-action') === 'submit') { + } else if (selected.dataset.action === 'submit') { this.dismissDropdown(); this.dispatchFormSubmitEvent(); } else { diff --git a/app/assets/javascripts/filtered_search/dropdown_operator.js b/app/assets/javascripts/filtered_search/dropdown_operator.js index fb9f25a8c4501..f3f159ab98880 100644 --- a/app/assets/javascripts/filtered_search/dropdown_operator.js +++ b/app/assets/javascripts/filtered_search/dropdown_operator.js @@ -23,7 +23,7 @@ export default class DropdownOperator extends FilteredSearchDropdown { const { selected } = e.detail; if (selected.tagName === 'LI') { - if (selected.hasAttribute('data-value')) { + if (Object.prototype.hasOwnProperty.call(selected.dataset, 'value')) { const name = FilteredSearchVisualTokens.getLastTokenPartial(); const operator = selected.dataset.value; diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js index 9a23ff25eacee..26507a85fa80b 100644 --- a/app/assets/javascripts/filtered_search/dropdown_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_user.js @@ -31,11 +31,11 @@ export default class DropdownUser extends DropdownAjaxFilter { } getGroupId() { - return this.input.getAttribute('data-group-id'); + return this.input.dataset.groupId; } getProjectId() { - return this.input.getAttribute('data-project-id'); + return this.input.dataset.projectId; } projectOrGroupId() { diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index c98d1f8e06417..22e1604871a53 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -87,6 +87,7 @@ export default class DropdownUtils { } static setDataValueIfSelected(filter, operator, selected) { + // eslint-disable-next-line unicorn/prefer-dom-node-dataset const dataValue = selected.getAttribute('data-value'); if (dataValue) { @@ -96,6 +97,7 @@ export default class DropdownUtils { tokenValue: dataValue, clicked: true, options: { + // eslint-disable-next-line unicorn/prefer-dom-node-dataset capitalizeTokenValue: selected.hasAttribute('data-capitalize'), }, }); diff --git a/app/assets/javascripts/filtered_search/droplab/drop_down.js b/app/assets/javascripts/filtered_search/droplab/drop_down.js index 05b741af19152..398a7b266773b 100644 --- a/app/assets/javascripts/filtered_search/droplab/drop_down.js +++ b/app/assets/javascripts/filtered_search/droplab/drop_down.js @@ -165,8 +165,8 @@ class DropDown { images.forEach((image) => { const img = image; - img.src = img.getAttribute('data-src'); - img.removeAttribute('data-src'); + img.src = img.dataset.src; + delete img.dataset.src; }); } } diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 07f2c75f00a3a..ac2cf27e87327 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -814,7 +814,7 @@ export default class FilteredSearchManager { getUsernameParams() { const usernamesById = {}; try { - const attribute = this.filteredSearchInput.getAttribute('data-username-params'); + const attribute = this.filteredSearchInput.dataset.usernameParams; JSON.parse(attribute).forEach((user) => { usernamesById[user.id] = user.username; }); diff --git a/app/assets/javascripts/image_diff/helpers/dom_helper.js b/app/assets/javascripts/image_diff/helpers/dom_helper.js index 3468a629f5ac0..180e927a3e789 100644 --- a/app/assets/javascripts/image_diff/helpers/dom_helper.js +++ b/app/assets/javascripts/image_diff/helpers/dom_helper.js @@ -6,7 +6,7 @@ export function setPositionDataAttribute(el, options) { const positionObject = { ...JSON.parse(position), x, y, width, height }; - el.setAttribute('data-position', JSON.stringify(positionObject)); + el.dataset.position = JSON.stringify(positionObject); } export function updateDiscussionAvatarBadgeNumber(discussionEl, newBadgeNumber) { diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js index c5f31081625f2..edf3789e6dc91 100644 --- a/app/assets/javascripts/issues/create_merge_request_dropdown.js +++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js @@ -82,10 +82,7 @@ export default class CreateMergeRequestDropdown { this.init(); if (isConfidentialIssue()) { - this.createMergeRequestButton.setAttribute( - 'data-dropdown-trigger', - '#create-merge-request-dropdown', - ); + this.createMergeRequestButton.dataset.dropdownTrigger = '#create-merge-request-dropdown'; initConfidentialMergeRequest(); } } diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index b8b7cbb5bdce4..892c631f8eae7 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -379,7 +379,7 @@ export default { }, setActiveTask(el) { const { parentElement } = el; - const lineNumbers = parentElement.getAttribute('data-sourcepos').match(/\b\d+(?=:)/g); + const lineNumbers = parentElement.dataset.sourcepos.match(/\b\d+(?=:)/g); this.activeTask = { title: parentElement.innerText, lineNumberStart: lineNumbers[0], diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js index 2b4dd205cf1c9..ba8010823775b 100644 --- a/app/assets/javascripts/lazy_loader.js +++ b/app/assets/javascripts/lazy_loader.js @@ -127,7 +127,7 @@ export default class LazyLoader { // Loading Images which are in the current viewport or close to them this.lazyImages = this.lazyImages.filter((selectedImage) => { - if (selectedImage.getAttribute('data-src')) { + if (selectedImage.dataset.src) { const imgBoundRect = selectedImage.getBoundingClientRect(); const imgTop = scrollTop + imgBoundRect.top; const imgBound = imgTop + imgBoundRect.height; @@ -156,16 +156,17 @@ export default class LazyLoader { } static loadImage(img) { - if (img.getAttribute('data-src')) { + if (img.dataset.src) { img.setAttribute('loading', 'lazy'); - let imgUrl = img.getAttribute('data-src'); + let imgUrl = img.dataset.src; // Only adding width + height for avatars for now if (imgUrl.indexOf('/avatar/') > -1 && imgUrl.indexOf('?') === -1) { const targetWidth = img.getAttribute('width') || img.width; imgUrl += `?width=${targetWidth}`; } img.setAttribute('src', imgUrl); - img.removeAttribute('data-src'); + // eslint-disable-next-line no-param-reassign + delete img.dataset.src; img.classList.remove('lazy'); img.classList.add('js-lazy-loaded'); img.classList.add('qa-js-lazy-loaded'); diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js index 173116062c9ac..2dc479db80af6 100644 --- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js +++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js @@ -56,7 +56,7 @@ export function confirmAction( export function confirmViaGlModal(message, element) { const primaryBtnConfig = {}; - const confirmBtnVariant = element.getAttribute('data-confirm-btn-variant'); + const { confirmBtnVariant } = element.dataset; if (confirmBtnVariant) { primaryBtnConfig.primaryBtnVariant = confirmBtnVariant; diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue index fa895cf24c476..6cd8bf57313ec 100644 --- a/app/assets/javascripts/members/components/table/role_dropdown.vue +++ b/app/assets/javascripts/members/components/table/role_dropdown.vue @@ -41,7 +41,7 @@ export default { const dropdownToggle = this.$refs.glDropdown.$el.querySelector('.dropdown-toggle'); if (dropdownToggle) { - dropdownToggle.setAttribute('data-qa-selector', 'access_level_dropdown'); + dropdownToggle.dataset.qaSelector = 'access_level_dropdown'; } }, methods: { diff --git a/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js index 79ce1a37d2111..47aae36ecbb97 100644 --- a/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js +++ b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js @@ -1,6 +1,6 @@ function onSidebarLinkClick() { const setDataTrackAction = (element, action) => { - element.setAttribute('data-track-action', action); + element.dataset.trackAction = action; }; const setDataTrackExtra = (element, value) => { @@ -12,10 +12,10 @@ function onSidebarLinkClick() { ? SIDEBAR_COLLAPSED : SIDEBAR_EXPANDED; - element.setAttribute( - 'data-track-extra', - JSON.stringify({ sidebar_display: sidebarCollapsed, menu_display: value }), - ); + element.dataset.trackExtra = JSON.stringify({ + sidebar_display: sidebarCollapsed, + menu_display: value, + }); }; const EXPANDED = 'Expanded'; diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index 996e12bc105c5..94506d33b3351 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -298,7 +298,7 @@ export default class ActivityCalendar { .querySelector(this.activitiesContainer) .querySelectorAll('.js-localtime') .forEach((el) => { - el.setAttribute('title', formatDate(el.getAttribute('data-datetime'))); + el.setAttribute('title', formatDate(el.dataset.datetime)); }); }) .catch(() => diff --git a/app/assets/javascripts/projects/commits/components/author_select.vue b/app/assets/javascripts/projects/commits/components/author_select.vue index c8a0a3417f3a7..884ef7321445c 100644 --- a/app/assets/javascripts/projects/commits/components/author_select.vue +++ b/app/assets/javascripts/projects/commits/components/author_select.vue @@ -57,7 +57,7 @@ export default { if (authorParam) { commitsSearchInput.setAttribute('disabled', true); - commitsSearchInput.setAttribute('data-toggle', 'tooltip'); + commitsSearchInput.dataset.toggle = 'tooltip'; commitsSearchInput.setAttribute('title', tooltipMessage); this.currentAuthor = authorParam; } diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js index 351bb50d9417d..bb40ac1443819 100644 --- a/app/assets/javascripts/sidebar/mount_sidebar.js +++ b/app/assets/javascripts/sidebar/mount_sidebar.js @@ -119,7 +119,7 @@ function mountAssigneesComponentDeprecated(mediator) { issuableIid: String(iid), projectPath: fullPath, field: el.dataset.field, - signedIn: el.hasAttribute('data-signed-in'), + signedIn: Object.prototype.hasOwnProperty.call(el.dataset, 'signedIn'), issuableType: isInIssuePage() || isInIncidentPage() || isInDesignPage() ? IssuableType.Issue @@ -149,7 +149,10 @@ function mountAssigneesComponent() { }, provide: { canUpdate: editable, - directlyInviteMembers: el.hasAttribute('data-directly-invite-members'), + directlyInviteMembers: Object.prototype.hasOwnProperty.call( + el.dataset, + 'directlyInviteMembers', + ), }, render: (createElement) => createElement('sidebar-assignees-widget', { diff --git a/app/assets/javascripts/terraform/index.js b/app/assets/javascripts/terraform/index.js index 571177986d2f5..2d70ccfac4dc4 100644 --- a/app/assets/javascripts/terraform/index.js +++ b/app/assets/javascripts/terraform/index.js @@ -39,7 +39,7 @@ export default () => { return createElement(TerraformList, { props: { emptyStateImage, - terraformAdmin: el.hasAttribute('data-terraform-admin'), + terraformAdmin: Object.prototype.hasOwnProperty.call(el.dataset, 'terraformAdmin'), }, }); }, diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue index b74dba686ade0..0c55cc2f8a6ce 100644 --- a/app/assets/javascripts/whats_new/components/app.vue +++ b/app/assets/javascripts/whats_new/components/app.vue @@ -33,7 +33,7 @@ export default { this.fetchFreshItems(); const body = document.querySelector('body'); - const namespaceId = body.getAttribute('data-namespace-id'); + const { namespaceId } = body.dataset; this.track('click_whats_new_drawer', { label: 'namespace_id', value: namespaceId }); }, diff --git a/app/assets/javascripts/whats_new/utils/notification.js b/app/assets/javascripts/whats_new/utils/notification.js index 66ee3b1a97126..41aff202f48c6 100644 --- a/app/assets/javascripts/whats_new/utils/notification.js +++ b/app/assets/javascripts/whats_new/utils/notification.js @@ -1,6 +1,6 @@ export const STORAGE_KEY = 'display-whats-new-notification'; -export const getVersionDigest = (appEl) => appEl.getAttribute('data-version-digest'); +export const getVersionDigest = (appEl) => appEl.dataset.versionDigest; export const setNotification = (appEl) => { const versionDigest = getVersionDigest(appEl); diff --git a/ee/app/assets/javascripts/analytics/productivity_analytics/index.js b/ee/app/assets/javascripts/analytics/productivity_analytics/index.js index 795bd8b7b8159..003052a99db5b 100644 --- a/ee/app/assets/javascripts/analytics/productivity_analytics/index.js +++ b/ee/app/assets/javascripts/analytics/productivity_analytics/index.js @@ -123,14 +123,14 @@ export default () => { const labelsEndpoint = getLabelsEndpoint(groupNamespace, projectNamespace); const milestonesEndpoint = getMilestonesEndpoint(groupNamespace, projectNamespace); - filteredSearchInput.setAttribute('data-group-id', groupId); + filteredSearchInput.dataset.groupId = groupId; if (projectId) { - filteredSearchInput.setAttribute('data-project-id', projectId); + filteredSearchInput.dataset.projectId = projectId; } - filteredSearchInput.setAttribute('data-labels-endpoint', labelsEndpoint); - filteredSearchInput.setAttribute('data-milestones-endpoint', milestonesEndpoint); + filteredSearchInput.dataset.labelsEndpoint = labelsEndpoint; + filteredSearchInput.dataset.milestonesEndpoint = milestonesEndpoint; filterManager = new FilteredSearchProductivityAnalytics({ isGroup: false }); filterManager.setup(); }, diff --git a/ee/app/assets/javascripts/event_tracking/navbar.js b/ee/app/assets/javascripts/event_tracking/navbar.js index 3a41d254c0760..ec8becc7d2125 100644 --- a/ee/app/assets/javascripts/event_tracking/navbar.js +++ b/ee/app/assets/javascripts/event_tracking/navbar.js @@ -33,7 +33,7 @@ export default function trackNavbarEvents() { const parentDropdown = e.currentTarget.closest('li.dropdown'); Tracking.event(TRACKING_CATEGORY, 'activate_form_input', { - label: `${parentDropdown.getAttribute('data-track-label')}_search`, + label: `${parentDropdown.dataset.trackLabel}_search`, property: '', value: '', }); diff --git a/ee/spec/frontend/arkose_labs/init_arkose_labs_script_spec.js b/ee/spec/frontend/arkose_labs/init_arkose_labs_script_spec.js index 7a3017a0458da..321f263b10668 100644 --- a/ee/spec/frontend/arkose_labs/init_arkose_labs_script_spec.js +++ b/ee/spec/frontend/arkose_labs/init_arkose_labs_script_spec.js @@ -37,7 +37,7 @@ describe('initArkoseLabsScript', () => { expect(scriptTag.getAttribute('src')).toBe( `https://${TEST_DOMAIN}/v2/${TEST_PUBLIC_KEY}/api.js`, ); - expect(scriptTag.getAttribute('data-callback')).toBe(EXPECTED_CALLBACK_NAME); + expect(scriptTag.dataset.callback).toBe(EXPECTED_CALLBACK_NAME); }); it('when callback is called, cleans up the global object and resolves the Promise', () => { diff --git a/ee/spec/frontend/group_member_contributions/components/table_header_spec.js b/ee/spec/frontend/group_member_contributions/components/table_header_spec.js index e8302e5dce6c4..c857da257790e 100644 --- a/ee/spec/frontend/group_member_contributions/components/table_header_spec.js +++ b/ee/spec/frontend/group_member_contributions/components/table_header_spec.js @@ -86,9 +86,7 @@ describe('TableHeaderComponent', () => { expect(headerItemEl).not.toBeNull(); expect(headerItemEl.innerText.trim()).toBe('Name'); - expect(headerItemEl.querySelector('svg').getAttribute('data-testid')).toBe( - 'chevron-lg-up-icon', - ); + expect(headerItemEl.querySelector('svg').dataset.testid).toBe('chevron-lg-up-icon'); }); }); }); diff --git a/ee/spec/frontend/groups/settings/compliance_frameworks/init_form_spec.js b/ee/spec/frontend/groups/settings/compliance_frameworks/init_form_spec.js index aea3a43f5fa9d..d8e77ed1017f4 100644 --- a/ee/spec/frontend/groups/settings/compliance_frameworks/init_form_spec.js +++ b/ee/spec/frontend/groups/settings/compliance_frameworks/init_form_spec.js @@ -19,13 +19,13 @@ describe('createComplianceFrameworksFormApp', () => { const setUpDocument = (id = null) => { el = document.createElement('div'); - el.setAttribute('data-group-edit-path', groupEditPath); - el.setAttribute('data-group-path', groupPath); - el.setAttribute('data-pipeline-configuration-full-path-enabled', 'true'); + el.dataset.groupEditPath = groupEditPath; + el.dataset.groupPath = groupPath; + el.dataset.pipelineConfigurationFullPathEnabled = 'true'; if (id) { - el.setAttribute('data-graphql-field-name', graphqlFieldName); - el.setAttribute('data-framework-id', id); + el.dataset.graphqlFieldName = graphqlFieldName; + el.dataset.frameworkId = id; } document.body.appendChild(el); diff --git a/ee/spec/frontend/members/index_spec.js b/ee/spec/frontend/members/index_spec.js index 49ea38e49ab5d..c562251f58aa6 100644 --- a/ee/spec/frontend/members/index_spec.js +++ b/ee/spec/frontend/members/index_spec.js @@ -14,7 +14,7 @@ describe('initMembersApp', () => { beforeEach(() => { el = document.createElement('div'); - el.setAttribute('data-members-data', dataAttribute); + el.dataset.membersData = dataAttribute; }); afterEach(() => { diff --git a/ee/spec/frontend/status_checks/mount_spec.js b/ee/spec/frontend/status_checks/mount_spec.js index 87b9624b6572c..81bbdb6c1d399 100644 --- a/ee/spec/frontend/status_checks/mount_spec.js +++ b/ee/spec/frontend/status_checks/mount_spec.js @@ -15,8 +15,8 @@ describe('mountStatusChecks', () => { const setUpDocument = () => { el = document.createElement('div'); - el.setAttribute('data-project-id', projectId); - el.setAttribute('data-status-checks-path', statusChecksPath); + el.dataset.projectId = projectId; + el.dataset.statusChecksPath = statusChecksPath; document.body.appendChild(el); diff --git a/spec/frontend/__helpers__/init_vue_mr_page_helper.js b/spec/frontend/__helpers__/init_vue_mr_page_helper.js index ee01e9e6268c6..6b719a324802f 100644 --- a/spec/frontend/__helpers__/init_vue_mr_page_helper.js +++ b/spec/frontend/__helpers__/init_vue_mr_page_helper.js @@ -13,16 +13,16 @@ export default function initVueMRPage() { const diffsAppProjectPath = 'testproject'; const mrEl = document.createElement('div'); mrEl.className = 'merge-request fixture-mr'; - mrEl.setAttribute('data-mr-action', 'diffs'); + mrEl.dataset.mrAction = 'diffs'; mrTestEl.appendChild(mrEl); const mrDiscussionsEl = document.createElement('div'); mrDiscussionsEl.id = 'js-vue-mr-discussions'; - mrDiscussionsEl.setAttribute('data-current-user-data', JSON.stringify(userDataMock)); - mrDiscussionsEl.setAttribute('data-noteable-data', JSON.stringify(noteableDataMock)); - mrDiscussionsEl.setAttribute('data-notes-data', JSON.stringify(notesDataMock)); - mrDiscussionsEl.setAttribute('data-noteable-type', 'merge-request'); - mrDiscussionsEl.setAttribute('data-is-locked', 'false'); + mrDiscussionsEl.dataset.currentUserData = JSON.stringify(userDataMock); + mrDiscussionsEl.dataset.noteableData = JSON.stringify(noteableDataMock); + mrDiscussionsEl.dataset.notesData = JSON.stringify(notesDataMock); + mrDiscussionsEl.dataset.noteableType = 'merge-request'; + mrDiscussionsEl.dataset.isLocked = 'false'; mrTestEl.appendChild(mrDiscussionsEl); const discussionCounterEl = document.createElement('div'); @@ -31,9 +31,9 @@ export default function initVueMRPage() { const diffsAppEl = document.createElement('div'); diffsAppEl.id = 'js-diffs-app'; - diffsAppEl.setAttribute('data-endpoint', diffsAppEndpoint); - diffsAppEl.setAttribute('data-project-path', diffsAppProjectPath); - diffsAppEl.setAttribute('data-current-user-data', JSON.stringify(userDataMock)); + diffsAppEl.dataset.endpoint = diffsAppEndpoint; + diffsAppEl.dataset.projectPath = diffsAppProjectPath; + diffsAppEl.dataset.currentUserData = JSON.stringify(userDataMock); mrTestEl.appendChild(diffsAppEl); const mock = new MockAdapter(axios); diff --git a/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js b/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js index bce9d93bea86f..45b9c31c4dbbf 100644 --- a/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js +++ b/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js @@ -9,7 +9,7 @@ export const toHaveSpriteIcon = (element, iconName) => { const iconReferences = [].slice.apply(element.querySelectorAll('svg use')); const matchingIcon = iconReferences.find( - (reference) => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`, + (reference) => reference.parentNode.dataset.testid === `${iconName}-icon`, ); const pass = Boolean(matchingIcon); diff --git a/spec/frontend/admin/users/index_spec.js b/spec/frontend/admin/users/index_spec.js index 06dbadd6d3d62..961fa96acdd16 100644 --- a/spec/frontend/admin/users/index_spec.js +++ b/spec/frontend/admin/users/index_spec.js @@ -12,8 +12,8 @@ describe('initAdminUsersApp', () => { beforeEach(() => { el = document.createElement('div'); - el.setAttribute('data-users', JSON.stringify(users)); - el.setAttribute('data-paths', JSON.stringify(paths)); + el.dataset.users = JSON.stringify(users); + el.dataset.paths = JSON.stringify(paths); wrapper = createWrapper(initAdminUsersApp(el)); }); @@ -40,8 +40,8 @@ describe('initAdminUserActions', () => { beforeEach(() => { el = document.createElement('div'); - el.setAttribute('data-user', JSON.stringify(user)); - el.setAttribute('data-paths', JSON.stringify(paths)); + el.dataset.user = JSON.stringify(user); + el.dataset.paths = JSON.stringify(paths); wrapper = createWrapper(initAdminUserActions(el)); }); diff --git a/spec/frontend/authentication/two_factor_auth/index_spec.js b/spec/frontend/authentication/two_factor_auth/index_spec.js index 0ff9d60f40944..f9a6b2df662ab 100644 --- a/spec/frontend/authentication/two_factor_auth/index_spec.js +++ b/spec/frontend/authentication/two_factor_auth/index_spec.js @@ -15,8 +15,8 @@ describe('initRecoveryCodes', () => { beforeEach(() => { el = document.createElement('div'); el.setAttribute('class', 'js-2fa-recovery-codes'); - el.setAttribute('data-codes', codesJsonString); - el.setAttribute('data-profile-account-path', profileAccountPath); + el.dataset.codes = codesJsonString; + el.dataset.profileAccountPath = profileAccountPath; document.body.appendChild(el); wrapper = createWrapper(initRecoveryCodes()); diff --git a/spec/frontend/blob/components/table_contents_spec.js b/spec/frontend/blob/components/table_contents_spec.js index 358ac31819cd1..2cbac809a0d39 100644 --- a/spec/frontend/blob/components/table_contents_spec.js +++ b/spec/frontend/blob/components/table_contents_spec.js @@ -11,7 +11,7 @@ function createComponent() { } async function setLoaded(loaded) { - document.querySelector('.blob-viewer').setAttribute('data-loaded', loaded); + document.querySelector('.blob-viewer').dataset.loaded = loaded; await nextTick(); } @@ -53,7 +53,7 @@ describe('Markdown table of contents component', () => { it('does not show dropdown when viewing non-rich content', async () => { createComponent(); - document.querySelector('.blob-viewer').setAttribute('data-type', 'simple'); + document.querySelector('.blob-viewer').dataset.type = 'simple'; await setLoaded(true); diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js index 5f6baf3f63d62..b2559af182b93 100644 --- a/spec/frontend/blob/viewer/index_spec.js +++ b/spec/frontend/blob/viewer/index_spec.js @@ -80,9 +80,9 @@ describe('Blob viewer', () => { return asyncClick() .then(() => asyncClick()) .then(() => { - expect( - document.querySelector('.blob-viewer[data-type="simple"]').getAttribute('data-loaded'), - ).toBe('true'); + expect(document.querySelector('.blob-viewer[data-type="simple"]').dataset.loaded).toBe( + 'true', + ); }); }); diff --git a/spec/frontend/cascading_settings/components/lock_popovers_spec.js b/spec/frontend/cascading_settings/components/lock_popovers_spec.js index 585e6ac505bbc..182e3c1c8ff1f 100644 --- a/spec/frontend/cascading_settings/components/lock_popovers_spec.js +++ b/spec/frontend/cascading_settings/components/lock_popovers_spec.js @@ -21,12 +21,12 @@ describe('LockPopovers', () => { }; if (lockedByApplicationSetting) { - popoverMountEl.setAttribute('data-popover-data', JSON.stringify(popoverData)); + popoverMountEl.dataset.popoverData = JSON.stringify(popoverData); } else if (lockedByAncestor) { - popoverMountEl.setAttribute( - 'data-popover-data', - JSON.stringify({ ...popoverData, ancestor_namespace: mockNamespace }), - ); + popoverMountEl.dataset.popoverData = JSON.stringify({ + ...popoverData, + ancestor_namespace: mockNamespace, + }); } document.body.appendChild(popoverMountEl); diff --git a/spec/frontend/code_navigation/store/actions_spec.js b/spec/frontend/code_navigation/store/actions_spec.js index c47a9e697b6ee..8eee61d1342f4 100644 --- a/spec/frontend/code_navigation/store/actions_spec.js +++ b/spec/frontend/code_navigation/store/actions_spec.js @@ -195,8 +195,8 @@ describe('Code navigation actions', () => { it('commits SET_CURRENT_DEFINITION with LSIF data', () => { target.classList.add('js-code-navigation'); - target.setAttribute('data-line-index', '0'); - target.setAttribute('data-char-index', '0'); + target.dataset.lineIndex = '0'; + target.dataset.charIndex = '0'; return testAction( actions.showDefinition, @@ -218,8 +218,8 @@ describe('Code navigation actions', () => { it('adds hll class to target element', () => { target.classList.add('js-code-navigation'); - target.setAttribute('data-line-index', '0'); - target.setAttribute('data-char-index', '0'); + target.dataset.lineIndex = '0'; + target.dataset.charIndex = '0'; return testAction( actions.showDefinition, @@ -243,8 +243,8 @@ describe('Code navigation actions', () => { it('caches current target element', () => { target.classList.add('js-code-navigation'); - target.setAttribute('data-line-index', '0'); - target.setAttribute('data-char-index', '0'); + target.dataset.lineIndex = '0'; + target.dataset.charIndex = '0'; return testAction( actions.showDefinition, diff --git a/spec/frontend/confirm_modal_spec.js b/spec/frontend/confirm_modal_spec.js index 53991349ee544..4224fb6be2a15 100644 --- a/spec/frontend/confirm_modal_spec.js +++ b/spec/frontend/confirm_modal_spec.js @@ -31,9 +31,9 @@ describe('ConfirmModal', () => { buttons.forEach((x) => { const button = document.createElement('button'); button.setAttribute('class', 'js-confirm-modal-button'); - button.setAttribute('data-path', x.path); - button.setAttribute('data-method', x.method); - button.setAttribute('data-modal-attributes', JSON.stringify(x.modalAttributes)); + button.dataset.path = x.path; + button.dataset.method = x.method; + button.dataset.modalAttributes = JSON.stringify(x.modalAttributes); button.innerHTML = 'Action'; buttonContainer.appendChild(button); }); diff --git a/spec/frontend/helpers/startup_css_helper_spec.js b/spec/frontend/helpers/startup_css_helper_spec.js index 2236b5aa261c9..05161437c2257 100644 --- a/spec/frontend/helpers/startup_css_helper_spec.js +++ b/spec/frontend/helpers/startup_css_helper_spec.js @@ -59,9 +59,10 @@ describe('waitForCSSLoaded', () => { <link href="two.css" data-startupcss="loading"> `); const events = waitForCSSLoaded(mockedCallback); - document - .querySelectorAll('[data-startupcss="loading"]') - .forEach((elem) => elem.setAttribute('data-startupcss', 'loaded')); + document.querySelectorAll('[data-startupcss="loading"]').forEach((elem) => { + // eslint-disable-next-line no-param-reassign + elem.dataset.startupcss = 'loaded'; + }); document.dispatchEvent(new CustomEvent('CSSStartupLinkLoaded')); await events; diff --git a/spec/frontend/issues/create_merge_request_dropdown_spec.js b/spec/frontend/issues/create_merge_request_dropdown_spec.js index 20b26f5abbaf4..cb7173c56a844 100644 --- a/spec/frontend/issues/create_merge_request_dropdown_spec.js +++ b/spec/frontend/issues/create_merge_request_dropdown_spec.js @@ -84,7 +84,7 @@ describe('CreateMergeRequestDropdown', () => { }); it('enables when can create confidential issue', () => { - document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true'); + document.querySelector('.js-create-mr').dataset.isConfidential = 'true'; confidentialState.selectedProject = { name: 'test' }; dropdown.enable(); @@ -93,7 +93,7 @@ describe('CreateMergeRequestDropdown', () => { }); it('does not enable when can not create confidential issue', () => { - document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true'); + document.querySelector('.js-create-mr').dataset.isConfidential = 'true'; dropdown.enable(); diff --git a/spec/frontend/labels/delete_label_modal_spec.js b/spec/frontend/labels/delete_label_modal_spec.js index 9804953894818..67220821fe083 100644 --- a/spec/frontend/labels/delete_label_modal_spec.js +++ b/spec/frontend/labels/delete_label_modal_spec.js @@ -25,11 +25,11 @@ describe('DeleteLabelModal', () => { buttons.forEach((x) => { const button = document.createElement('button'); button.setAttribute('class', 'js-delete-label-modal-button'); - button.setAttribute('data-label-name', x.labelName); - button.setAttribute('data-destroy-path', x.destroyPath); + button.dataset.labelName = x.labelName; + button.dataset.destroyPath = x.destroyPath; if (x.subjectName) { - button.setAttribute('data-subject-name', x.subjectName); + button.dataset.subjectName = x.subjectName; } button.innerHTML = 'Action'; diff --git a/spec/frontend/lazy_loader_spec.js b/spec/frontend/lazy_loader_spec.js index 3d8b0d9c30770..e0b6c7119f956 100644 --- a/spec/frontend/lazy_loader_spec.js +++ b/spec/frontend/lazy_loader_spec.js @@ -27,7 +27,7 @@ describe('LazyLoader', () => { const createLazyLoadImage = () => { const newImg = document.createElement('img'); newImg.className = 'lazy'; - newImg.setAttribute('data-src', TEST_PATH); + newImg.dataset.src = TEST_PATH; document.body.appendChild(newImg); triggerChildMutation(); @@ -108,7 +108,7 @@ describe('LazyLoader', () => { expect(LazyLoader.loadImage).toHaveBeenCalledWith(img); expect(img.getAttribute('src')).toBe(TEST_PATH); - expect(img.getAttribute('data-src')).toBe(null); + expect(img.dataset.src).toBeUndefined(); expect(img).toHaveClass('js-lazy-loaded'); }); diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js index efabe54f23841..251a8b0b7740b 100644 --- a/spec/frontend/members/index_spec.js +++ b/spec/frontend/members/index_spec.js @@ -24,7 +24,7 @@ describe('initMembersApp', () => { beforeEach(() => { el = document.createElement('div'); - el.setAttribute('data-members-data', dataAttribute); + el.dataset.membersData = dataAttribute; window.gon = { current_user_id: 123 }; }); diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js index a157cfa1c1dab..b0c9459ff4ff2 100644 --- a/spec/frontend/members/utils_spec.js +++ b/spec/frontend/members/utils_spec.js @@ -256,7 +256,7 @@ describe('Members Utils', () => { beforeEach(() => { el = document.createElement('div'); - el.setAttribute('data-members-data', dataAttribute); + el.dataset.membersData = dataAttribute; }); afterEach(() => { diff --git a/spec/frontend/notebook/cells/markdown_spec.js b/spec/frontend/notebook/cells/markdown_spec.js index 7dc6f90d20223..de415b5bfe04c 100644 --- a/spec/frontend/notebook/cells/markdown_spec.js +++ b/spec/frontend/notebook/cells/markdown_spec.js @@ -78,8 +78,8 @@ describe('Markdown component', () => { }); await nextTick(); - expect(findLink().getAttribute('data-remote')).toBe(null); - expect(findLink().getAttribute('data-type')).toBe(null); + expect(findLink().dataset.remote).toBeUndefined(); + expect(findLink().dataset.type).toBeUndefined(); }); describe('When parsing images', () => { diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index 4ecfbc5de1f46..38f29ac25596c 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -404,13 +404,13 @@ describe('Actions Notes Store', () => { beforeEach(() => { axiosMock.onDelete(endpoint).replyOnce(200, {}); - document.body.setAttribute('data-page', ''); + document.body.dataset.page = ''; }); afterEach(() => { axiosMock.restore(); - document.body.setAttribute('data-page', ''); + document.body.dataset.page = ''; }); it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', () => { @@ -440,7 +440,7 @@ describe('Actions Notes Store', () => { it('dispatches removeDiscussionsFromDiff on merge request page', () => { const note = { path: endpoint, id: 1 }; - document.body.setAttribute('data-page', 'projects:merge_requests:show'); + document.body.dataset.page = 'projects:merge_requests:show'; return testAction( actions.removeNote, @@ -473,13 +473,13 @@ describe('Actions Notes Store', () => { beforeEach(() => { axiosMock.onDelete(endpoint).replyOnce(200, {}); - document.body.setAttribute('data-page', ''); + document.body.dataset.page = ''; }); afterEach(() => { axiosMock.restore(); - document.body.setAttribute('data-page', ''); + document.body.dataset.page = ''; }); it('dispatches removeNote', () => { diff --git a/spec/frontend/performance_bar/index_spec.js b/spec/frontend/performance_bar/index_spec.js index 008961bf70937..2da176dbfe49b 100644 --- a/spec/frontend/performance_bar/index_spec.js +++ b/spec/frontend/performance_bar/index_spec.js @@ -17,11 +17,11 @@ describe('performance bar wrapper', () => { performance.getEntriesByType = jest.fn().mockReturnValue([]); peekWrapper.setAttribute('id', 'js-peek'); - peekWrapper.setAttribute('data-env', 'development'); - peekWrapper.setAttribute('data-request-id', '123'); - peekWrapper.setAttribute('data-peek-url', '/-/peek/results'); - peekWrapper.setAttribute('data-stats-url', 'https://log.gprd.gitlab.net/app/dashboards#/view/'); - peekWrapper.setAttribute('data-profile-url', '?lineprofiler=true'); + peekWrapper.dataset.env = 'development'; + peekWrapper.dataset.requestId = '123'; + peekWrapper.dataset.peekUrl = '/-/peek/results'; + peekWrapper.dataset.statsUrl = 'https://log.gprd.gitlab.net/app/dashboards#/view/'; + peekWrapper.dataset.profileUrl = '?lineprofiler=true'; mock = new MockAdapter(axios); diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js index 4639552b4d3ac..266f047e9dc91 100644 --- a/spec/frontend/search_autocomplete_spec.js +++ b/spec/frontend/search_autocomplete_spec.js @@ -53,7 +53,7 @@ describe('Search autocomplete dropdown', () => { }; const disableProjectIssues = () => { - document.querySelector('.js-search-project-options').setAttribute('data-issues-disabled', true); + document.querySelector('.js-search-project-options').dataset.issuesDisabled = true; }; // Mock `gl` object in window for dashboard specific page. App code will need it. diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js index 2c3db36d7e630..1544fed5240f5 100644 --- a/spec/frontend/user_popovers_spec.js +++ b/spec/frontend/user_popovers_spec.js @@ -22,7 +22,7 @@ describe('User Popovers', () => { const link = document.createElement('a'); link.classList.add('js-user-link'); - link.setAttribute('data-user', '1'); + link.dataset.user = '1'; return link; }; diff --git a/spec/frontend/users_select/test_helper.js b/spec/frontend/users_select/test_helper.js index 59edde48eab4c..9231e38ea9030 100644 --- a/spec/frontend/users_select/test_helper.js +++ b/spec/frontend/users_select/test_helper.js @@ -95,10 +95,10 @@ export const setAssignees = (...users) => { const input = document.createElement('input'); input.name = 'merge_request[assignee_ids][]'; input.value = user.id.toString(); - input.setAttribute('data-avatar-url', user.avatar_url); - input.setAttribute('data-name', user.name); - input.setAttribute('data-username', user.username); - input.setAttribute('data-can-merge', user.can_merge); + input.dataset.avatarUrl = user.avatar_url; + input.dataset.name = user.name; + input.dataset.username = user.username; + input.dataset.canMerge = user.can_merge; return input; }), ); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js index 8efc4d8462476..29ee7e0010fc1 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -193,9 +193,7 @@ describe('MRWidgetMerged', () => { it('shows button to copy commit SHA to clipboard', () => { expect(selectors.copyMergeShaButton).not.toBe(null); - expect(selectors.copyMergeShaButton.getAttribute('data-clipboard-text')).toBe( - vm.mr.mergeCommitSha, - ); + expect(selectors.copyMergeShaButton.dataset.clipboardText).toBe(vm.mr.mergeCommitSha); }); it('hides button to copy commit SHA if SHA does not exist', async () => { diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index 298ac764d732a..bfd921d5e4e23 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -427,7 +427,7 @@ describe('MrWidgetOptions', () => { beforeEach(() => { const favicon = document.createElement('link'); favicon.setAttribute('id', 'favicon'); - favicon.setAttribute('data-original-href', faviconDataUrl); + favicon.dataset.originalHref = faviconDataUrl; document.body.appendChild(favicon); faviconElement = document.getElementById('favicon'); diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js index 5253560c6553c..20a1e5aceb207 100644 --- a/spec/frontend_integration/ide/helpers/ide_helper.js +++ b/spec/frontend_integration/ide/helpers/ide_helper.js @@ -46,14 +46,14 @@ export const findMonacoDiffEditor = () => export const findAndSetEditorValue = async (value) => { const editor = await findMonacoEditor(); - const uri = editor.getAttribute('data-uri'); + const { uri } = editor.dataset; monacoEditor.getModel(uri).setValue(value); }; export const getEditorValue = async () => { const editor = await findMonacoEditor(); - const uri = editor.getAttribute('data-uri'); + const { uri } = editor.dataset; return monacoEditor.getModel(uri).getValue(); }; -- GitLab