diff --git a/packages/web-components/src/avatar/avatar.spec.ts b/packages/web-components/src/avatar/avatar.spec.ts new file mode 100644 index 0000000000000..5fab067f8ba0d --- /dev/null +++ b/packages/web-components/src/avatar/avatar.spec.ts @@ -0,0 +1,205 @@ +import { expect, test } from '@playwright/test'; +import type { Locator, Page } from '@playwright/test'; +import { fixtureURL } from '../helpers.tests.js'; +import { Avatar } from './avatar.js'; +import { AvatarAppearance, AvatarColor, AvatarSize } from './avatar.options.js'; + +test.describe('Avatar Component', () => { + let page: Page; + let element: Locator; + let root: Locator; + + test.beforeAll(async ({ browser }) => { + page = await browser.newPage(); + + element = page.locator('fluent-avatar'); + + root = page.locator('#root'); + + await page.goto(fixtureURL('components-avatar--avatar')); + }); + + test.afterAll(async () => { + await page.close(); + }); + + const colorAttributes = { + neutral: 'neutral', + brand: 'brand', + colorful: 'colorful', + darkRed: 'dark-red', + cranberry: 'cranberry', + red: 'red', + pumpkin: 'pumpkin', + peach: 'peach', + marigold: 'marigold', + gold: 'gold', + brass: 'brass', + brown: 'brown', + forest: 'forest', + seafoam: 'seafoam', + darkGreen: 'dark-green', + lightTeal: 'light-teal', + teal: 'teal', + steel: 'steel', + blue: 'blue', + royalBlue: 'royal-blue', + cornflower: 'cornflower', + navy: 'navy', + lavender: 'lavender', + purple: 'purple', + grape: 'grape', + lilac: 'lilac', + pink: 'pink', + magenta: 'magenta', + plum: 'plum', + beige: 'beige', + mink: 'mink', + platinum: 'platinum', + anchor: 'anchor', + }; + + const appearanceAttributes = { + ring: 'ring', + shadow: 'shadow', + ringShadow: 'ring-shadow', + }; + + const sizeAttributes = { + _16: 16, + _20: 20, + _24: 24, + _28: 28, + _32: 32, + _36: 36, + _40: 40, + _48: 48, + _56: 56, + _64: 64, + _72: 72, + _96: 96, + _120: 120, + _128: 128, + }; + + test('should render without crashing', async () => { + await page.waitForSelector('fluent-avatar'); + await expect(element).toBeVisible(); + }); + + test('When no name value is set, should render with custom initials based on the provided initials value', async () => { + await root.evaluate(node => { + node.innerHTML = /* html */ ` + + `; + }); + + await expect(element).toHaveText('JD'); + }); + + test('When name value is set, should generate initials based on the provided name value', async () => { + await root.evaluate(node => { + node.innerHTML = /* html */ ` + + `; + }); + + await expect(element).toHaveText('JD'); + }); + + test('When name value and custom initials are set, should prioritize the provided initials', async () => { + await root.evaluate(node => { + node.innerHTML = /* html */ ` + + `; + }); + + await expect(element).toHaveText('JJ'); + }); + + test('should render correctly in active state', async () => { + await element.evaluate((node: Avatar) => { + node.active = 'active'; + }); + + await expect(element).toHaveJSProperty('active', 'active'); + }); + + test('should render correctly in inactive state', async () => { + await element.evaluate((node: Avatar) => { + node.active = 'inactive'; + }); + + await expect(element).toHaveJSProperty('active', 'inactive'); + }); + + test('default color should be neutral', async () => { + await expect(element).toHaveAttribute('data-color', `neutral`); + }); + + test('should default to a specific color when "colorful" is set without name or colorId', async () => { + await element.evaluate((node: Avatar) => { + node.color = 'colorful'; + }); + const generatedColor = await element.evaluate((node: Avatar) => { + return node.generateColor(); + }); + await expect(element).toHaveAttribute('data-color', `${generatedColor}`); + }); + + test('should derive the color from the name attribute when set to "colorful"', async () => { + await root.evaluate(node => { + node.innerHTML = /* html */ ` + + `; + }); + + const generatedColor = await element.evaluate((node: Avatar) => { + return node.generateColor(); + }); + + await expect(element).toHaveAttribute('data-color', `${generatedColor}`); + }); + + test('should prioritize color derivation from colorId over name when set to "colorful"', async () => { + await root.evaluate(node => { + node.innerHTML = /* html */ ` + + `; + }); + + const generatedColor = await element.evaluate((node: Avatar) => { + return node.generateColor(); + }); + await expect(element).toHaveAttribute('data-color', `${generatedColor}`); + }); + + for (const [, value] of Object.entries(colorAttributes)) { + test(`should set the color attribute to \`${value}\` on the internal control`, async () => { + await element.evaluate((node: Avatar, colorValue: string) => { + node.color = colorValue as AvatarColor; + }, value as string); + await expect(element).toHaveJSProperty('color', `${value}`); + await expect(element).toHaveAttribute('color', `${value}`); + }); + } + for (const [, value] of Object.entries(sizeAttributes)) { + test(`should set the size attribute to \`${value}\` on the internal control`, async () => { + await element.evaluate((node: Avatar, sizeValue: number) => { + node.size = sizeValue as AvatarSize; + }, value as number); + await expect(element).toHaveJSProperty('size', value); + await expect(element).toHaveAttribute('size', `${value}`); + }); + } + for (const [, value] of Object.entries(appearanceAttributes)) { + test(`should set and reflect the appearance attribute to \`${value}\` on the internal control`, async () => { + await element.evaluate((node: Avatar, appearanceValue: string) => { + node.appearance = appearanceValue as AvatarAppearance; + }, value as string); + + await expect(element).toHaveJSProperty('appearance', `${value}`); + await expect(element).toHaveAttribute('appearance', `${value}`); + }); + } +});