Commit 75686c6d authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'ps-add-to-have-tracking-attributes-matcher' into 'master'

Add toHaveTrackingAttributes matcher

See merge request gitlab-org/gitlab!77679
parents 951313ad ef013e55
export * from './to_have_sprite_icon';
export * from './to_have_tracking_attributes';
export * from './to_match_interpolated_text';
import { diff } from 'jest-diff';
import { isObject, mapValues, isEqual } from 'lodash';
export const toHaveTrackingAttributes = (actual, obj) => {
if (!(actual instanceof Element)) {
return { actual, message: () => 'The received value must be an Element.', pass: false };
}
if (!isObject(obj)) {
return {
message: () => `The matching object must be an object. Found ${obj}.`,
pass: false,
};
}
const actualAttributes = mapValues(obj, (val, key) => actual.getAttribute(`data-track-${key}`));
const matcherPass = isEqual(actualAttributes, obj);
const failMessage = () => {
// We can match, but still fail because we're in a `expect...not.` context
if (matcherPass) {
return `Expected the element's tracking attributes not to match. Found that they matched ${JSON.stringify(
obj,
)}.`;
}
const objDiff = diff(actualAttributes, obj);
return `Expected the element's tracking attributes to match the given object. Diff:
${objDiff}
`;
};
return { actual, message: failMessage, pass: matcherPass };
};
import { diff } from 'jest-diff';
describe('custom matcher toHaveTrackingAttributes', () => {
const createElementWithAttrs = (attributes) => {
const el = document.createElement('div');
Object.entries(attributes).forEach(([key, value]) => {
el.setAttribute(key, value);
});
return el;
};
it('blows up if actual is not an element', () => {
expect(() => {
expect({}).toHaveTrackingAttributes({});
}).toThrow('The received value must be an Element.');
});
it('blows up if expected is not an object', () => {
expect(() => {
expect(createElementWithAttrs({})).toHaveTrackingAttributes('foo');
}).toThrow('The matching object must be an object.');
});
it('prints diff when fails', () => {
const expectedDiff = diff({ label: 'foo' }, { label: 'a' });
expect(() => {
expect(createElementWithAttrs({ 'data-track-label': 'foo' })).toHaveTrackingAttributes({
label: 'a',
});
}).toThrow(
`Expected the element's tracking attributes to match the given object. Diff:\n${expectedDiff}\n`,
);
});
describe('positive assertions', () => {
it.each`
attrs | expected
${{ 'data-track-label': 'foo' }} | ${{ label: 'foo' }}
${{ 'data-track-label': 'foo' }} | ${{}}
${{ 'data-track-label': 'foo', label: 'bar' }} | ${{ label: 'foo' }}
${{ 'data-track-label': 'foo', 'data-track-extra': '123' }} | ${{ label: 'foo', extra: '123' }}
${{ 'data-track-label': 'foo', 'data-track-extra': '123' }} | ${{ extra: '123' }}
${{ label: 'foo', extra: '123', id: '7' }} | ${{}}
`('$expected matches element with attrs $attrs', ({ attrs, expected }) => {
expect(createElementWithAttrs(attrs)).toHaveTrackingAttributes(expected);
});
});
describe('negative assertions', () => {
it.each`
attrs | expected
${{}} | ${{ label: 'foo' }}
${{ label: 'foo' }} | ${{ label: 'foo' }}
${{ 'data-track-label': 'bar', label: 'foo' }} | ${{ label: 'foo' }}
${{ 'data-track-label': 'foo' }} | ${{ extra: '123' }}
${{ 'data-track-label': 'foo', 'data-track-extra': '123' }} | ${{ label: 'foo', extra: '456' }}
${{ 'data-track-label': 'foo', 'data-track-extra': '123' }} | ${{ label: 'foo', extra: '123', action: 'click' }}
${{ label: 'foo', extra: '123', id: '7' }} | ${{ id: '7' }}
`('$expected does not match element with attrs $attrs', ({ attrs, expected }) => {
expect(createElementWithAttrs(attrs)).not.toHaveTrackingAttributes(expected);
});
});
});
......@@ -57,9 +57,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
menu.classList.add('is-over', 'is-showing-fly-out');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu',
extra: JSON.stringify({
sidebar_display: 'Expanded',
menu_display: 'Fly out',
}),
......@@ -74,9 +74,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
submenuList.classList.add('fly-out-list');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu_item',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu_item',
extra: JSON.stringify({
sidebar_display: 'Expanded',
menu_display: 'Fly out',
}),
......@@ -92,9 +92,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
menu.classList.add('active');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu',
extra: JSON.stringify({
sidebar_display: 'Expanded',
menu_display: 'Expanded',
}),
......@@ -108,9 +108,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
menu.classList.add('active');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu_item',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu_item',
extra: JSON.stringify({
sidebar_display: 'Expanded',
menu_display: 'Expanded',
}),
......@@ -131,9 +131,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
menu.classList.add('is-over', 'is-showing-fly-out');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu',
extra: JSON.stringify({
sidebar_display: 'Collapsed',
menu_display: 'Fly out',
}),
......@@ -148,9 +148,9 @@ describe('~/pages/shared/nav/sidebar_tracking.js', () => {
submenuList.classList.add('fly-out-list');
menuLink.click();
expect(menu.dataset).toMatchObject({
trackAction: 'click_menu_item',
trackExtra: JSON.stringify({
expect(menu).toHaveTrackingAttributes({
action: 'click_menu_item',
extra: JSON.stringify({
sidebar_display: 'Collapsed',
menu_display: 'Fly out',
}),
......
......@@ -2395,6 +2395,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
ansi-styles@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
......@@ -4778,6 +4783,11 @@ diff-sequences@^26.5.0:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd"
integrity sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q==
diff-sequences@^27.4.0:
version "27.4.0"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5"
integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==
diff@^3.4.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
......@@ -7253,6 +7263,16 @@ jest-diff@^26.5.2:
jest-get-type "^26.3.0"
pretty-format "^26.5.2"
jest-diff@^27.4.6:
version "27.4.6"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d"
integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w==
dependencies:
chalk "^4.0.0"
diff-sequences "^27.4.0"
jest-get-type "^27.4.0"
pretty-format "^27.4.6"
jest-docblock@^26.0.0:
version "26.0.0"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5"
......@@ -7301,6 +7321,11 @@ jest-get-type@^26.3.0:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==
jest-get-type@^27.4.0:
version "27.4.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5"
integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==
jest-haste-map@^26.5.2:
version "26.5.2"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.5.2.tgz#a15008abfc502c18aa56e4919ed8c96304ceb23d"
......@@ -9716,6 +9741,15 @@ pretty-format@^26.4.2, pretty-format@^26.5.2:
ansi-styles "^4.0.0"
react-is "^16.12.0"
pretty-format@^27.4.6:
version "27.4.6"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7"
integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==
dependencies:
ansi-regex "^5.0.1"
ansi-styles "^5.0.0"
react-is "^17.0.1"
pretty@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5"
......@@ -10103,6 +10137,11 @@ react-is@^16.12.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
read-pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment