From a02289ee5e783bf19569b01390e866530c60c925 Mon Sep 17 00:00:00 2001
From: v-baambati <132879294+v-baambati@users.noreply.github.com>
Date: Thu, 14 Nov 2024 16:35:10 +0530
Subject: [PATCH] Added basic test cases to donut chart (#33127)
---
.../src/donut-chart/donut-chart.spec.ts | 140 ++++
.../chart-web-components/src/helpers.tests.ts | 86 ++
.../horizontal-bar-chart.styles.ts | 2 +-
.../horizontal-bar-chart.ts | 6 +-
.../horizontalbarchart.spec.ts | 733 ++++++++++++++++++
5 files changed, 963 insertions(+), 4 deletions(-)
create mode 100644 packages/charts/chart-web-components/src/donut-chart/donut-chart.spec.ts
create mode 100644 packages/charts/chart-web-components/src/helpers.tests.ts
create mode 100644 packages/charts/chart-web-components/src/horizontal-bar-chart/horizontalbarchart.spec.ts
diff --git a/packages/charts/chart-web-components/src/donut-chart/donut-chart.spec.ts b/packages/charts/chart-web-components/src/donut-chart/donut-chart.spec.ts
new file mode 100644
index 0000000000000..1e3854cb89289
--- /dev/null
+++ b/packages/charts/chart-web-components/src/donut-chart/donut-chart.spec.ts
@@ -0,0 +1,140 @@
+import { test } from '@playwright/test';
+import { expect, fixtureURL } from '../helpers.tests.js';
+import { ChartDataPoint, ChartProps } from './donut-chart.options.js';
+import { teamsDarkTheme } from '@fluentui/tokens';
+
+const points: ChartDataPoint[] = [
+ {
+ legend: 'first',
+ data: 20000,
+ },
+ {
+ legend: 'second',
+ data: 39000,
+ },
+];
+
+const data: ChartProps = {
+ chartTitle: 'Donut chart basic example',
+ chartData: points,
+};
+
+test.describe('Donut-chart - Basic', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto(fixtureURL('components-donutchart--basic'));
+ await page.setContent(/* html */ `
+
+
+
+
+ `);
+ await page.waitForFunction(() => customElements.whenDefined('fluent-donut-chart'));
+ });
+
+ test('Should render chart properly', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const legends = element.locator('.legend-text');
+ await expect(legends.nth(0).getByText('first')).toBeVisible();
+ await expect(legends.nth(1).getByText('second')).toBeVisible();
+ await expect(element.getByText('39,000')).toBeVisible();
+ });
+
+ test('Should render path with proper attributes and css', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const arcList = element.locator('.arc');
+ await expect(arcList).toHaveCount(2);
+ await expect(arcList.nth(0)).toHaveAttribute('fill', '#637cef');
+ await expect(arcList.nth(0)).toHaveAttribute('aria-label', 'first, 20000.');
+ await expect(arcList.nth(0)).toHaveAttribute(
+ 'd',
+ 'M-76.547,47.334A90,90,0,0,1,-1.055,-89.994L-1.055,-54.99A55,55,0,0,0,-46.993,28.577Z',
+ );
+ await expect(arcList.nth(0)).toHaveCSS('fill', 'rgb(99, 124, 239)');
+ await expect(arcList.nth(0)).toHaveCSS('--borderRadiusMedium', '4px');
+
+ await expect(arcList.nth(1)).toHaveAttribute('fill', '#e3008c');
+ await expect(arcList.nth(1)).toHaveAttribute('aria-label', 'second, 39000.');
+ await expect(arcList.nth(1)).toHaveAttribute(
+ 'd',
+ 'M1.055,-89.994A90,90,0,1,1,-75.417,49.115L-45.863,30.358A55,55,0,1,0,1.055,-54.99Z',
+ );
+ await expect(arcList.nth(1)).toHaveCSS('fill', 'rgb(227, 0, 140)');
+ await expect(arcList.nth(1)).toHaveCSS('--borderRadiusMedium', '4px');
+ });
+
+ test('Should render legends data properly', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const legends = element.getByRole('option');
+ await expect(legends).toHaveCount(2);
+ const firstLegend = element.getByRole('option', { name: 'First' });
+ const secondLegend = element.getByRole('option', { name: 'Second' });
+ await expect(firstLegend).toBeVisible();
+ await expect(firstLegend).toHaveText('first');
+ await expect(firstLegend).toHaveCSS('--borderRadiusMedium', '4px');
+ await expect(secondLegend).toBeVisible();
+ await expect(secondLegend).toHaveText('second');
+ await expect(secondLegend).toHaveCSS('--borderRadiusMedium', '4px');
+ });
+
+ test('Should update path css values with mouse click event on legend', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const firstPath = element.getByLabel('first,');
+ const secondPath = element.getByLabel('second,');
+ const firstLegend = element.getByRole('option', { name: 'First' });
+ //mouse events
+ await firstLegend.click();
+ await expect(firstPath).toHaveCSS('opacity', '1');
+ await expect(secondPath).toHaveCSS('opacity', '0.1');
+ await firstLegend.click();
+ await expect(firstPath).toHaveCSS('opacity', '1');
+ await expect(secondPath).toHaveCSS('opacity', '1');
+ });
+
+ test('Should update path css values with mouse hover event on legend', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const firstPath = element.getByLabel('first,');
+ const secondPath = element.getByLabel('second,');
+ const firstLegend = element.getByRole('option', { name: 'First' });
+ //mouse events
+ await firstLegend.dispatchEvent('mouseover');
+ await expect(firstPath).toHaveCSS('opacity', '1');
+ await expect(secondPath).toHaveCSS('opacity', '0.1');
+ await firstLegend.dispatchEvent('mouseout');
+ await expect(firstPath).toHaveCSS('opacity', '1');
+ await expect(secondPath).toHaveCSS('opacity', '1');
+ });
+
+ test('Should show callout with mouse hover event on path', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const firstPath = element.getByLabel('first,');
+ const calloutRoot = element.locator('.tooltip');
+ await expect(calloutRoot).toHaveCount(0);
+ await firstPath.dispatchEvent('mouseover');
+ await expect(calloutRoot).toHaveCount(1);
+ await expect(calloutRoot).toHaveCSS('opacity', '1');
+ const calloutLegendText = await element.locator('.tooltip-legend-text');
+ await expect(calloutLegendText).toHaveText('first');
+ const calloutContentY = await element.locator('.tooltip-content-y');
+ await expect(calloutContentY).toHaveText('20000');
+ await firstPath.dispatchEvent('mouseout');
+ await expect(calloutRoot).not.toHaveCSS('opacity', '0');
+ });
+
+ test('Should update callout data when mouse moved from one path to another path', async ({ page }) => {
+ const element = page.locator('fluent-donut-chart');
+ const firstPath = element.getByLabel('first,');
+ const calloutRoot = element.locator('.tooltip');
+ await expect(calloutRoot).toHaveCount(0);
+ await firstPath.dispatchEvent('mouseover');
+ await expect(calloutRoot).toHaveCSS('opacity', '1');
+ const calloutLegendText = await element.locator('.tooltip-legend-text');
+ await expect(calloutLegendText).toHaveText('first');
+ const calloutContentY = await element.locator('.tooltip-content-y');
+ await expect(calloutContentY).toHaveText('20000');
+ const secondPath = element.getByLabel('second,');
+ await secondPath.dispatchEvent('mouseover');
+ await expect(calloutRoot).toHaveCSS('opacity', '1');
+ await expect(calloutLegendText).toHaveText('second');
+ await expect(calloutContentY).toHaveText('39000');
+ });
+});
diff --git a/packages/charts/chart-web-components/src/helpers.tests.ts b/packages/charts/chart-web-components/src/helpers.tests.ts
new file mode 100644
index 0000000000000..46d72c8403a92
--- /dev/null
+++ b/packages/charts/chart-web-components/src/helpers.tests.ts
@@ -0,0 +1,86 @@
+import qs from 'qs';
+import { expect as baseExpect, type ExpectMatcherState, type Locator } from '@playwright/test';
+
+/**
+ * Returns a formatted URL for a given Storybook fixture.
+ *
+ * @param id - the Storybook fixture ID
+ * @param args - Story args
+ * @returns - the local URL for the Storybook fixture iframe
+ */
+export function fixtureURL(id: string = 'debug--blank', args?: Record): string {
+ const params: Record = { id };
+ if (args) {
+ params.args = qs
+ .stringify(args, {
+ allowDots: true,
+ delimiter: ';',
+ format: 'RFC1738',
+ encode: false,
+ })
+ .replace(/=/g, ':')
+ .replace(/\//g, '--');
+ }
+
+ const url = qs.stringify(params, {
+ addQueryPrefix: true,
+ format: 'RFC1738',
+ encode: false,
+ });
+
+ return url;
+}
+
+/**
+ * Evaluate whether an element has the given state or not on its `elementInternals` property.
+ *
+ * @param locator - The Playwright locator for the element.
+ * @param state - The name of the state.
+ * @param expected - Whether the given state is expected to exist.
+ * @param has - Whether the element is expected to have or not have the given state, defaults to `true`.
+ */
+async function toHaveCustomState(
+ this: ExpectMatcherState,
+ locator: Locator,
+ state: string,
+ options?: { timeout?: number },
+) {
+ const assertionName = 'toHaveCustomState';
+ let pass: boolean;
+ let matcherResult: any;
+ const expected: boolean = !this.isNot;
+
+ try {
+ baseExpect(await locator.evaluate((el, state) => el.matches(`:state(${state})`), state, options)).toEqual(true);
+ pass = true;
+ } catch (err: any) {
+ matcherResult = err.matcherResult;
+ pass = false;
+ }
+
+ const message = pass
+ ? () =>
+ this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
+ '\n\n' +
+ `Locator: ${locator}\n` +
+ `Expected: ${this.isNot ? 'not' : ''}${this.utils.printExpected(expected)}\n` +
+ (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '')
+ : () =>
+ this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
+ '\n\n' +
+ `Locator: ${locator}\n` +
+ `Expected: ${this.utils.printExpected(expected)}\n` +
+ (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '');
+
+ return {
+ name: assertionName,
+ message,
+ pass,
+ expected,
+ actual: matcherResult?.actual,
+ };
+}
+
+export const expect = baseExpect.extend({
+ toHaveCustomState,
+});
diff --git a/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.styles.ts b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.styles.ts
index 5a73ea05fbb04..31d834d8defe2 100644
--- a/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.styles.ts
+++ b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.styles.ts
@@ -78,7 +78,7 @@ export const styles: ElementStyles = css`
stroke-width: 2px;
stroke: black;
}
- .svgChart {
+ .svg-chart {
display: block;
overflow: visible;
}
diff --git a/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.ts b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.ts
index 78e9faa4bff65..db6fe2f111b72 100644
--- a/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.ts
+++ b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontal-bar-chart.ts
@@ -332,7 +332,7 @@ export class HorizontalBarChart extends FASTElement {
.append('svg')
.attr('height', 12)
.attr('width', 100 + '%')
- .attr('class', 'svgChart')
+ .attr('class', 'svg-chart')
.attr('aria-label', data?.chartTitle ? data?.chartTitle : '')
.selectAll('g')
.data(data.chartData!)
@@ -372,7 +372,7 @@ export class HorizontalBarChart extends FASTElement {
.append('text')
.attr('key', 'text')
.attr('style', 'margin-top: -4.5px; margin-left: 2px;')
- .attr('class', 'barLabel')
+ .attr('class', 'bar-label')
.attr(
'x',
`${
@@ -392,7 +392,7 @@ export class HorizontalBarChart extends FASTElement {
svgEle
.append('text')
.attr('key', 'text')
- .attr('class', 'barLabel')
+ .attr('class', 'bar-label')
.attr(
'x',
`${
diff --git a/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontalbarchart.spec.ts b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontalbarchart.spec.ts
new file mode 100644
index 0000000000000..b30c81b810303
--- /dev/null
+++ b/packages/charts/chart-web-components/src/horizontal-bar-chart/horizontalbarchart.spec.ts
@@ -0,0 +1,733 @@
+import { test } from '@playwright/test';
+import { expect, fixtureURL } from '../helpers.tests.js';
+import { ChartDataPoint, ChartProps } from './horizontal-bar-chart.options.js';
+
+const chartPoints1: ChartDataPoint[] = [
+ {
+ legend: 'Debit card numbers (EU and USA)',
+ data: 40,
+ color: '#0099BC',
+ },
+ {
+ legend: 'Passport numbers (USA)',
+ data: 23,
+ color: '#77004D',
+ },
+ {
+ legend: 'Social security numbers',
+ data: 35,
+ color: '#4F68ED',
+ },
+ {
+ legend: 'Credit card Numbers',
+ data: 87,
+ color: '#AE8C00',
+ },
+ {
+ legend: 'Tax identification numbers (USA)',
+ data: 87,
+ color: '#004E8C',
+ },
+];
+
+const chartPoints2: ChartDataPoint[] = [
+ {
+ legend: 'Debit card numbers (EU and USA)',
+ data: 40,
+ color: '#0099BC',
+ },
+ {
+ legend: 'Passport numbers (USA)',
+ data: 56,
+ color: '#77004D',
+ },
+ {
+ legend: 'Social security numbers',
+ data: 35,
+ color: '#4F68ED',
+ },
+ {
+ legend: 'Credit card Numbers',
+ data: 92,
+ color: '#AE8C00',
+ },
+ {
+ legend: 'Tax identification numbers (USA)',
+ data: 87,
+ color: '#004E8C',
+ },
+];
+
+const chartPoints3: ChartDataPoint[] = [
+ {
+ legend: 'Phone Numbers',
+ data: 40,
+ color: '#881798',
+ },
+ {
+ legend: 'Credit card Numbers',
+ data: 23,
+ color: '#AE8C00',
+ },
+];
+
+const basicChartTestData: ChartProps[] = [
+ {
+ chartTitle: 'Monitored First',
+ chartData: chartPoints1,
+ },
+ {
+ chartTitle: 'Monitored Second',
+ chartData: chartPoints2,
+ },
+ {
+ chartTitle: 'Unmonitored',
+ chartData: chartPoints3,
+ },
+];
+
+const singleBarHBCData = [
+ {
+ chartTitle: 'one',
+ chartData: [
+ {
+ legend: 'one',
+ data: 1543,
+ total: 15000,
+ color: '#637cef',
+ },
+ ],
+ },
+ {
+ chartTitle: 'two',
+ chartData: [
+ {
+ legend: 'two',
+ data: 800,
+ total: 15000,
+ color: '#e3008c',
+ },
+ ],
+ },
+ {
+ chartTitle: 'three',
+ chartData: [
+ {
+ legend: 'three',
+ data: 8888,
+ total: 15000,
+ color: '#2aa0a4',
+ },
+ ],
+ },
+ {
+ chartTitle: 'four',
+ chartData: [
+ {
+ legend: 'four',
+ data: 15888,
+ total: 15000,
+ color: '#9373c0',
+ },
+ ],
+ },
+ {
+ chartTitle: 'five',
+ chartData: [
+ {
+ legend: 'five',
+ data: 11444,
+ total: 15000,
+ color: '#13a10e',
+ },
+ ],
+ },
+ {
+ chartTitle: 'six',
+ chartData: [
+ {
+ legend: 'six',
+ data: 14000,
+ total: 15000,
+ color: '#3a96dd',
+ },
+ ],
+ },
+ {
+ chartTitle: 'seven',
+ chartData: [
+ {
+ legend: 'seven',
+ data: 9855,
+ total: 15000,
+ color: '#ca5010',
+ },
+ ],
+ },
+ {
+ chartTitle: 'eight',
+ chartData: [
+ {
+ legend: 'eight',
+ data: 4250,
+ total: 15000,
+ color: '#57811b',
+ },
+ ],
+ },
+];
+
+const singleBarNMVariantData = [
+ {
+ chartTitle: 'one',
+ chartData: [
+ {
+ legend: 'one',
+ data: 1543,
+ total: 15000,
+ color: '#637cef',
+ },
+ ],
+ },
+ {
+ chartTitle: 'two',
+ chartData: [
+ {
+ legend: 'two',
+ data: 800,
+ total: 15000,
+ color: '#e3008c',
+ },
+ ],
+ },
+ {
+ chartTitle: 'three',
+ chartData: [
+ {
+ legend: 'three',
+ data: 8888,
+ total: 15000,
+ color: '#2aa0a4',
+ },
+ ],
+ },
+ {
+ chartTitle: 'four',
+ chartData: [
+ {
+ legend: 'four',
+ data: 15888,
+ total: 15000,
+ color: '#9373c0',
+ },
+ ],
+ },
+ {
+ chartTitle: 'five',
+ chartData: [
+ {
+ legend: 'five',
+ data: 11444,
+ total: 15000,
+ color: '#13a10e',
+ },
+ ],
+ },
+ {
+ chartTitle: 'six',
+ chartData: [
+ {
+ legend: 'six',
+ data: 14000,
+ total: 15000,
+ color: '#3a96dd',
+ },
+ ],
+ },
+ {
+ chartTitle: 'seven',
+ chartData: [
+ {
+ legend: 'seven',
+ data: 9855,
+ total: 15000,
+ color: '#ca5010',
+ },
+ ],
+ },
+ {
+ chartTitle: 'eight',
+ chartData: [
+ {
+ legend: 'eight',
+ data: 4250,
+ total: 15000,
+ color: '#57811b',
+ },
+ ],
+ },
+];
+
+const singlePointData = [
+ {
+ chartTitle: 'one',
+ chartData: [
+ {
+ legend: 'one',
+ data: 1543,
+ total: 15000,
+ gradient: ['#637cef', '#e3008c'],
+ },
+ ],
+ },
+];
+
+async function expectOptionsToBeVisible(
+ element: { getByRole: (arg0: string, arg1: { name: any }) => any },
+ options: string | any[],
+) {
+ for (let i = 0; i < options.length; i++) {
+ await expect(element.getByRole('option', { name: options[i] })).toBeVisible();
+ }
+}
+
+test.describe('horizontalbarchart - Basic', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto(fixtureURL('components-horizontalbarchart--basic'));
+ await page.setContent(/* html */ `
+
+
+
+
+ `);
+ await page.waitForFunction(() => customElements.whenDefined('fluent-horizontal-bar-chart'));
+ });
+
+ test('Should render horizontalbarchart properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ await expectOptionsToBeVisible(element, [
+ 'Debit card numbers (EU and USA)',
+ 'Passport numbers (USA)',
+ 'Social security numbers',
+ 'Credit card Numbers',
+ 'Phone Numbers',
+ ]);
+ await expect(page.getByText('Monitored First')).toBeVisible();
+ await expect(page.getByText('Monitored Second')).toBeVisible();
+ await expect(page.getByText('Unmonitored')).toBeVisible();
+ });
+
+ test('Should render legends data properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(6);
+ const firstLegend = legends.first();
+ await expect(firstLegend.locator('div').first()).toHaveCSS('background-color', 'rgb(0, 153, 188)');
+ await expect(firstLegend).toHaveText('Debit card numbers (EU and USA)');
+ });
+
+ test('Should update bar css/opaity when mouse hover on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(6);
+ const firstLegend = legends.first();
+ //mouse events
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(12);
+ for (let i = 0; i < (await bars.count()); i++) {
+ if (i == 0 || i == 5) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should update bar css/opaity when mouse moved from one legend to another legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(6);
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ for (let i = 0; i < (await bars.count()); i++) {
+ if (i == 0 || i == 5) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ await legends.nth(0).dispatchEvent('mouseout');
+ await legends.nth(1).dispatchEvent('mouseover');
+ for (let i = 0; i < (await bars.count()); i++) {
+ if (i == 1 || i == 6) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should show callout when mouse hover on bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('Debit card numbers (EU and USA) 40');
+ });
+
+ test('Should update callout data when mouse moved from one bar to another bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('Debit card numbers (EU and USA) 40');
+ await bars.nth(0).dispatchEvent('mouseout');
+ await bars.nth(1).dispatchEvent('mouseover');
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('Passport numbers (USA) 23');
+ });
+});
+
+test.describe('horizontalbarchart - Single Bar HBC', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto(fixtureURL('components-horizontalbarchart--single-bar-hbc'));
+ await page.setContent(/* html */ `
+
+
+
+
+ `);
+ await page.waitForFunction(() => customElements.whenDefined('fluent-horizontal-bar-chart'));
+ });
+
+ test('Should render Single Bar HBC properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ await expectOptionsToBeVisible(element, ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']);
+ const barsTitles = element.locator('.chart-title');
+ await expect(barsTitles).toHaveCount(8);
+ await expect(barsTitles.nth(0)).toHaveText('one');
+ await expect(barsTitles.nth(1)).toHaveText('two');
+ await expect(barsTitles.nth(2)).toHaveText('three');
+ await expect(barsTitles.nth(3)).toHaveText('four');
+ await expect(barsTitles.nth(4)).toHaveText('five');
+ await expect(barsTitles.nth(5)).toHaveText('six');
+ await expect(barsTitles.nth(6)).toHaveText('seven');
+ await expect(barsTitles.nth(7)).toHaveText('eight');
+ for (let i = 0; i < (await barsTitles.count()); i++) {
+ await expect(barsTitles.nth(i)).toBeVisible();
+ }
+ });
+
+ test('Should update bar css/opaity when mouse hover on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(8);
+ //mouse events
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(8);
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 0) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should update bar css/opaity when mouse moved from one legend to another legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(8);
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 0) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ await legends.nth(0).dispatchEvent('mouseout');
+ await legends.nth(1).dispatchEvent('mouseover');
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 1) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should update bar css/opaity when mouse click on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(8);
+ await legends.nth(0).click();
+ const bars = element.locator('.bar');
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 0) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ await legends.nth(0).click();
+ for (let i = 1; i < (await bars.count()); i++) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ }
+ });
+
+ test('Should show callout when mouse hover on bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ });
+
+ test('Should update callout data when mouse moved from one bar to another bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ await bars.nth(0).dispatchEvent('mouseout');
+ await bars.nth(1).dispatchEvent('mouseover');
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('two 800');
+ });
+});
+
+test.describe('horizontalbarchart - Single Bar NM Variant', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto(fixtureURL('components-horizontalbarchart--single-bar-nm-variant'));
+ await page.setContent(/* html */ `
+
+
+
+
+ `);
+ await page.waitForFunction(() => customElements.whenDefined('fluent-horizontal-bar-chart'));
+ });
+
+ test('Should render Single Bar HBC properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ await expectOptionsToBeVisible(element, ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']);
+ });
+
+ test('Should render bars and bar labels properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(16);
+ await expect(bars.nth(0)).toHaveCSS('fill', 'rgb(99, 124, 239)');
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ await expect(bars.nth(0)).toHaveAttribute(`height`, '12');
+
+ let firstBarWidth = await bars.nth(0).getAttribute('width');
+ let firstBarWidthEmptySpace = await bars.nth(1).getAttribute('width');
+ expect(parseFloat(firstBarWidth)).toBeLessThan(parseFloat(firstBarWidthEmptySpace));
+ expect(parseFloat(firstBarWidth) + parseFloat(firstBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let secondBarWidth = await bars.nth(2).getAttribute('width');
+ let secondBarWidthEmptySpace = await bars.nth(3).getAttribute('width');
+ expect(parseFloat(secondBarWidth)).toBeLessThan(parseFloat(secondBarWidthEmptySpace));
+ expect(parseFloat(secondBarWidth) + parseFloat(secondBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let thirdBarWidth = await bars.nth(4).getAttribute('width');
+ let thirdBarWidthEmptySpace = await bars.nth(5).getAttribute('width');
+ expect(parseFloat(thirdBarWidth)).toBeGreaterThan(parseFloat(thirdBarWidthEmptySpace));
+ expect(parseFloat(thirdBarWidth) + parseFloat(thirdBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let fourthBarWidth = await bars.nth(6).getAttribute('width');
+ let fourthBarWidthEmptySpace = await bars.nth(7).getAttribute('width');
+ expect(parseFloat(fourthBarWidth)).toBeGreaterThan(parseFloat(fourthBarWidthEmptySpace));
+ expect(parseFloat(fourthBarWidth) + parseFloat(fourthBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let fifthBarWidth = await bars.nth(8).getAttribute('width');
+ let fifthBarWidthEmptySpace = await bars.nth(9).getAttribute('width');
+ expect(parseFloat(fifthBarWidth)).toBeGreaterThan(parseFloat(fifthBarWidthEmptySpace));
+ expect(parseFloat(fifthBarWidth) + parseFloat(fifthBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let sixthBarWidth = await bars.nth(10).getAttribute('width');
+ let sixthBarWidthEmptySpace = await bars.nth(11).getAttribute('width');
+ expect(parseFloat(sixthBarWidth)).toBeGreaterThan(parseFloat(sixthBarWidthEmptySpace));
+ expect(parseFloat(sixthBarWidth) + parseFloat(sixthBarWidthEmptySpace)).toBeGreaterThanOrEqual(98);
+
+ let seventhBarWidth = await bars.nth(12).getAttribute('width');
+ let seventhBarWidthEmptySpace = await bars.nth(13).getAttribute('width');
+ expect(parseFloat(seventhBarWidth)).toBeGreaterThan(parseFloat(seventhBarWidthEmptySpace));
+ expect(parseFloat(seventhBarWidth) + parseFloat(seventhBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+
+ let eigthBarWidth = await bars.nth(14).getAttribute('width');
+ let eigthBarWidthEmptySpace = await bars.nth(15).getAttribute('width');
+ expect(parseFloat(eigthBarWidth)).toBeLessThan(parseFloat(eigthBarWidthEmptySpace));
+ expect(parseFloat(eigthBarWidth) + parseFloat(eigthBarWidthEmptySpace)).toBeGreaterThanOrEqual(99);
+ });
+
+ test('Should update bar css/opaity when mouse hover on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(8);
+ //mouse events
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(16);
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 0) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should update bar css/opaity when mouse moved from one legend to another legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(8);
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 0) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ await legends.nth(0).dispatchEvent('mouseout');
+ await legends.nth(1).dispatchEvent('mouseover');
+ for (let i = 1; i < (await bars.count()); i++) {
+ if (i == 2) {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '1');
+ } else {
+ await expect(bars.nth(i)).toHaveCSS('opacity', '0.1');
+ }
+ }
+ });
+
+ test('Should show callout when mouse hover on bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ });
+
+ test('Should update callout data when mouse moved from one bar to another bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ await bars.nth(0).dispatchEvent('mouseout');
+ await bars.nth(2).dispatchEvent('mouseover');
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('two 800');
+ });
+});
+
+test.describe('horizontalbarchart - Single Data Point', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto(fixtureURL('components-horizontalbarchart--single-data-point'));
+ await page.setContent(/* html */ `
+
+
+
+
+ `);
+ await page.waitForFunction(() => customElements.whenDefined('fluent-horizontal-bar-chart'));
+ });
+
+ test('Should render Single Bar HBC properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ await expect(element.getByRole('option', { name: 'one' })).toBeVisible();
+ const barsTitles = element.locator('.chart-title');
+ await expect(barsTitles).toHaveCount(1);
+ await expect(barsTitles.nth(0)).toHaveText('one');
+ await expect(barsTitles.nth(0)).toBeVisible();
+ });
+
+ test('Should render bars and bar labels properly', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(2);
+ await expect(bars.nth(0)).toHaveCSS('fill', 'url("#gradient-0-0")');
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ await expect(bars.nth(0)).toHaveAttribute(`height`, '12');
+ let firstBarWidth = await bars.nth(0).getAttribute('width');
+ let firstBarWidthEmptySpace = await bars.nth(1).getAttribute('width');
+ expect(parseFloat(firstBarWidth)).toBeLessThan(parseFloat(firstBarWidthEmptySpace));
+ expect(parseFloat(firstBarWidth) + parseFloat(firstBarWidthEmptySpace)).toBeGreaterThan(99);
+ });
+
+ test('Should update bar css/opaity when mouse hover on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await expect(legends).toHaveCount(1);
+ //mouse events
+ await legends.nth(0).dispatchEvent('mouseover');
+ const bars = element.locator('.bar');
+ await expect(bars).toHaveCount(2);
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ await expect(bars.nth(1)).toHaveCSS('opacity', '0.1');
+ });
+
+ test('Should update bar css/opaity when mouse click on legend', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const legends = element.locator('.legend');
+ await legends.nth(0).click();
+ const bars = element.locator('.bar');
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ await expect(bars.nth(1)).toHaveCSS('opacity', '0.1');
+ await legends.nth(0).click();
+ await expect(bars.nth(0)).toHaveCSS('opacity', '1');
+ await expect(bars.nth(1)).toHaveCSS('opacity', '1');
+ });
+
+ test('Should show callout when mouse hover on bar', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ });
+
+ test('Should hide callout when mouve moved to bar offset', async ({ page }) => {
+ const element = page.locator('fluent-horizontal-bar-chart');
+ const bars = element.locator('.bar');
+ const tooltip = element.locator('.tooltip');
+ await expect(tooltip).toHaveCount(0);
+ await bars.nth(0).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(1);
+ await expect(tooltip.nth(0)).toHaveCSS('opacity', '1');
+ await expect(tooltip.nth(0).locator('div').first()).toHaveText('one 1543');
+ await bars.nth(0).dispatchEvent('mouseout');
+ await bars.nth(1).dispatchEvent('mouseover');
+ await expect(tooltip).toHaveCount(0);
+ });
+});