diff --git a/change/@fluentui-web-components-f10b25db-f9c4-4ce4-a77b-5c3bdf81283e.json b/change/@fluentui-web-components-f10b25db-f9c4-4ce4-a77b-5c3bdf81283e.json new file mode 100644 index 00000000000000..0da3e221a3ffce --- /dev/null +++ b/change/@fluentui-web-components-f10b25db-f9c4-4ce4-a77b-5c3bdf81283e.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "chore: use component tag names in playwright tests", + "packageName": "@fluentui/web-components", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/web-components/playwright.config.ts b/packages/web-components/playwright.config.ts index 91b2f75a52d273..dd6a17dc3b0571 100644 --- a/packages/web-components/playwright.config.ts +++ b/packages/web-components/playwright.config.ts @@ -8,6 +8,9 @@ const config: PlaywrightTestConfig = { timeout: process.env.CI ? 10000 : 30000, use: { baseURL: 'http://localhost:5173', + contextOptions: { + reducedMotion: 'reduce', + }, }, projects: [ { @@ -20,7 +23,10 @@ const config: PlaywrightTestConfig = { }, { name: 'webkit', - use: { ...devices['Desktop Safari'] }, + use: { + ...devices['Desktop Safari'], + deviceScaleFactor: 1, + }, }, ], webServer: { diff --git a/packages/web-components/src/accordion-item/accordion-item.spec.ts b/packages/web-components/src/accordion-item/accordion-item.spec.ts index bdfbdd8761a1b4..24c38b413f461e 100644 --- a/packages/web-components/src/accordion-item/accordion-item.spec.ts +++ b/packages/web-components/src/accordion-item/accordion-item.spec.ts @@ -1,12 +1,13 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as AccordionTagName } from '../accordion/accordion.options.js'; import { AccordionItem } from './accordion-item.js'; -import { AccordionItemSize } from './accordion-item.options.js'; +import { AccordionItemSize, tagName } from './accordion-item.options.js'; test.describe('Accordion item', () => { test.use({ innerHTML: 'Hello, World!', - tagName: 'fluent-accordion-item', - waitFor: ['fluent-accordion-item'], + tagName, + waitFor: [AccordionTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -18,9 +19,9 @@ test.describe('Accordion item', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-accordion-item'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -29,12 +30,12 @@ test.describe('Accordion item', () => { const { element } = fastPage; await fastPage.setTemplate(/* html */ ` - - + <${AccordionTagName}> + <${tagName}> Heading 1
Content 1
-
-
+ + `); await expect(element).toHaveJSProperty('headinglevel', 2); @@ -78,7 +79,7 @@ test.describe('Accordion item', () => { fastPage, }) => { const { element } = fastPage; - const button = fastPage.element.locator('button'); + const button = element.locator('button'); await fastPage.setTemplate({ attributes: { disabled: true } }); @@ -95,11 +96,11 @@ test.describe('Accordion item', () => { const { element } = fastPage; await fastPage.setTemplate(/* html */ ` - - Item 1 - Item 2 - Item 3 - + <${AccordionTagName}> + <${tagName}>Item 1 + <${tagName} disabled>Item 2 + <${tagName}>Item 3 + `); const firstItem = element.nth(0); const secondItem = element.nth(1); diff --git a/packages/web-components/src/accordion/accordion.spec.ts b/packages/web-components/src/accordion/accordion.spec.ts index 679ca8713b291a..1c6ce16e4a0758 100644 --- a/packages/web-components/src/accordion/accordion.spec.ts +++ b/packages/web-components/src/accordion/accordion.spec.ts @@ -1,9 +1,21 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as AccordionItemTagName } from '../accordion-item/accordion-item.options.js'; +import { tagName } from './accordion.options.js'; test.describe('Accordion', () => { test.use({ - innerHTML: 'Hello, World!', - tagName: 'fluent-accordion', + tagName, + innerHTML: /* html */ ` + <${AccordionItemTagName} tabindex="0"> + Heading 1 +
Content 1
+ + <${AccordionItemTagName} tabindex="0"> + Heading 2 +
Content 2
+ + `, + waitFor: [AccordionItemTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -15,9 +27,9 @@ test.describe('Accordion', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-accordion'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -27,16 +39,6 @@ test.describe('Accordion', () => { await fastPage.setTemplate({ attributes: { 'expand-mode': 'multi' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); await expect(element).toHaveAttribute('expand-mode', 'multi'); @@ -44,22 +46,12 @@ test.describe('Accordion', () => { test('should open/close appropriate accordion items on Enter key in single expand mode', async ({ fastPage }) => { const { element } = fastPage; - const accordionItems = element.locator('fluent-accordion-item'); + const accordionItems = element.locator(AccordionItemTagName); const firstItem = accordionItems.nth(0); const secondItem = accordionItems.nth(1); await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 1 -
Content 1
-
- `, }); await expect(firstItem).toHaveAttribute('expanded'); @@ -81,22 +73,12 @@ test.describe('Accordion', () => { test('should open/close appropriate accordion items on Enter key in multi expand mode', async ({ fastPage }) => { const { element } = fastPage; - const accordionItems = element.locator('fluent-accordion-item'); + const accordionItems = element.locator(AccordionItemTagName); const firstItem = accordionItems.nth(0); const secondItem = accordionItems.nth(1); await fastPage.setTemplate({ attributes: { 'expand-mode': 'multi' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 1 -
Content 1
-
- `, }); await expect(firstItem).toHaveJSProperty('expanded', false); @@ -124,16 +106,6 @@ test.describe('Accordion', () => { const { element } = fastPage; await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); await expect(element).toHaveAttribute('expand-mode', 'single'); @@ -144,18 +116,7 @@ test.describe('Accordion', () => { }) => { const { element } = fastPage; - await fastPage.setTemplate({ - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, - }); + await fastPage.setTemplate(); await expect(element).toHaveJSProperty('expandmode', 'multi'); @@ -164,20 +125,10 @@ test.describe('Accordion', () => { test('should expand/collapse items when clicked in multi mode', async ({ fastPage }) => { const { element } = fastPage; - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); await fastPage.setTemplate({ attributes: { 'expand-mode': 'multi' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); await items.nth(0).click(); @@ -191,22 +142,12 @@ test.describe('Accordion', () => { test('should only have one expanded item in single mode', async ({ fastPage }) => { const { element } = fastPage; - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); const secondItem = items.nth(1); await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); await firstItem.click(); @@ -229,19 +170,9 @@ test.describe('Accordion', () => { await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); @@ -272,19 +203,9 @@ test.describe('Accordion', () => { await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); @@ -310,19 +231,9 @@ test.describe('Accordion', () => { attributes: { 'expand-mode': 'single', }, - innerHTML: /* html */ ` - - Heading 1 -
Content 1
-
- - Heading 2 -
Content 2
-
- `, }); - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); @@ -347,22 +258,22 @@ test.describe('Accordion', () => { 'expand-mode': 'single', }, innerHTML: /* html */ ` - + <${AccordionItemTagName}> Heading 1
Content 1
-
- + + <${AccordionItemTagName} expanded> Heading 2
Content 2
-
- + + <${AccordionItemTagName} expanded> Heading 3
Content 2
-
+ `, }); - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); @@ -385,22 +296,22 @@ test.describe('Accordion', () => { 'expand-mode': 'single', }, innerHTML: /* html */ ` - + <${AccordionItemTagName}> Heading 1
Content 1
-
- + + <${AccordionItemTagName} expanded disabled> Heading 2
Content 2
-
- + + <${AccordionItemTagName} expanded> Heading 3
Content 2
-
+ `, }); - const items = element.locator('fluent-accordion-item'); + const items = element.locator(AccordionItemTagName); const firstItem = items.nth(0); @@ -431,18 +342,18 @@ test.describe('Accordion', () => { await fastPage.setTemplate({ attributes: { 'expand-mode': 'single' }, innerHTML: /* html */ ` - + <${AccordionItemTagName}>
Accordion Item 1 Heading
Accordion Item 1 Content -
- + + <${AccordionItemTagName}>
Accordion Item 2 Heading
- A checkbox as content -
+ A checkbox as content + `, }); - const item = element.locator('fluent-accordion-item').nth(1); + const item = element.locator(AccordionItemTagName).nth(1); const button = item.locator('button[part="button"]'); @@ -450,7 +361,7 @@ test.describe('Accordion', () => { await expect(item).toHaveAttribute('expanded'); - const checkbox = item.locator('fluent-checkbox'); + const checkbox = item.locator('input[type="checkbox"]'); await checkbox.click(); diff --git a/packages/web-components/src/anchor-button/anchor-button.spec.ts b/packages/web-components/src/anchor-button/anchor-button.spec.ts index f0e0bd22bd21fe..e34999cea9260f 100644 --- a/packages/web-components/src/anchor-button/anchor-button.spec.ts +++ b/packages/web-components/src/anchor-button/anchor-button.spec.ts @@ -1,10 +1,10 @@ import { expect, test } from '../../test/playwright/index.js'; -import { AnchorButtonAppearance, AnchorButtonShape, AnchorButtonSize } from './anchor-button.options.js'; +import { AnchorButtonAppearance, AnchorButtonShape, AnchorButtonSize, tagName } from './anchor-button.options.js'; test.describe('Anchor Button', () => { test.use({ - innerHTML: 'Fluent Anchor Button', - tagName: 'fluent-anchor-button', + innerHTML: 'Anchor Button', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -16,9 +16,9 @@ test.describe('Anchor Button', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-anchor-button'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); diff --git a/packages/web-components/src/avatar/avatar.spec.ts b/packages/web-components/src/avatar/avatar.spec.ts index 19c236542e9b0b..0556964a2eb83e 100644 --- a/packages/web-components/src/avatar/avatar.spec.ts +++ b/packages/web-components/src/avatar/avatar.spec.ts @@ -1,9 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; -import { AvatarAppearance, AvatarColor, AvatarSize } from './avatar.options.js'; +import { AvatarAppearance, AvatarColor, AvatarSize, tagName } from './avatar.options.js'; test.describe('Avatar', () => { test.use({ - tagName: 'fluent-avatar', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -15,9 +15,9 @@ test.describe('Avatar', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-avatar'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -25,6 +25,8 @@ test.describe('Avatar', () => { test('should have a `role` of `img`', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'img'); }); @@ -37,13 +39,13 @@ test.describe('Avatar', () => { await expect(icon).toBeVisible(); await test.step('should NOT render the icon when empty elements are present in the default slot', async () => { - await fastPage.setTemplate({ innerHTML: `
\n\n` }); + await fastPage.updateTemplate(element, { innerHTML: `
\n\n` }); await expect(icon).toBeHidden(); }); await test.step('should retain comment nodes in the default slot when no name or initials are provided', async () => { - await fastPage.setTemplate({ innerHTML: `\n\n\n` }); + await fastPage.updateTemplate(element, { innerHTML: `\n\n\n` }); await expect(icon).toBeVisible(); }); @@ -102,7 +104,11 @@ test.describe('Avatar', () => { }); test('should have a data-color attribute of `neutral` when no color is provided', async ({ fastPage }) => { - await expect(fastPage.element).toHaveAttribute('data-color', 'neutral'); + const { element } = fastPage; + + await fastPage.setTemplate(); + + await expect(element).toHaveAttribute('data-color', 'neutral'); }); test('should add a data-color attribute of `brand` when `brand is provided as the color', async ({ fastPage }) => { @@ -124,9 +130,11 @@ test.describe('Avatar', () => { test('should set the `data-color` attribute to match the `color` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const color of Object.values(AvatarColor)) { await test.step(`should set the \`color\` property to \`${color}\``, async () => { - await fastPage.setTemplate({ attributes: { color } }); + await fastPage.updateTemplate(element, { attributes: { color } }); await expect(element).toHaveAttribute('color', color); @@ -143,9 +151,11 @@ test.describe('Avatar', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(AvatarSize)) { await test.step(`should set the \`size\` property to \`${size}\``, async () => { - await fastPage.setTemplate({ attributes: { size: `${size}` } }); + await fastPage.updateTemplate(element, { attributes: { size: `${size}` } }); await expect(element).toHaveAttribute('size', `${size}`); @@ -157,9 +167,11 @@ test.describe('Avatar', () => { test('should set the `appearance` property to match the `appearance` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const appearance of Object.values(AvatarAppearance)) { await test.step(appearance, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); diff --git a/packages/web-components/src/badge/badge.spec.ts b/packages/web-components/src/badge/badge.spec.ts index 4c84a7271f9782..df4ee10a746c44 100644 --- a/packages/web-components/src/badge/badge.spec.ts +++ b/packages/web-components/src/badge/badge.spec.ts @@ -1,9 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; -import { BadgeAppearance, BadgeColor, BadgeShape, BadgeSize } from './badge.options.js'; +import { BadgeAppearance, BadgeColor, BadgeShape, BadgeSize, tagName } from './badge.options.js'; test.describe('Badge', () => { test.use({ - tagName: 'fluent-badge', + tagName, innerHTML: 'Badge', }); @@ -16,9 +16,9 @@ test.describe('Badge', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-badge'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); diff --git a/packages/web-components/src/button/button.spec.ts b/packages/web-components/src/button/button.spec.ts index 77f66a0984cdb1..263a8282786752 100644 --- a/packages/web-components/src/button/button.spec.ts +++ b/packages/web-components/src/button/button.spec.ts @@ -1,8 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName } from './button.options.js'; test.describe('Button', () => { test.use({ - tagName: 'fluent-button', + tagName, innerHTML: 'Button', }); @@ -15,9 +16,9 @@ test.describe('Button', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-button'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -27,7 +28,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName}>Button
`); @@ -44,7 +45,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="button">Button
`); @@ -61,7 +62,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="reset">Button
`); @@ -75,7 +76,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="submit" name="bar" value="baz">Button
`); @@ -92,7 +93,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="submit" value="baz">Button
`); @@ -104,6 +105,8 @@ test.describe('Button', () => { test('should be focusable by default', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.focus(); await expect(element).toBeFocused(); @@ -241,12 +244,13 @@ test.describe('Button', () => { } test('should NOT receive focus when the `tabindex` is manually set to -1', async ({ fastPage, page }) => { - const element = page.locator('fluent-button', { hasText: 'Not Focusable' }); - const focusable = page.locator('fluent-button', { hasText: 'Recieves Focus' }); + const { element } = fastPage; + const focusable = element.nth(0); + const notFocusable = element.nth(1); await fastPage.setTemplate(/* html */ ` - Recieves Focus - Not Focusable + <${tagName}>Recieves Focus + <${tagName} tabindex="-1">Not Focusable `); await focusable.focus(); @@ -255,7 +259,7 @@ test.describe('Button', () => { await focusable.press('Tab'); - await expect(element).not.toBeFocused(); + await expect(notFocusable).not.toBeFocused(); }); test('should focus the element when the `autofocus` attribute is present', async ({ fastPage }) => { @@ -271,7 +275,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit">Submit Button
`); @@ -290,7 +294,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Reset Button + <${tagName} type="reset">Reset Button
`); @@ -315,7 +319,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Reset Button + <${tagName} type="reset" disabled>Reset Button
`); @@ -334,7 +338,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
Unrelated Form
- Submit Button + <${tagName} type="submit">Submit Button `); await element.click(); @@ -354,7 +358,7 @@ test.describe('Button', () => { Unrelated Form - Submit Button + <${tagName} type="reset">Submit Button `); await expect(input).toHaveValue(''); @@ -375,7 +379,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit" disabled>Submit Button
`); @@ -395,7 +399,7 @@ test.describe('Button', () => { - Submit Button + <${tagName} type="submit" form="testform">Submit Button `); await expect(page).not.toHaveURL(/foo/); @@ -410,7 +414,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit" formaction="bar">Submit Button
`); @@ -431,7 +435,7 @@ test.describe('Button', () => {
- Submit Button + <${tagName} type="submit" form="testform" formaction="bar">Submit Button `); await element.click(); @@ -446,7 +450,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit" formmethod="post">Submit Button
`); @@ -472,7 +476,7 @@ test.describe('Button', () => { - Submit Button + <${tagName} type="submit" form="testform" formmethod="post">Submit Button `); await expect(page).not.toHaveURL(/foo/); @@ -492,7 +496,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit" formenctype="plain/text">Submit Button
`); @@ -514,7 +518,7 @@ test.describe('Button', () => { - Submit Button + <${tagName} type="submit" form="testform" formenctype="plain/text">Submit Button `); await expect(page).not.toHaveURL(/foo/); @@ -529,7 +533,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Submit Button + <${tagName} type="submit" formtarget="_self">Submit Button
`); @@ -551,7 +555,7 @@ test.describe('Button', () => { - Submit Button + <${tagName} type="submit" form="testform" formtarget="_self">Submit Button `); await expect(page).not.toHaveURL(/foo/); @@ -572,7 +576,7 @@ test.describe('Button', () => { await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="submit" formnovalidate>Button
`); @@ -602,7 +606,7 @@ test.describe('Button', () => { - Button + <${tagName} type="submit" form="test-form" formnovalidate>Button `); await input.fill('foo'); @@ -620,13 +624,13 @@ test.describe('Button', () => { fastPage, page, }) => { - const button = page.locator('fluent-button'); + const button = page.locator(tagName); const input = page.locator('#text-input'); await fastPage.setTemplate(/* html */ `
- Button + <${tagName} type="submit">Button
`); @@ -648,7 +652,7 @@ test.describe('Button', () => { fastPage, page, }) => { - const button = page.locator('fluent-button'); + const button = page.locator(tagName); const input = page.locator('#text-input'); await fastPage.setTemplate(/* html */ ` @@ -656,7 +660,7 @@ test.describe('Button', () => { - Button + <${tagName} type="submit" form="test-form">Button `); await input.fill('foo'); diff --git a/packages/web-components/src/checkbox/checkbox.spec.ts b/packages/web-components/src/checkbox/checkbox.spec.ts index 0abab1d376ac14..26fbbf93209be9 100644 --- a/packages/web-components/src/checkbox/checkbox.spec.ts +++ b/packages/web-components/src/checkbox/checkbox.spec.ts @@ -1,11 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; + import type { Checkbox } from './checkbox.js'; -import { CheckboxShape, CheckboxSize } from './checkbox.options.js'; +import { CheckboxShape, CheckboxSize, tagName } from './checkbox.options.js'; test.describe('Checkbox', () => { test.use({ - tagName: 'fluent-checkbox', - waitFor: ['fluent-button'], + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -17,33 +17,37 @@ test.describe('Checkbox', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-checkbox'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); test('should have a role of `checkbox`', async ({ fastPage }) => { - await expect(fastPage.element).toHaveJSProperty('elementInternals.role', 'checkbox'); + const { element } = fastPage; + + await fastPage.setTemplate(); + + await expect(element).toHaveJSProperty('elementInternals.role', 'checkbox'); }); test('should initialize to the initial value if no value property is set', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('value', 'on'); }); test('should set the `shape` property to match the `shape` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const shape of Object.values(CheckboxShape)) { await test.step(`should set the \`shape\` property to "${shape}"`, async () => { - await fastPage.setTemplate({ - attributes: { - shape, - }, - }); + await fastPage.updateTemplate(element, { attributes: { shape } }); await expect(element).toHaveAttribute('shape', shape); @@ -55,9 +59,11 @@ test.describe('Checkbox', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(CheckboxSize)) { await test.step(`should set the \`size\` property to "${size}"`, async () => { - await fastPage.setTemplate({ attributes: { size: size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveJSProperty('size', size); @@ -69,6 +75,8 @@ test.describe('Checkbox', () => { test('should set the `ariaChecked` property equal to the `checked` property', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.ariaChecked', 'false'); await element.evaluate((node: Checkbox) => { @@ -81,6 +89,8 @@ test.describe('Checkbox', () => { test('should NOT set a default `aria-required` value when `required` is not defined', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).not.toHaveAttribute('required'); await expect(element).not.toHaveAttribute('aria-required'); @@ -89,6 +99,8 @@ test.describe('Checkbox', () => { test('should be focusable by default', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.focus(); await expect(element).toBeFocused(); @@ -109,6 +121,8 @@ test.describe('Checkbox', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Checkbox) => { node.indeterminate = true; }); @@ -125,6 +139,8 @@ test.describe('Checkbox', () => { test('should set `indeterminate` to false when the `checked` state changes via click', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Checkbox) => { node.indeterminate = true; }); @@ -142,7 +158,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -176,22 +192,26 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(''); - const value = await page.evaluate(expectedValue => { - const node = document.createElement('fluent-checkbox') as Checkbox; + const value = await page.evaluate( + ([expectedValue, tagName]) => { + const node = document.createElement(tagName) as Checkbox; - node.setAttribute('value', expectedValue); + node.setAttribute('value', expectedValue); - return node.value; - }, expectedValue); + return node.value; + }, + [expectedValue, tagName], + ); expect(value).toBe(expectedValue); }); test('should initialize to the provided `value` attribute when set post-connection', async ({ fastPage }) => { const { element } = fastPage; - const expectedValue = 'foobar'; + await fastPage.setTemplate(); + await element.evaluate((node: Checkbox, expectedValue) => { node.setAttribute('value', expectedValue); }, expectedValue); @@ -206,13 +226,16 @@ test.describe('Checkbox', () => { const expectedValue = 'foobar'; - const value = await page.evaluate(expectedValue => { - const node = document.createElement('fluent-checkbox') as Checkbox; + const value = await page.evaluate( + ([expectedValue, tagName]) => { + const node = document.createElement(tagName) as Checkbox; - node.value = expectedValue; + node.value = expectedValue; - return node.value; - }, expectedValue); + return node.value; + }, + [expectedValue, tagName], + ); expect(value).toBe(expectedValue); }); @@ -222,7 +245,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -234,7 +257,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- checkbox + <${tagName} required>checkbox
`); @@ -251,7 +274,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -276,7 +299,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -304,7 +327,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -334,7 +357,7 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="checkbox" value="foo">
`); @@ -354,8 +377,8 @@ test.describe('Checkbox', () => { await fastPage.setTemplate(/* html */ `
- - + <${tagName} name="checkbox" value="foo"> + <${tagName} name="checkbox" value="bar">
`); @@ -373,13 +396,13 @@ test.describe('Checkbox', () => { page, }) => { const { element } = fastPage; - const submitButton = page.locator('fluent-button'); + const submitButton = page.locator('button[type="submit"]'); await fastPage.setTemplate(/* html */ `
- - submit + <${tagName} required name="checkbox" id="checkbox"> +
`); diff --git a/packages/web-components/src/counter-badge/counter-badge.spec.ts b/packages/web-components/src/counter-badge/counter-badge.spec.ts index ff9cf98cd04b01..fc24a15e25f402 100644 --- a/packages/web-components/src/counter-badge/counter-badge.spec.ts +++ b/packages/web-components/src/counter-badge/counter-badge.spec.ts @@ -5,11 +5,12 @@ import { CounterBadgeColor, CounterBadgeShape, CounterBadgeSize, + tagName, } from './counter-badge.options.js'; test.describe('CounterBadge component', () => { test.use({ - tagName: 'fluent-counter-badge', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -21,9 +22,9 @@ test.describe('CounterBadge component', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-counter-badge'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -174,9 +175,11 @@ test.describe('CounterBadge component', () => { test('should set the `shape` property to match the `shape` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const shape of Object.values(CounterBadgeShape)) { await test.step(`should set the \`shape\` property to \`${shape}\``, async () => { - await fastPage.setTemplate({ attributes: { shape } }); + await fastPage.updateTemplate(element, { attributes: { shape } }); await expect(element).toHaveAttribute('shape', shape); @@ -188,9 +191,11 @@ test.describe('CounterBadge component', () => { test('should set the `color` property to match the `color` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const color of Object.values(CounterBadgeColor)) { await test.step(`should set the \`color\` property to \`${color}\``, async () => { - await fastPage.setTemplate({ attributes: { color } }); + await fastPage.updateTemplate(element, { attributes: { color } }); await expect(element).toHaveAttribute('color', color); @@ -202,9 +207,11 @@ test.describe('CounterBadge component', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(CounterBadgeSize)) { await test.step(`should set the \`size\` property to "${size}"`, async () => { - await fastPage.setTemplate({ attributes: { size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveAttribute('size', size); @@ -216,9 +223,11 @@ test.describe('CounterBadge component', () => { test('should set the `appearance` property to match the `appearance` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const appearance of Object.values(CounterBadgeAppearance)) { await test.step(appearance, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); diff --git a/packages/web-components/src/dialog/dialog.spec.ts b/packages/web-components/src/dialog/dialog.spec.ts index d5aaf22c9048ef..967a655033e40e 100644 --- a/packages/web-components/src/dialog/dialog.spec.ts +++ b/packages/web-components/src/dialog/dialog.spec.ts @@ -1,22 +1,24 @@ import type { Locator } from '@playwright/test'; import { expect, test } from '../../test/playwright/index.js'; +import { tagName as DialogBodyTagName } from '../dialog-body/dialog-body.options.js'; import type { Dialog } from './dialog.js'; +import { tagName } from './dialog.options.js'; test.describe('Dialog', () => { test.use({ - tagName: 'fluent-dialog', + tagName, innerHTML: /* html */ `
Dialog Body
`, - waitFor: ['fluent-button', 'fluent-dialog-body'], + waitFor: [DialogBodyTagName], }); async function getPointOutside(element: Locator) { // Get the bounding box of the element - const boundingBox = (await element.boundingBox()) as { x: number; y: number; width: number; height: number }; + const boundingBox = await element.boundingBox(); // Calculate a point outside the bounding box return { - x: boundingBox.x + boundingBox.width + 10, // 10 pixels to the right - y: boundingBox.y + boundingBox.height + 10, // 10 pixels below + x: boundingBox!.x + boundingBox!.width + 10, // 10 pixels to the right + y: boundingBox!.y + boundingBox!.height + 10, // 10 pixels below }; } @@ -29,9 +31,9 @@ test.describe('Dialog', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-dialog'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -40,6 +42,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const content = element.locator('#content'); + await fastPage.setTemplate(); + await test.step('should show the dialog content when the dialog is shown', async () => { await expect(content).toBeHidden(); @@ -66,6 +70,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const content = element.locator('#content'); + await fastPage.setTemplate(); + await element.evaluate((node: Dialog) => { node.show(); }); @@ -116,6 +122,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const content = element.locator('#content'); + await fastPage.setTemplate(); + await element.evaluate((node: Dialog) => { node.setAttribute('type', 'alert'); node.show(); @@ -139,6 +147,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const content = element.locator('#content'); + await fastPage.setTemplate(); + await element.evaluate((node: Dialog) => { node.show(); }); @@ -152,17 +162,17 @@ test.describe('Dialog', () => { test('should close after a button is slotted into the close slot and clicked', async ({ fastPage, page }) => { const { element } = fastPage; - const closeButton = element.locator('fluent-button[slot="close"]'); + const closeButton = element.locator('button[slot="close"]'); const content = element.locator('#content'); - await fastPage.setTemplate(/* html */ ` - - - Close -
content
-
-
- `); + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${DialogBodyTagName}> + +
content
+ + `, + }); await element.evaluate((node: Dialog) => { node.show(); @@ -177,17 +187,18 @@ test.describe('Dialog', () => { test('should NOT close after a slotted button is clicked', async ({ fastPage, page }) => { const { element } = fastPage; - const genericButton = element.locator('fluent-button'); + const genericButton = element.locator('button'); const content = element.locator('#content'); - await fastPage.setTemplate(/* html */ ` - - - Close -
content
-
-
- `); + await fastPage.setTemplate({ + attributes: { type: 'non-modal' }, + innerHTML: /* html */ ` + <${DialogBodyTagName}> + +
content
+ + `, + }); await element.evaluate((node: Dialog) => { node.show(); @@ -292,6 +303,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const dialog = element.locator('dialog'); + await fastPage.setTemplate(); + await expect(dialog).not.toHaveAttribute('aria-labelledby'); await element.evaluate(node => { @@ -307,6 +320,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const dialog = element.locator('dialog'); + await fastPage.setTemplate(); + await expect(dialog).not.toHaveAttribute('aria-describedby'); await element.evaluate(node => { @@ -322,6 +337,8 @@ test.describe('Dialog', () => { const { element } = fastPage; const dialog = element.locator('dialog'); + await fastPage.setTemplate(); + await expect(dialog).not.toHaveAttribute('aria-label'); await element.evaluate(node => { @@ -337,14 +354,14 @@ test.describe('Dialog', () => { const label = page.locator('label'); const input = page.locator('input'); - await fastPage.setTemplate(/* html */ ` - - + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${DialogBodyTagName} id="content"> - - - `); + + `, + }); await element.evaluate((node: Dialog) => { node.show(); diff --git a/packages/web-components/src/divider/divider.spec.ts b/packages/web-components/src/divider/divider.spec.ts index 1683f67aebd357..035c94ad2ddbd9 100644 --- a/packages/web-components/src/divider/divider.spec.ts +++ b/packages/web-components/src/divider/divider.spec.ts @@ -1,9 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Divider } from './divider.js'; -import { DividerAlignContent, DividerAppearance, DividerOrientation, DividerRole } from './divider.options.js'; +import { DividerAlignContent, DividerAppearance, DividerOrientation, DividerRole, tagName } from './divider.options.js'; test.describe('Divider', () => { - test.use({ tagName: 'fluent-divider' }); + test.use({ tagName }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -14,9 +14,9 @@ test.describe('Divider', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-divider'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -24,15 +24,19 @@ test.describe('Divider', () => { test('should set a default `role` attribute of "separator"', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'separator'); }); test('should set the internal `role` property to match the `role` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const role of Object.values(DividerRole)) { await test.step(`role="${role}"`, async () => { - await fastPage.setTemplate({ attributes: { role } }); + await fastPage.updateTemplate(element, { attributes: { role } }); await expect(element).toHaveJSProperty('elementInternals.role', role); }); @@ -42,9 +46,11 @@ test.describe('Divider', () => { test('should set the `aria-orientation` attribute equal to the `orientation` value', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const orientation of Object.values(DividerOrientation)) { await test.step(`orientation="${orientation}"`, async () => { - await fastPage.setTemplate({ attributes: { orientation } }); + await fastPage.updateTemplate(element, { attributes: { orientation } }); await expect(element).toHaveJSProperty('elementInternals.ariaOrientation', orientation); }); @@ -83,9 +89,11 @@ test.describe('Divider', () => { test('should initialize to the provided value attribute if set post-connection', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const alignment of Object.values(DividerAlignContent)) { await test.step(`alignContent="${alignment}"`, async () => { - await fastPage.setTemplate({ attributes: { 'align-content': alignment } }); + await fastPage.updateTemplate(element, { attributes: { 'align-content': alignment } }); await expect(element).toHaveJSProperty('alignContent', alignment); }); @@ -93,14 +101,14 @@ test.describe('Divider', () => { for (const appearance of Object.values(DividerAppearance)) { await test.step(`appearance="${appearance}"`, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); }); } await test.step('inset', async () => { - await fastPage.setTemplate({ attributes: { inset: true } }); + await fastPage.updateTemplate(element, { attributes: { inset: true } }); await expect(element).toHaveJSProperty('inset', true); }); diff --git a/packages/web-components/src/drawer/drawer.spec.ts b/packages/web-components/src/drawer/drawer.spec.ts index 60b00ce2770e6c..159706f678c3a8 100644 --- a/packages/web-components/src/drawer/drawer.spec.ts +++ b/packages/web-components/src/drawer/drawer.spec.ts @@ -1,11 +1,12 @@ import { expect, test } from '../../test/playwright/index.js'; -import type { Drawer } from './drawer.js'; -import { DrawerPosition } from './drawer.options.js'; -import { DrawerSize, DrawerType } from './drawer.options.js'; +import { tagName as DrawerBodyTagName } from '../drawer-body/drawer-body.options.js'; +import { Drawer } from './drawer.js'; +import { DrawerPosition, DrawerSize, DrawerType, tagName } from './drawer.options.js'; test.describe('Drawer', () => { test.use({ - tagName: 'fluent-drawer', + tagName, + waitFor: [DrawerBodyTagName], }); for (const type of Object.values(DrawerType)) { @@ -28,9 +29,9 @@ test.describe('Drawer', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-drawer'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -38,9 +39,11 @@ test.describe('Drawer', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(DrawerSize)) { await test.step(`should set the \`size\` property to \`${size}\``, async () => { - await fastPage.setTemplate({ attributes: { size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveAttribute('size', size); @@ -52,9 +55,11 @@ test.describe('Drawer', () => { test('should set the `position` property to match the `position` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const position of Object.values(DrawerPosition)) { await test.step(`should set the \`position\` property to \`${position}\``, async () => { - await fastPage.setTemplate({ attributes: { position } }); + await fastPage.updateTemplate(element, { attributes: { position } }); await expect(element).toHaveAttribute('position', position); @@ -122,6 +127,8 @@ test.describe('Drawer', () => { test('should emit a `toggle` event when the `show` method is called', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const wasOpened = element.evaluate( node => new Promise(resolve => node.addEventListener('toggle', () => resolve(true))), ); @@ -136,6 +143,8 @@ test.describe('Drawer', () => { test('should emit a `beforetoggle` event before open property changes', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const wasOpened = element.evaluate( node => new Promise(resolve => node.addEventListener('beforetoggle', () => resolve(true))), ); @@ -150,6 +159,8 @@ test.describe('Drawer', () => { test('should emit a `cancel` event when a `cancel` event is invoked on the document', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Drawer) => { node.show(); }); @@ -167,17 +178,17 @@ test.describe('Drawer', () => { test('should close after a button is slotted into the close slot and clicked', async ({ fastPage, page }) => { const { element } = fastPage; - const closeButton = element.locator('fluent-button[slot="close"]'); + const closeButton = element.locator('button[slot="close"]'); const content = element.locator('#content'); - await fastPage.setTemplate(/* html */ ` - - - Close -
content
-
-
- `); + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${DrawerBodyTagName}> + +
content
+ + `, + }); await element.evaluate((node: Drawer) => { node.show(); diff --git a/packages/web-components/src/dropdown/dropdown.spec.ts b/packages/web-components/src/dropdown/dropdown.spec.ts index dca5c0a00159ce..cfc2ecec632fb6 100644 --- a/packages/web-components/src/dropdown/dropdown.spec.ts +++ b/packages/web-components/src/dropdown/dropdown.spec.ts @@ -1,22 +1,25 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as ListboxTagName } from '../listbox/listbox.options.js'; +import { tagName as OptionTagName } from '../option/option.options.js'; import type { Dropdown } from './dropdown.js'; +import { tagName } from './dropdown.options.js'; test.describe('Dropdown', () => { test.use({ - tagName: 'fluent-dropdown', + tagName, innerHTML: /* html */ ` - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango">Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + `, - waitFor: ['fluent-listbox', 'fluent-option'], + waitFor: [ListboxTagName, OptionTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -28,9 +31,9 @@ test.describe('Dropdown', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-dropdown'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -38,12 +41,16 @@ test.describe('Dropdown', () => { test('should render a dropdown', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveCount(1); }); test('should render a dropdown with options', async ({ fastPage }) => { const { element } = fastPage; - const options = element.locator('fluent-option'); + const options = element.locator(OptionTagName); + + await fastPage.setTemplate(); await expect(options).toHaveCount(8); }); @@ -52,6 +59,8 @@ test.describe('Dropdown', () => { const { element } = fastPage; const button = element.locator('button'); + await fastPage.setTemplate(); + await expect(button).toHaveCount(1); }); @@ -66,7 +75,9 @@ test.describe('Dropdown', () => { test('should open the dropdown on click', async ({ fastPage }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); + + await fastPage.setTemplate(); await expect(listbox).toBeHidden(); @@ -77,9 +88,11 @@ test.describe('Dropdown', () => { test('should close the dropdown on click', async ({ fastPage }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); const button = element.locator('[role=combobox]'); + await fastPage.setTemplate(); + await button.click(); await expect(listbox).toBeVisible(); @@ -91,9 +104,11 @@ test.describe('Dropdown', () => { test('should open the dropdown when the space key is pressed', async ({ fastPage }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); const button = element.locator('[role=combobox]'); + await fastPage.setTemplate(); + await button.press(' '); await expect(listbox).toBeVisible(); @@ -101,7 +116,7 @@ test.describe('Dropdown', () => { test("should set the `name` property on options when it's set on the dropdown", async ({ fastPage }) => { const { element } = fastPage; - const options = element.locator('fluent-option'); + const options = element.locator(OptionTagName); await fastPage.setTemplate({ attributes: { name: 'fruit' } }); @@ -117,29 +132,29 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit"> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango">Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); await element.click(); - await expect(element.locator('fluent-listbox')).toBeVisible(); + await expect(element.locator(ListboxTagName)).toBeVisible(); - await element.locator('fluent-option[value=cherry]').click(); + await element.locator(`${OptionTagName}[value=cherry]`).click(); - await expect(element.locator('fluent-option[value=cherry]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=cherry]`)).toHaveJSProperty('selected', true); await submitButton.click(); @@ -152,25 +167,25 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit" disabled> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango">Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry" selected>Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); await element.click(); - await expect(element.locator('fluent-listbox')).toBeHidden(); + await expect(element.locator(ListboxTagName)).toBeHidden(); await submitButton.click(); @@ -186,25 +201,25 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit"> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango" selected>Mango + <${OptionTagName} value="kiwi" selected>Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); await element.click(); - await expect(element.locator('fluent-listbox')).toBeVisible(); + await expect(element.locator(ListboxTagName)).toBeVisible(); await submitButton.click(); @@ -222,27 +237,27 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit" multiple> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango" selected>Mango + <${OptionTagName} value="kiwi" selected>Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); - await expect(element.locator('fluent-option[value=mango]')).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=mango]')).toHaveAttribute('selected'); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveAttribute('selected'); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveAttribute('selected'); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveAttribute('selected'); await submitButton.click(); @@ -257,37 +272,37 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit"> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango" selected>Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); await element.click(); - await expect(element.locator('fluent-listbox')).toBeVisible(); + await expect(element.locator(ListboxTagName)).toBeVisible(); - await element.locator('fluent-option[value=kiwi]').click(); + await element.locator(`${OptionTagName}[value=kiwi]`).click(); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=mango]')).toHaveJSProperty('selected', false); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveJSProperty('selected', false); await resetButton.click(); - await expect(element.locator('fluent-option[value=mango]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', false); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', false); }); test('should reset the values when the form is reset and the `multiple` attribute is present', async ({ @@ -299,41 +314,41 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit" multiple> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango" selected>Mango + <${OptionTagName} value="kiwi" selected>Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); await element.click(); - await expect(element.locator('fluent-listbox')).toBeVisible(); + await expect(element.locator(ListboxTagName)).toBeVisible(); - await element.locator('fluent-option[value=apple]').click(); + await element.locator(`${OptionTagName}[value=apple]`).click(); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=mango]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=apple]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=apple]`)).toHaveJSProperty('selected', true); await resetButton.click(); - await expect(element.locator('fluent-option[value=mango]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=mango]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', true); - await expect(element.locator('fluent-option[value=apple]')).toHaveJSProperty('selected', false); + await expect(element.locator(`${OptionTagName}[value=apple]`)).toHaveJSProperty('selected', false); }); test('should display a validation message when the dropdown is required and the form is submitted without a value', async ({ @@ -342,7 +357,7 @@ test.describe('Dropdown', () => { browserName, }) => { const { element } = fastPage; - const options = element.locator('fluent-option'); + const options = element.locator(OptionTagName); const submitButton = page.locator('button[type=submit]'); const messages: Record = { @@ -354,18 +369,18 @@ test.describe('Dropdown', () => { await fastPage.setTemplate(/* html */ `
- - - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya - - + <${tagName} name="fruit" required> + <${ListboxTagName}> + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango">Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya + +
`); @@ -386,8 +401,8 @@ test.describe('Dropdown', () => { test('should select an option when the user types the value', async ({ fastPage }) => { const { element } = fastPage; const input = element.locator('input'); - const listbox = element.locator('fluent-listbox'); - const kiwiOption = element.locator('fluent-option[value=kiwi]'); + const listbox = element.locator(ListboxTagName); + const kiwiOption = element.locator(`${OptionTagName}[value=kiwi]`); await fastPage.setTemplate({ attributes: { type: 'combobox' } }); @@ -414,7 +429,7 @@ test.describe('Dropdown', () => { }) => { const { element } = fastPage; const input = element.locator('input'); - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); await fastPage.setTemplate({ attributes: { type: 'combobox' } }); @@ -441,7 +456,9 @@ test.describe('Dropdown', () => { page, }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); + + await fastPage.setTemplate(); await element.click(); @@ -464,7 +481,9 @@ test.describe('Dropdown', () => { test('should emit a `change` event when the value is confirmed by pressing Enter', async ({ fastPage }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + const listbox = element.locator(ListboxTagName); + + await fastPage.setTemplate(); await element.click(); @@ -502,6 +521,8 @@ test.describe('Dropdown', () => { test('should NOT emit a `change` event when the value is changed programmatically', async ({ fastPage, page }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((el: Dropdown) => { el.addEventListener('change', () => el.insertAdjacentText('afterend', 'changed'), { once: true }); }); @@ -514,13 +535,15 @@ test.describe('Dropdown', () => { await expect(element).toHaveJSProperty('value', 'kiwi'); - await expect(element.locator('fluent-option[value=kiwi]')).toHaveJSProperty('selected', true); + await expect(element.locator(`${OptionTagName}[value=kiwi]`)).toHaveJSProperty('selected', true); }); test('should not focus listbox when tabbing from dropdown', async ({ fastPage, page }) => { const { element } = fastPage; - const listbox = element.locator('fluent-listbox'); + await fastPage.setTemplate(); + + const listbox = element.locator(ListboxTagName); await element.focus(); await page.keyboard.press('Tab'); diff --git a/packages/web-components/src/field/field.spec.ts b/packages/web-components/src/field/field.spec.ts index fa7a2cff709a72..68edb224a408d5 100644 --- a/packages/web-components/src/field/field.spec.ts +++ b/packages/web-components/src/field/field.spec.ts @@ -1,11 +1,13 @@ import { expect, test } from '../../test/playwright/index.js'; import type { TextInput } from '../text-input/text-input.js'; +import { tagName as TextInputTagName } from '../text-input/text-input.options.js'; import type { Field } from './field.js'; +import { tagName } from './field.options.js'; test.describe('Field', () => { test.use({ - tagName: 'fluent-field', - waitFor: ['fluent-text-input'], + tagName, + waitFor: [TextInputTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -17,9 +19,9 @@ test.describe('Field', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-field'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -388,7 +390,7 @@ test.describe('Field', () => { await fastPage.setTemplate({ innerHTML: /* html */ ` - + <${TextInputTagName} id="input" slot="input" type="text">
I have no idea how you managed to do this.
`, }); diff --git a/packages/web-components/src/image/image.spec.ts b/packages/web-components/src/image/image.spec.ts index 19c5e6c068e3bd..0db5aeda36711b 100644 --- a/packages/web-components/src/image/image.spec.ts +++ b/packages/web-components/src/image/image.spec.ts @@ -1,10 +1,10 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Image } from './image.js'; -import { ImageFit, ImageShape } from './image.options.js'; +import { ImageFit, ImageShape, tagName } from './image.options.js'; test.describe('Image', () => { test.use({ - tagName: 'fluent-image', + tagName, innerHTML: /* html */ ` Short image description `, @@ -19,9 +19,9 @@ test.describe('Image', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-image'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -83,9 +83,11 @@ test.describe('Image', () => { test('should set the `fit` property to match the `fit` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const fit of Object.values(ImageFit)) { await test.step(`should set the \`fit\` property to "${fit}"`, async () => { - await fastPage.setTemplate({ attributes: { fit } }); + await fastPage.updateTemplate(element, { attributes: { fit } }); await expect(element).toHaveAttribute('fit', fit); @@ -97,9 +99,11 @@ test.describe('Image', () => { test('should set the `shape` property to match the `shape` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const shape of Object.values(ImageShape)) { await test.step(`should set the \`shape\` property to "${shape}"`, async () => { - await fastPage.setTemplate({ attributes: { shape } }); + await fastPage.updateTemplate(element, { attributes: { shape } }); await expect(element).toHaveAttribute('shape', shape); diff --git a/packages/web-components/src/label/label.spec.ts b/packages/web-components/src/label/label.spec.ts index 2dff43462aed66..56f17a8f56bfba 100644 --- a/packages/web-components/src/label/label.spec.ts +++ b/packages/web-components/src/label/label.spec.ts @@ -1,16 +1,21 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Label } from './label.js'; -import { LabelSize, LabelWeight } from './label.options.js'; +import { LabelSize, LabelWeight, tagName } from './label.options.js'; test.describe('Label', () => { - test.use({ tagName: 'fluent-label' }); + test.use({ + tagName, + innerHTML: 'Label', + }); test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(LabelSize)) { await test.step(`should set the \`size\` property to "${size}"`, async () => { - await fastPage.setTemplate({ attributes: { size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveAttribute('size', size); @@ -28,9 +33,9 @@ test.describe('Label', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-label'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -38,9 +43,11 @@ test.describe('Label', () => { test('should set the `weight` property to match the `weight` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const weight of Object.values(LabelWeight)) { await test.step(`should set the \`weight\` property to "${weight}"`, async () => { - await fastPage.setTemplate({ attributes: { weight } }); + await fastPage.updateTemplate(element, { attributes: { weight } }); await expect(element).toHaveAttribute('weight', weight); diff --git a/packages/web-components/src/link/link.spec.ts b/packages/web-components/src/link/link.spec.ts index aa6d26f2a2cd1e..877c8df6637021 100644 --- a/packages/web-components/src/link/link.spec.ts +++ b/packages/web-components/src/link/link.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '../../test/playwright/index.js'; -import type { Link } from './link.js'; -import { LinkAppearance } from './link.options.js'; +import { Link } from './link.js'; +import { LinkAppearance, tagName } from './link.options.js'; const attributes = { download: 'download', @@ -14,7 +14,9 @@ const attributes = { }; test.describe('Link', () => { - test.use({ tagName: 'fluent-link' }); + test.use({ + tagName, + }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -25,9 +27,9 @@ test.describe('Link', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-link'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -36,9 +38,11 @@ test.describe('Link', () => { const { element } = fastPage; const anchor = element.locator('a'); + await fastPage.setTemplate(); + for (const [attribute, value] of Object.entries(attributes)) { await test.step(`should set the \`${attribute}\` property to match the \`${attribute}\` attribute`, async () => { - await fastPage.setTemplate({ attributes: { [attribute]: value } }); + await fastPage.updateTemplate(element, { attributes: { [attribute]: value } }); await expect(element).toHaveAttribute(attribute, value); @@ -54,9 +58,11 @@ test.describe('Link', () => { test('should set the `appearance` property to match the `appearance` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const appearance of Object.values(LinkAppearance)) { await test.step(appearance, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); @@ -68,6 +74,8 @@ test.describe('Link', () => { test('should add an "inline" attribute when the `inline` property is true', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Link) => { node.inline = true; }); diff --git a/packages/web-components/src/listbox/listbox.spec.ts b/packages/web-components/src/listbox/listbox.spec.ts index 402f6282e8194d..ad4d49a7271e58 100644 --- a/packages/web-components/src/listbox/listbox.spec.ts +++ b/packages/web-components/src/listbox/listbox.spec.ts @@ -1,20 +1,22 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as OptionTagName } from '../option/option.options.js'; import type { Listbox } from './listbox.js'; +import { tagName } from './listbox.options.js'; test.describe('Listbox', () => { test.use({ - tagName: 'fluent-listbox', + tagName, innerHTML: /* html */ ` - Apple - Banana - Orange - Mango - Kiwi - Cherry - Grapefruit - Papaya + <${OptionTagName} value="apple">Apple + <${OptionTagName} value="banana">Banana + <${OptionTagName} value="orange">Orange + <${OptionTagName} value="mango">Mango + <${OptionTagName} value="kiwi">Kiwi + <${OptionTagName} value="cherry">Cherry + <${OptionTagName} value="grapefruit">Grapefruit + <${OptionTagName} value="papaya">Papaya `, - waitFor: ['fluent-option'], + waitFor: [OptionTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -26,9 +28,9 @@ test.describe('Listbox', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-listbox'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -75,7 +77,7 @@ test.describe('Listbox', () => { fastPage, }) => { const { element } = fastPage; - const options = element.locator('fluent-option'); + const options = element.locator(OptionTagName); await fastPage.setTemplate(); @@ -98,7 +100,7 @@ test.describe('Listbox', () => { test('should set the `ariaPosInSet` and `ariaSetSize` properties on the options', async ({ fastPage }) => { const { element } = fastPage; - const options = element.locator('fluent-option'); + const options = element.locator(OptionTagName); await fastPage.setTemplate(); @@ -113,8 +115,8 @@ test.describe('Listbox', () => { } await test.step('should update the `ariaPosInSet` and `ariaSetSize` properties when the options change', async () => { - await element.evaluate((node: Listbox) => { - const newOption = document.createElement('fluent-option'); + await element.evaluate((node: Listbox, OptionTagName) => { + const newOption = document.createElement(OptionTagName); newOption.textContent = 'New Option'; node.appendChild(newOption); @@ -122,7 +124,7 @@ test.describe('Listbox', () => { for (let i = node.children.length; i >= 0; i--) { node.appendChild(node.children[(Math.random() * i) | 0]); } - }); + }, OptionTagName); const newOptionsCount = await options.count(); diff --git a/packages/web-components/src/menu-list/menu-list.spec.ts b/packages/web-components/src/menu-list/menu-list.spec.ts index be9d7281371c3d..25372a141be4b9 100644 --- a/packages/web-components/src/menu-list/menu-list.spec.ts +++ b/packages/web-components/src/menu-list/menu-list.spec.ts @@ -1,16 +1,18 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as DividerTagName } from '../divider/divider.options.js'; import type { MenuItem } from '../menu-item/menu-item.js'; -import { MenuItemRole } from '../menu-item/menu-item.options.js'; +import { MenuItemRole, tagName as MenuItemTagName } from '../menu-item/menu-item.options.js'; +import { tagName } from './menu-list.options.js'; test.describe('MenuList', () => { test.use({ - tagName: 'fluent-menu-list', - waitFor: ['fluent-menu-item'], + tagName, + waitFor: [MenuItemTagName, DividerTagName], innerHTML: /* html */ ` - Menu item 1 - Menu item 2 - Menu item 3 - Menu item 4 + <${MenuItemTagName}>Menu item 1 + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -23,9 +25,9 @@ test.describe('MenuList', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-menu-list'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -33,34 +35,39 @@ test.describe('MenuList', () => { test('should have a role of `menu`', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'menu'); }); test('should set `tabindex` of the first focusable menu item to 0', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate(); await expect(menuItems.first()).toHaveAttribute('tabindex', '0'); }); test('should NOT set any `tabindex` on non-menu-item elements', async ({ fastPage }) => { const { element } = fastPage; + const divider = element.locator('div.divider'); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item + <${MenuItemTagName}>Menu item
Not a menu item
`, }); - const divider = element.locator('div.divider'); - await expect(divider).not.toHaveAttribute('tabindex'); }); test('should focus on first menu item when `focus()` is called', async ({ fastPage }) => { const { element } = fastPage; - const firstItem = element.locator('fluent-menu-item').first(); + const firstItem = element.locator(MenuItemTagName).first(); + + await fastPage.setTemplate(); await expect(firstItem).toHaveAttribute('tabindex', '0'); @@ -88,30 +95,29 @@ test.describe('MenuList', () => { await fastPage.setTemplate(''); - await page.evaluate(() => { - const menu = document.createElement('fluent-menu-list'); + await page.evaluate(tagName => { + const menu = document.createElement(tagName); menu.focus(); document.body.append(menu); - }); + }, tagName); await expect(element).not.toBeFocused(); }); test('should focus disabled items', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); + const firstMenuItem = menuItems.first(); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item - Menu item + <${MenuItemTagName} disabled>Menu item + <${MenuItemTagName}>Menu item `, }); - const firstMenuItem = menuItems.first(); - await expect(firstMenuItem).toHaveAttribute('disabled'); await expect(firstMenuItem).toHaveJSProperty('elementInternals.ariaDisabled', 'true'); @@ -134,16 +140,9 @@ test.describe('MenuList', () => { test('should not navigate to hidden items when changed after connection', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); - await fastPage.setTemplate({ - innerHTML: /* html */ ` - Menu item 1 - Menu item 2 - Menu item 3 - Menu item 4 - `, - }); + await fastPage.setTemplate(); await expect(menuItems).toHaveCount(4); @@ -190,14 +189,14 @@ test.describe('MenuList', () => { test('should treat all checkbox menu items as individually selectable items', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item 1 - Menu item 2 - Menu item 3 - Menu item 4 + <${MenuItemTagName} role="menuitemcheckbox">Menu item 1 + <${MenuItemTagName} role="menuitemcheckbox">Menu item 2 + <${MenuItemTagName} role="menuitemcheckbox">Menu item 3 + <${MenuItemTagName} role="menuitemcheckbox">Menu item 4 `, }); @@ -218,13 +217,13 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item 1 - Menu item 2 - Menu item 3 + <${MenuItemTagName} role="menuitemradio">Menu item 1 + <${MenuItemTagName} role="menuitemradio">Menu item 2 + <${MenuItemTagName} role="menuitemradio">Menu item 3 `, }); @@ -257,15 +256,15 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item 1 - Menu item 2 - - Menu item 3 - Menu item 4 + <${MenuItemTagName} role="menuitemradio">Menu item 1 + <${MenuItemTagName} role="menuitemradio">Menu item 2 + <${DividerTagName} role="separator"> + <${MenuItemTagName} role="menuitemradio">Menu item 3 + <${MenuItemTagName} role="menuitemradio">Menu item 4 `, }); @@ -308,7 +307,9 @@ test.describe('MenuList', () => { test('should navigate the menu on arrow up/down keys', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate(); await element.evaluate(node => { node.focus(); @@ -335,18 +336,18 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item 1 - - Menu item 1.1 - Menu item 1.2 - Menu item 1.3 - - + <${tagName} slot="submenu"> + <${MenuItemTagName}>Menu item 1.1 + <${MenuItemTagName}>Menu item 1.2 + <${MenuItemTagName}>Menu item 1.3 + + `, }); @@ -365,14 +366,14 @@ test.describe('MenuList', () => { test('should not navigate to hidden items when set before connection', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Menu item 1 - - Menu item 3 - Menu item 4 + <${MenuItemTagName}>Menu item 1 + <${MenuItemTagName} hidden="hidden">Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -403,7 +404,9 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate(); for (const item of await menuItems.all()) { await expect(item).toHaveAttribute('data-indent', '0'); @@ -414,14 +417,14 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - Menu item 2 - Menu item 3 - Menu item 4 + <${MenuItemTagName} role="menuitemcheckbox"> + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -434,14 +437,14 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - Menu item 2 - Menu item 3 - Menu item 4 + <${MenuItemTagName} role="menuitemradio"> + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -454,17 +457,17 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - + <${MenuItemTagName} role="menuitemcheckbox"> Item 1 Icon - - Menu item 2 - Menu item 3 - Menu item 4 + + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -477,14 +480,14 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Item 1 Icon - Menu item 2 - Menu item 3 - Menu item 4 + <${MenuItemTagName} role="menuitemradio"> Item 1 Icon + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 `, }); @@ -497,21 +500,21 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: '' }); - await element.evaluate(node => { + await element.evaluate((node, MenuItemTagName) => { const items = ['item 1', 'item 2', 'item 3']; items.forEach(item => { - const menuItem = document.createElement('fluent-menu-item'); + const menuItem = document.createElement(MenuItemTagName); menuItem.role = 'menuitemradio'; menuItem.textContent = item; node.append(menuItem); }); - }); + }, MenuItemTagName); - const menuItems = element.locator('fluent-menu-item'); await expect(menuItems).toHaveCount(3); for (const item of await menuItems.all()) { @@ -523,24 +526,24 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; + const menuItems = element.locator(MenuItemTagName); await fastPage.setTemplate({ innerHTML: '' }); - await element.evaluate(node => { + await element.evaluate((node, MenuItemTagName) => { const fragment = document.createDocumentFragment(); const items = ['item 1', 'item 2', 'item 3']; items.forEach(item => { - const menuItem = document.createElement('fluent-menu-item'); + const menuItem = document.createElement(MenuItemTagName); menuItem.role = 'menuitemradio'; menuItem.textContent = item; fragment.append(menuItem); }); node.append(fragment); - }); + }, MenuItemTagName); - const menuItems = element.locator('fluent-menu-item'); await expect(menuItems).toHaveCount(3); for (const item of await menuItems.all()) { @@ -552,7 +555,9 @@ test.describe('MenuList', () => { fastPage, }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate(); await test.step('all plain menuitems should start with data-indent 0', async () => { for (const item of await menuItems.all()) { @@ -561,12 +566,12 @@ test.describe('MenuList', () => { }); await test.step('appending a menuitemradio should update all items to data-indent 1', async () => { - await element.evaluate(node => { - const menuItem = document.createElement('fluent-menu-item'); + await element.evaluate((node, MenuItemTagName) => { + const menuItem = document.createElement(MenuItemTagName); menuItem.role = 'menuitemradio'; menuItem.textContent = 'Radio item'; node.append(menuItem); - }); + }, MenuItemTagName); await expect(menuItems).toHaveCount(5); @@ -589,16 +594,16 @@ test.describe('MenuList', () => { test.describe('`change` event', () => { test('should emit `change` event when `checked` property changed', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); + const menuItems = element.locator(MenuItemTagName); - await fastPage.setTemplate(/* html */ ` - - Menu Item 1 - Menu item 2 - Menu item 3 - Menu item 4 - - `); + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${MenuItemTagName} role="menuitemradio">Menu Item 1 + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 + `, + }); const [wasChanged] = await Promise.all([ menuItems @@ -616,16 +621,18 @@ test.describe('MenuList', () => { test('should emit change event when menu-item checked and unchecked', async ({ fastPage }) => { const { element } = fastPage; - const menuItems = element.locator('fluent-menu-item'); - - await fastPage.setTemplate(/* html */ ` - - Menu Item 1 - Menu item 2 - Menu item 3 - Menu item 4 - - `); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${tagName}> + <${MenuItemTagName} role="menuitemradio">Menu Item 1 + <${MenuItemTagName} checked role="menuitemradio">Menu item 2 + <${MenuItemTagName} role="menuitemradio">Menu item 3 + <${MenuItemTagName} role="menuitemradio">Menu item 4 + + `, + }); let wasChanged = menuItems.nth(0).evaluate((node: MenuItem) => { return new Promise(resolve => { diff --git a/packages/web-components/src/menu/menu.spec.ts b/packages/web-components/src/menu/menu.spec.ts index 90aa168ed5d2de..01aa6d3a6b0c4f 100644 --- a/packages/web-components/src/menu/menu.spec.ts +++ b/packages/web-components/src/menu/menu.spec.ts @@ -1,18 +1,24 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName as ButtonTagName } from '../button/button.options.js'; +import { tagName as DividerTagName } from '../divider/divider.options.js'; +import { tagName as MenuButtonTagName } from '../menu-button/menu-button.options.js'; +import { tagName as MenuItemTagName } from '../menu-item/menu-item.options.js'; +import { tagName as MenuListTagName } from '../menu-list/menu-list.options.js'; +import { tagName } from './menu.options.js'; test.describe('Menu', () => { test.use({ innerHTML: /* html */ ` - Toggle Menu - - Menu item 1 - Menu item 2 - Menu item 3 - Menu item 4 - + <${MenuButtonTagName} appearance="primary" slot="trigger">Toggle Menu + <${MenuListTagName}> + <${MenuItemTagName}>Menu item 1 + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 + `, - tagName: 'fluent-menu', - waitFor: ['fluent-menu-list', 'fluent-menu-item', 'fluent-menu-button'], + tagName, + waitFor: [MenuListTagName, MenuItemTagName, MenuButtonTagName, DividerTagName, ButtonTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -24,24 +30,28 @@ test.describe('Menu', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-menu'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); test('should have menu-list be initially hidden', async ({ fastPage }) => { const { element } = fastPage; - const menuList = element.locator('fluent-menu-list'); + const menuList = element.locator(MenuListTagName); + + await fastPage.setTemplate(); await expect(menuList).toBeHidden(); }); test('should be visible when the button is clicked', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + + await fastPage.setTemplate(); await menuButton.click(); @@ -50,8 +60,10 @@ test.describe('Menu', () => { test('should be hidden when the button is clicked again', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + + await fastPage.setTemplate(); await menuButton.click(); @@ -64,14 +76,18 @@ test.describe('Menu', () => { test('should be hidden when an item is clicked', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); - const menuItems = menuList.locator('fluent-menu-item'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); + await expect(menuItems.first()).toBeFocused(); + await menuItems.first().click(); await expect(menuList).toBeHidden(); @@ -79,15 +95,17 @@ test.describe('Menu', () => { test('should close when an item is focused and the enter key is pressed', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); - const menuItems = menuList.locator('fluent-menu-item'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); - await menuItems.first().focus(); + await expect(menuItems.first()).toBeFocused(); await page.keyboard.press('Enter'); @@ -96,15 +114,17 @@ test.describe('Menu', () => { test('should close when an item is focused and the escape key is pressed', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); - const menuItems = menuList.locator('fluent-menu-item'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); - await menuItems.first().focus(); + await expect(menuItems.first()).toBeFocused(); await page.keyboard.press('Escape'); @@ -113,13 +133,18 @@ test.describe('Menu', () => { test('should close when the mouse is clicked outside the menu', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); + await expect(menuItems.first()).toBeFocused(); + await page.mouse.click(0, 0); await expect(menuList).toBeHidden(); @@ -127,13 +152,18 @@ test.describe('Menu', () => { test('should close when the escape key is pressed', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); + await expect(menuItems.first()).toBeFocused(); + await page.keyboard.press('Escape'); await expect(menuList).toBeHidden(); @@ -141,13 +171,16 @@ test.describe('Menu', () => { test('should close when the menu list loses keyboard focus', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); - const menuItems = element.locator('fluent-menu-item'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = element.locator(MenuItemTagName); + + await fastPage.setTemplate(); await menuButton.click(); await expect(menuList).toBeVisible(); + await expect(menuItems.nth(0)).toBeFocused(); await page.keyboard.press('Tab'); @@ -157,8 +190,10 @@ test.describe('Menu', () => { test('should NOT open on hover when the `openOnHover` property is false', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + + await fastPage.setTemplate(); await expect(menuList).toBeHidden(); @@ -169,8 +204,8 @@ test.describe('Menu', () => { test('should open on hover when the `openOnHover` property is true', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); await fastPage.setTemplate({ attributes: { 'open-on-hover': true } }); @@ -183,19 +218,22 @@ test.describe('Menu', () => { test('should NOT open on context when the `openOnContext` property is false', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + + await fastPage.setTemplate(); await expect(menuList).toBeHidden(); await menuButton.click({ button: 'right' }); + await expect(menuList).toBeHidden(); }); test('should open on context when the `openOnContext` property is true', async ({ fastPage }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); await fastPage.setTemplate({ attributes: { 'open-on-context': true } }); @@ -208,67 +246,64 @@ test.describe('Menu', () => { test('should set popover attribute on slotted submenu', async ({ fastPage }) => { const { element } = fastPage; - - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list:not([slot])'); - const menuItems = menuList.locator('fluent-menu-item'); - - const submenuList = element.locator('fluent-menu-list[slot="submenu"]'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(`${MenuListTagName}:not([slot])`); + const menuItems = menuList.locator(MenuItemTagName); + const submenuList = element.locator(`${MenuListTagName}[slot="submenu"]`); await fastPage.setTemplate({ innerHTML: /* html */ ` - Toggle Menu - - + <${MenuButtonTagName} appearance="primary" slot="trigger">Toggle Menu + <${MenuListTagName}> + <${MenuItemTagName}> Menu item 1 - - Subitem 1 - Subitem 2 - Subitem 3 - - - Menu item 2 - Menu item 3 - Menu item 4 - + <${MenuListTagName} slot="submenu"> + <${MenuItemTagName}> Subitem 1 + <${MenuItemTagName}> Subitem 2 + <${MenuItemTagName}> Subitem 3 + + + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 + `, }); await menuButton.click(); - await menuItems.first().focus(); + await expect(menuItems.first()).toBeFocused(); await element.press('ArrowRight'); await expect(submenuList).toBeVisible(); + await expect(submenuList).toHaveAttribute('popover'); }); test('should focus the first item when a submenu is closed', async ({ fastPage }) => { const { element } = fastPage; - - const menuButton = element.locator('fluent-menu-button'); - const menuList = element.locator('fluent-menu-list:not([slot])'); - const menuItems = menuList.locator('fluent-menu-item'); - - const submenuList = element.locator('fluent-menu-list[slot="submenu"]'); + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(`${MenuListTagName}:not([slot])`); + const menuItems = menuList.locator(MenuItemTagName); + const submenuList = element.locator(`${MenuListTagName}[slot="submenu"]`); await fastPage.setTemplate({ innerHTML: /* html */ ` - Toggle Menu - - + <${MenuButtonTagName} appearance="primary" slot="trigger">Toggle Menu + <${MenuListTagName}> + <${MenuItemTagName}> Menu item 1 - - Subitem 1 - Subitem 2 - Subitem 3 - - - Menu item 2 - Menu item 3 - Menu item 4 - + <${MenuListTagName} slot="submenu"> + <${MenuItemTagName}> Subitem 1 + <${MenuItemTagName}> Subitem 2 + <${MenuItemTagName}> Subitem 3 + + + <${MenuItemTagName}>Menu item 2 + <${MenuItemTagName}>Menu item 3 + <${MenuItemTagName}>Menu item 4 + `, }); @@ -278,7 +313,7 @@ test.describe('Menu', () => { await expect(submenuList).toBeHidden(); - await menuItems.first().focus(); + await expect(menuItems.first()).toBeFocused(); await element.press('ArrowRight'); @@ -295,38 +330,42 @@ test.describe('Menu', () => { test('should focus trigger after menu is closed', async ({ fastPage, page }) => { const { element } = fastPage; - const menuButton = element.locator('fluent-menu-button'); - - await fastPage.setTemplate(/* html */ ` - - - Primary Action - - + const menuButton = element.locator(MenuButtonTagName); + const menuList = element.locator(MenuListTagName); + const menuItems = menuList.locator(MenuItemTagName); + + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${MenuButtonTagName} appearance="primary" slot="trigger" icon-only> + <${ButtonTagName} appearance="primary" slot="primary-action">Primary Action + <${MenuListTagName}> + <${MenuItemTagName}> Item 1 - - Subitem 1 - Subitem 2 - - + <${MenuListTagName} slot="submenu"> + <${MenuItemTagName}> Subitem 1 + <${MenuItemTagName}> Subitem 2 + + - Item 2 - Item 3 + <${MenuItemTagName} role="menuitemcheckbox"> Item 2 + <${MenuItemTagName} role="menuitemcheckbox"> Item 3 - + <${DividerTagName} role="separator" aria-orientation="horizontal" orientation="horizontal"> - Menu item 4 - Menu item 5 - Menu item 6 + <${MenuItemTagName}>Menu item 4 + <${MenuItemTagName}>Menu item 5 + <${MenuItemTagName}>Menu item 6 - Menu item 7 - Menu item 8 - - - `); + <${MenuItemTagName}>Menu item 7 + <${MenuItemTagName}>Menu item 8 + + `, + }); await menuButton.click(); + await expect(menuItems.nth(0)).toBeFocused(); + await page.keyboard.press('Escape'); await expect(menuButton).toBeFocused(); diff --git a/packages/web-components/src/message-bar/message-bar.spec.ts b/packages/web-components/src/message-bar/message-bar.spec.ts index e255b2d3b73c91..907210cc913d92 100644 --- a/packages/web-components/src/message-bar/message-bar.spec.ts +++ b/packages/web-components/src/message-bar/message-bar.spec.ts @@ -1,11 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; import type { MessageBar } from './message-bar.js'; -import { MessageBarIntent, MessageBarLayout, MessageBarShape } from './message-bar.options.js'; +import { MessageBarIntent, MessageBarLayout, MessageBarShape, tagName } from './message-bar.options.js'; test.describe('Message Bar', () => { test.use({ - tagName: 'fluent-message-bar', - waitFor: ['fluent-button'], + tagName, + innerHTML: 'Message Bar', }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -17,9 +17,9 @@ test.describe('Message Bar', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-message-bar'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -27,15 +27,19 @@ test.describe('Message Bar', () => { test('should include a role of status', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'status'); }); test('should set the `intent` property to match the `intent` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const intent of Object.values(MessageBarIntent)) { await test.step(intent, async () => { - await fastPage.setTemplate({ attributes: { intent } }); + await fastPage.updateTemplate(element, { attributes: { intent } }); await expect(element).toHaveJSProperty('intent', intent); @@ -47,9 +51,11 @@ test.describe('Message Bar', () => { test('should set the `shape` property to match the `shape` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const shape of Object.values(MessageBarShape)) { await test.step(shape, async () => { - await fastPage.setTemplate({ attributes: { shape } }); + await fastPage.updateTemplate(element, { attributes: { shape } }); await expect(element).toHaveJSProperty('shape', shape); @@ -58,13 +64,14 @@ test.describe('Message Bar', () => { } }); - // @FIXME: This test is failing on OSX - https://github.com/microsoft/fluentui/issues/33172 test('should set the `layout` property to match the `layout` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const layout of Object.values(MessageBarLayout)) { await test.step(layout, async () => { - await fastPage.setTemplate({ attributes: { layout } }); + await fastPage.updateTemplate(element, { attributes: { layout } }); await expect(element).toHaveJSProperty('layout', layout); @@ -76,6 +83,8 @@ test.describe('Message Bar', () => { test('should emit a `dismiss` event when `dismissMessageBar()` is called', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const didDismiss = element.evaluate( node => new Promise(resolve => node.addEventListener('dismiss', () => resolve(true))), ); diff --git a/packages/web-components/src/option/option.spec.ts b/packages/web-components/src/option/option.spec.ts index 13574e5ca3869f..f7617f3ca42f81 100644 --- a/packages/web-components/src/option/option.spec.ts +++ b/packages/web-components/src/option/option.spec.ts @@ -1,9 +1,10 @@ import { expect, test } from '../../test/playwright/index.js'; import type { DropdownOption } from './option.js'; +import { tagName } from './option.options.js'; test.describe('DropdownOption', () => { test.use({ - tagName: 'fluent-option', + tagName, innerHTML: 'Option', }); @@ -16,9 +17,9 @@ test.describe('DropdownOption', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-option'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -160,7 +161,7 @@ test.describe('DropdownOption', () => { await fastPage.setTemplate(/* html */ `
- Hello + <${tagName} name="option" value="hello" selected>Hello
`); diff --git a/packages/web-components/src/progress-bar/progress-bar.spec.ts b/packages/web-components/src/progress-bar/progress-bar.spec.ts index fa6f1823f02960..66e5bab756af15 100644 --- a/packages/web-components/src/progress-bar/progress-bar.spec.ts +++ b/packages/web-components/src/progress-bar/progress-bar.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '../../test/playwright/index.js'; import type { ProgressBar } from './progress-bar.js'; -import { ProgressBarShape, ProgressBarThickness, ProgressBarValidationState } from './progress-bar.options.js'; +import { ProgressBarShape, ProgressBarThickness, ProgressBarValidationState, tagName } from './progress-bar.options.js'; interface BoundingBox { width: number; @@ -8,7 +8,7 @@ interface BoundingBox { test.describe('Progress Bar', () => { test.use({ - tagName: 'fluent-progress-bar', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -20,9 +20,9 @@ test.describe('Progress Bar', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-progress-bar'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -30,6 +30,8 @@ test.describe('Progress Bar', () => { test('should include a role of progressbar', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'progressbar'); }); @@ -59,6 +61,9 @@ test.describe('Progress Bar', () => { test('should set indicator width to be 1/3 of the container width if `value` is missing', async ({ fastPage }) => { const { element } = fastPage; + + await fastPage.setTemplate(); + await element.evaluate(node => { node.style.setProperty('width', '100px'); }); diff --git a/packages/web-components/src/radio-group/radio-group.spec.ts b/packages/web-components/src/radio-group/radio-group.spec.ts index 56dea1212bc9ff..6b581d079c232b 100644 --- a/packages/web-components/src/radio-group/radio-group.spec.ts +++ b/packages/web-components/src/radio-group/radio-group.spec.ts @@ -1,12 +1,13 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Radio } from '../radio/index.js'; +import { tagName as RadioTagName } from '../radio/radio.options.js'; import type { RadioGroup } from './radio-group.js'; +import { tagName } from './radio-group.options.js'; test.describe('RadioGroup', () => { test.use({ - tagName: 'fluent-radio-group', - waitFor: ['fluent-radio'], - innerHTML: '', + tagName, + waitFor: [RadioTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -18,9 +19,9 @@ test.describe('RadioGroup', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-radio-group'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -67,13 +68,13 @@ test.describe('RadioGroup', () => { test('should set the `aria-setsize` and `aria-posinset` attributes on the radios', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> `, }); @@ -91,16 +92,16 @@ test.describe('RadioGroup', () => { fastPage, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); const firstRadio = radios.nth(0); const secondRadio = radios.nth(1); const thirdRadio = radios.nth(2); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName}> + <${RadioTagName} disabled> + <${RadioTagName}> `, }); @@ -133,11 +134,11 @@ test.describe('RadioGroup', () => { await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName} disabled> + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> + `); @@ -154,16 +155,16 @@ test.describe('RadioGroup', () => { test('should NOT be focusable via click when disabled', async ({ fastPage, page }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); const button = page.locator('button', { hasText: 'Button' }); await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName}> + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> + `); await button.focus(); @@ -200,16 +201,16 @@ test.describe('RadioGroup', () => { test('should set tabindex of 0 to a child radio with a matching `value`', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ attributes: { value: 'foo', }, innerHTML: /* html */ ` - - - + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> `, }); @@ -218,13 +219,13 @@ test.describe('RadioGroup', () => { test("should set tabindex of 0 to a child radio that's initially checked", async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar" checked> + <${RadioTagName} value="baz"> `, }); @@ -233,13 +234,13 @@ test.describe('RadioGroup', () => { test('should check the first radio with a matching `value`', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ ` - - - - + <${tagName} value="bar"> + <${RadioTagName} id="radio-1" name="radio" value="foo"> + <${RadioTagName} id="radio-2" name="radio" value="bar"> + <${RadioTagName} id="radio-3" name="radio" value="baz"> `); await expect(radios.nth(0)).toHaveJSProperty('checked', false); @@ -254,14 +255,14 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName}> + <${RadioTagName} id="radio-1" name="radio" value="foo"> + <${RadioTagName} id="radio-2" name="radio" value="bar"> + <${RadioTagName} id="radio-3" name="radio" value="baz"> + `); await radios.nth(0).evaluate((node: Radio) => { @@ -283,16 +284,16 @@ test.describe('RadioGroup', () => { }); test('should emit `change` event when using keyboard', async ({ fastPage, page }) => { - const element = page.locator('fluent-radio-group'); - const radios = element.locator('fluent-radio'); + const element = page.locator(tagName); + const radios = element.locator(RadioTagName); - await fastPage.setTemplate(/* html */ ` - - - - - - `); + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${RadioTagName} id="radio-1" name="radio" value="foo"> + <${RadioTagName} id="radio-2" name="radio" value="bar"> + <${RadioTagName} id="radio-3" name="radio" value="baz"> + `, + }); const wasChanged = element.evaluate((node: RadioGroup) => { return new Promise(resolve => { @@ -308,16 +309,16 @@ test.describe('RadioGroup', () => { test('should set a child radio with a matching `value` to `checked` when value changes', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ attributes: { value: 'foo', }, innerHTML: /* html */ ` - - - + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> `, }); @@ -334,13 +335,13 @@ test.describe('RadioGroup', () => { test('should mark only the last radio defaulted to checked as checked', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} value="foo" checked> + <${RadioTagName} value="bar" checked> + <${RadioTagName} value="baz" checked> `, }); @@ -355,14 +356,14 @@ test.describe('RadioGroup', () => { test('should mark radio matching value on radio-group over any checked attributes', async ({ fastPage }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ attributes: { value: 'foo' }, innerHTML: /* html */ ` - - - + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar" checked> + <${RadioTagName} value="baz"> `, }); @@ -379,15 +380,15 @@ test.describe('RadioGroup', () => { test('should allow resetting of elements by the parent form', async ({ fastPage, page }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ `
- - - - - + <${tagName}> + <${RadioTagName} name="radio" value="foo"> + <${RadioTagName} name="radio" value="bar" checked> + <${RadioTagName} name="radio" value="baz"> +
`); @@ -420,13 +421,13 @@ test.describe('RadioGroup', () => { test('should focus the first radio when the radio group is focused', async ({ fastPage, page }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> `, }); @@ -440,13 +441,13 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} disabled> + <${RadioTagName}> + <${RadioTagName}> `, }); @@ -460,13 +461,13 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} disabled> + <${RadioTagName} disabled> + <${RadioTagName}> `, }); @@ -483,9 +484,9 @@ test.describe('RadioGroup', () => { await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} disabled> + <${RadioTagName} disabled> + <${RadioTagName} disabled> `, }); @@ -494,21 +495,20 @@ test.describe('RadioGroup', () => { await expect(element).not.toBeFocused(); }); - // @FIXME: This test is failing on OSX - https://github.com/microsoft/fluentui/issues/33172 test('should move focus to the next radio when the radio group is focused and the arrow down key is pressed', async ({ fastPage, page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName}> + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> + `); await page.getByTestId('before').focus(); @@ -540,9 +540,9 @@ test.describe('RadioGroup', () => { await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} name="foo"> + <${RadioTagName} name="foo"> + <${RadioTagName} name="foo"> `, }); @@ -556,28 +556,27 @@ test.describe('RadioGroup', () => { await fastPage.setTemplate({ innerHTML: /* html */ ` - - - + <${RadioTagName} name="foo"> + <${RadioTagName} name="bar"> + <${RadioTagName} name="baz"> `, }); await expect(element).not.toHaveAttribute('name'); }); - // @FIXME: This test is failing on OSX - https://github.com/microsoft/fluentui/issues/33172 test('should set the `name` attribute of the radios to the `name` attribute of the radio group', async ({ fastPage, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ attributes: { name: 'foo' }, innerHTML: /* html */ ` - - - + <${RadioTagName}> + <${RadioTagName}> + <${RadioTagName}> `, }); @@ -592,14 +591,14 @@ test.describe('RadioGroup', () => { fastPage, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate({ attributes: { name: 'foo' }, innerHTML: /* html */ ` - - - + <${RadioTagName} name="bar"> + <${RadioTagName} name="baz"> + <${RadioTagName} name="qux"> `, }); @@ -617,15 +616,15 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ `
- - - - - + <${tagName} name="radio"> + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> +
`); @@ -644,15 +643,15 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ `
- - - - - + <${tagName} name="radio" disabled> + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> +
`); @@ -671,15 +670,15 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); await fastPage.setTemplate(/* html */ `
- - - - - + <${tagName}> + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> +
`); @@ -699,7 +698,7 @@ test.describe('RadioGroup', () => { }) => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="radio" value="foo">
`); @@ -716,16 +715,16 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); const button = page.locator('button'); await fastPage.setTemplate(/* html */ `
- - - - - + <${tagName} name="radio"> + <${RadioTagName} disabled value="foo"> + <${RadioTagName} disabled value="bar"> + <${RadioTagName} disabled value="baz"> +
`); @@ -744,16 +743,16 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); const before = page.getByTestId('before'); await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName} name="radio"> + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> + `); await before.focus(); @@ -771,16 +770,16 @@ test.describe('RadioGroup', () => { page, }) => { const { element } = fastPage; - const radios = element.locator('fluent-radio'); + const radios = element.locator(RadioTagName); const before = page.getByTestId('before'); await fastPage.setTemplate(/* html */ ` - - - - - + <${tagName} name="radio"> + <${RadioTagName} value="foo"> + <${RadioTagName} value="bar"> + <${RadioTagName} value="baz"> + `); await before.focus(); diff --git a/packages/web-components/src/radio/radio.spec.ts b/packages/web-components/src/radio/radio.spec.ts index e66920b60ab9da..7d329a057054de 100644 --- a/packages/web-components/src/radio/radio.spec.ts +++ b/packages/web-components/src/radio/radio.spec.ts @@ -1,8 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Radio } from './radio.js'; +import { tagName } from './radio.options.js'; test.describe('Radio', () => { - test.use({ tagName: 'fluent-radio' }); + test.use({ + tagName, + }); test('should have a role of `radio`', async ({ fastPage }) => { const { element } = fastPage; @@ -21,9 +24,9 @@ test.describe('Radio', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-radio'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -87,12 +90,12 @@ test.describe('Radio', () => { test('should initialize to the provided value attribute if set pre-connection', async ({ fastPage, page }) => { await fastPage.setTemplate(''); - const value = await page.evaluate(() => { - const radio = document.createElement('fluent-radio') as Radio; + const value = await page.evaluate(tagName => { + const radio = document.createElement(tagName) as Radio; radio.setAttribute('value', 'foo'); return radio.value; - }); + }, tagName); expect(value).toBe('foo'); }); @@ -157,7 +160,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- Radio + <${tagName}>Radio
`); @@ -180,7 +183,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} checked>
`); @@ -212,7 +215,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- Radio + <${tagName}>Radio
`); @@ -242,7 +245,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -267,7 +270,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -295,7 +298,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -325,7 +328,7 @@ test.describe('Radio', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="radio" value="foo">
`); diff --git a/packages/web-components/src/rating-display/rating-display.spec.ts b/packages/web-components/src/rating-display/rating-display.spec.ts index 388350316676ea..d21bac63afafe8 100644 --- a/packages/web-components/src/rating-display/rating-display.spec.ts +++ b/packages/web-components/src/rating-display/rating-display.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '../../test/playwright/index.js'; -import { RatingDisplaySize } from './rating-display.options.js'; import type { RatingDisplay } from './rating-display.js'; +import { RatingDisplaySize, tagName } from './rating-display.options.js'; function encodedSvg(str: string, browserName: string) { return encodeURIComponent(str) @@ -10,7 +10,7 @@ function encodedSvg(str: string, browserName: string) { test.describe('Rating Display', () => { test.use({ - tagName: 'fluent-rating-display', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -22,15 +22,18 @@ test.describe('Rating Display', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-rating-display'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); test('should not set any default attributes and custom states', async ({ fastPage }) => { const { element } = fastPage; + + await fastPage.setTemplate(); + await expect(element).toBeVisible(); for (const attribute of ['color', 'compact', 'count', 'icon-view-box', 'max', 'size']) { await expect(element).not.toHaveAttribute(attribute); diff --git a/packages/web-components/src/slider/slider.spec.ts b/packages/web-components/src/slider/slider.spec.ts index e49fa9e18ef10d..01b35c8aa758e6 100644 --- a/packages/web-components/src/slider/slider.spec.ts +++ b/packages/web-components/src/slider/slider.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Slider } from './slider.js'; -import { SliderSize } from './slider.options.js'; +import { SliderSize, tagName } from './slider.options.js'; interface BoundingBox { x: number; @@ -11,11 +11,9 @@ interface BoundingBox { test.describe('Slider', () => { test.use({ - tagName: 'fluent-slider', + tagName, }); - // Foundation tests - test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -25,9 +23,9 @@ test.describe('Slider', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-slider'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -35,6 +33,8 @@ test.describe('Slider', () => { test('should have a default role of `slider`', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'slider'); }); @@ -43,6 +43,8 @@ test.describe('Slider', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('min', ''); await expect(element).toHaveJSProperty('max', ''); @@ -55,7 +57,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ ` - + <${tagName} id="slider"> `); @@ -69,6 +71,8 @@ test.describe('Slider', () => { test('should set a `tabindex` of 0', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveAttribute('tabindex', '0'); }); @@ -77,12 +81,16 @@ test.describe('Slider', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.ariaOrientation', 'horizontal'); }); test('should initialize to the initial value if no value property is set', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('value', '50'); }); @@ -91,6 +99,8 @@ test.describe('Slider', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.ariaDisabled', 'false'); }); @@ -105,6 +115,8 @@ test.describe('Slider', () => { test('should set the `elementInternals.ariaDisabled` when `disabled` property is true', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.ariaDisabled', 'false'); await element.evaluate((node: Slider) => { @@ -129,7 +141,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -219,6 +231,8 @@ test.describe('Slider', () => { test('should allow setting value with number', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Slider) => { node.valueAsNumber = 8; }); @@ -240,6 +254,8 @@ test.describe('Slider', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Slider) => { node.valueTextFormatter = () => 'Seventy Five Years'; }); @@ -317,7 +333,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} min="0" max="100">
`); @@ -343,7 +359,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} min="0" max="100">
`); @@ -437,13 +453,13 @@ test.describe('Slider', () => { await fastPage.setTemplate(''); - await page.evaluate(() => { - const slider = document.createElement('fluent-slider') as Slider; + await page.evaluate(tagName => { + const slider = document.createElement(tagName) as Slider; slider.value = '3'; document.body.appendChild(slider); - }); + }, tagName); await expect(element).toHaveJSProperty('value', '3'); await expect(element).toHaveJSProperty('elementInternals.ariaValueNow', '3'); @@ -452,6 +468,8 @@ test.describe('Slider', () => { test('should initialize to the provided value attribute when set post-connection', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: Slider) => { node.setAttribute('value', '3'); }); @@ -488,7 +506,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -515,7 +533,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} min="0" max="100">
`); @@ -548,7 +566,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} min="0" max="100">
`); @@ -580,6 +598,8 @@ test.describe('Slider', () => { test('should emit `change` event when `value` property changed', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const wasChanged = element.evaluate( node => new Promise(resolve => node.addEventListener('change', () => resolve(true))), ); @@ -594,6 +614,8 @@ test.describe('Slider', () => { test('should emit `change` event if the `value` attribute changed', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const wasChanged = element.evaluate( node => new Promise(resolve => node.addEventListener('change', () => resolve(true))), ); @@ -662,6 +684,8 @@ test.describe('Slider', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const track = element.locator('.track'); const thumb = element.locator('.thumb-container'); const trackBox = (await track.boundingBox()) as BoundingBox; @@ -816,7 +840,7 @@ test.describe('Slider', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -847,6 +871,8 @@ test.describe('Slider', () => { const { element } = fastPage; const thumb = element.locator('.thumb-container'); + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('valueAsNumber', 50); await thumb.click(); diff --git a/packages/web-components/src/spinner/spinner.spec.ts b/packages/web-components/src/spinner/spinner.spec.ts index 693e25f65ec57d..ce446dbc7bbff3 100644 --- a/packages/web-components/src/spinner/spinner.spec.ts +++ b/packages/web-components/src/spinner/spinner.spec.ts @@ -1,9 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; -import { SpinnerAppearance, SpinnerSize } from './spinner.options.js'; +import { SpinnerAppearance, SpinnerSize, tagName } from './spinner.options.js'; test.describe('Spinner', () => { test.use({ - tagName: 'fluent-spinner', + tagName, }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -15,9 +15,9 @@ test.describe('Spinner', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-spinner'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -25,9 +25,11 @@ test.describe('Spinner', () => { test('should set the `appearance` property to match the `appearance` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const appearance of Object.values(SpinnerAppearance)) { await test.step(appearance, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); @@ -39,9 +41,11 @@ test.describe('Spinner', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(SpinnerSize)) { await test.step(size, async () => { - await fastPage.setTemplate({ attributes: { size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveJSProperty('size', size); diff --git a/packages/web-components/src/switch/switch.spec.ts b/packages/web-components/src/switch/switch.spec.ts index 3411289c7e1605..98478ce7fabb8d 100644 --- a/packages/web-components/src/switch/switch.spec.ts +++ b/packages/web-components/src/switch/switch.spec.ts @@ -1,8 +1,9 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Switch } from './switch.js'; +import { tagName } from './switch.options.js'; test.describe('Switch', () => { - test.use({ tagName: 'fluent-switch' }); + test.use({ tagName: tagName }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -13,9 +14,9 @@ test.describe('Switch', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-switch'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -23,12 +24,16 @@ test.describe('Switch', () => { test('should have a role of `switch`', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', 'switch'); }); test('should set the `ariaChecked` property to `false` when `checked` is not defined', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).not.toHaveAttribute('checked'); await expect(element).toHaveJSProperty('elementInternals.ariaChecked', 'false'); @@ -51,6 +56,8 @@ test.describe('Switch', () => { test('should NOT set a default `aria-required` value when `required` is not defined', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).not.toHaveAttribute('required'); await expect(element).not.toHaveAttribute('aria-required'); @@ -59,6 +66,8 @@ test.describe('Switch', () => { test('should be focusable by default', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.focus(); await expect(element).toBeFocused(); @@ -77,6 +86,8 @@ test.describe('Switch', () => { test('should initialize to the initial value if no `value` property is set', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('value', 'on'); }); @@ -93,6 +104,8 @@ test.describe('Switch', () => { const expectedValue = 'foobar'; + await fastPage.setTemplate(); + await element.evaluate((node: Switch, expectedValue) => { node.setAttribute('value', expectedValue); }, expectedValue); @@ -101,17 +114,20 @@ test.describe('Switch', () => { }); test('should initialize to the provided `value` property when set pre-connection', async ({ fastPage, page }) => { - await fastPage.setTemplate(''); - const expectedValue = 'foobar'; - const value = await page.evaluate(expectedValue => { - const node = document.createElement('fluent-switch') as Switch; + await fastPage.setTemplate(''); + + const value = await page.evaluate( + ([expectedValue, tagName]) => { + const node = document.createElement(tagName) as Switch; - node.value = expectedValue; + node.value = expectedValue; - return node.value; - }, expectedValue); + return node.value; + }, + [expectedValue, tagName], + ); expect(value).toBe(expectedValue); }); @@ -121,7 +137,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -133,7 +149,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -150,7 +166,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -175,7 +191,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -203,7 +219,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} required>
`); @@ -233,7 +249,7 @@ test.describe('Switch', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="switch" value="foo">
`); @@ -246,15 +262,15 @@ test.describe('Switch', () => { }); test('should submit the values of multiple switches when checked', async ({ fastPage, page }) => { - const switches = page.locator('fluent-switch'); + const switches = page.locator(tagName); const element1 = switches.nth(0); const element2 = switches.nth(1); const submitButton = page.locator('button'); await fastPage.setTemplate(/* html */ `
- - + <${tagName} name="switch" value="foo"> + <${tagName} name="switch" value="bar">
`); diff --git a/packages/web-components/src/tab/tab.spec.ts b/packages/web-components/src/tab/tab.spec.ts index 2b46355e147092..5e905f3e874651 100644 --- a/packages/web-components/src/tab/tab.spec.ts +++ b/packages/web-components/src/tab/tab.spec.ts @@ -1,7 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; +import { tagName } from './tab.options.js'; test.describe('Tab', () => { - test.use({ tagName: 'fluent-tab' }); + test.use({ + tagName, + innerHTML: 'Tab', + }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(''); @@ -12,9 +16,9 @@ test.describe('Tab', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-tab'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); diff --git a/packages/web-components/src/tablist/tablist.spec.ts b/packages/web-components/src/tablist/tablist.spec.ts index 7cbf89f3ea5d9e..6878e54aa64f96 100644 --- a/packages/web-components/src/tablist/tablist.spec.ts +++ b/packages/web-components/src/tablist/tablist.spec.ts @@ -1,20 +1,21 @@ import { expect, test } from '../../test/playwright/index.js'; import type { Tab } from '../tab/tab.js'; +import { tagName as TabTagName } from '../tab/tab.options.js'; import type { Tablist } from './tablist.js'; -import { TablistAppearance, TablistSize } from './tablist.options.js'; +import { TablistAppearance, TablistSize, tagName } from './tablist.options.js'; test.describe('Tablist', () => { test.use({ - tagName: 'fluent-tablist', - waitFor: ['fluent-tab'], + tagName, innerHTML: /* html */ ` - Tab one - Tab two - Tab three + <${TabTagName}>Tab one + <${TabTagName}>Tab two + <${TabTagName}>Tab three `, + waitFor: [TabTagName], }); - test('should create with document.createElement()', async ({ page, fastPage }) => { + test('should create with document.createElement()', async ({ page, fastPage, innerHTML }) => { await fastPage.setTemplate(); let hasError = false; @@ -23,9 +24,9 @@ test.describe('Tablist', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-tablist'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -33,6 +34,8 @@ test.describe('Tablist', () => { test('should have reflect disabled attribute on control', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).not.toHaveAttribute('disabled'); await element.evaluate((node: Tablist) => { @@ -44,7 +47,9 @@ test.describe('Tablist', () => { test('should set aria-disabled on individual tabs when tablist is disabled', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); // Initially tabs should not have aria-disabled await expect(tabs.nth(0)).not.toHaveAttribute('aria-disabled'); @@ -75,6 +80,8 @@ test.describe('Tablist', () => { test('should have role of `tablist`', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveAttribute('role', 'tablist'); }); @@ -83,12 +90,16 @@ test.describe('Tablist', () => { }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('orientation', 'horizontal'); }); test('should set an `id` attribute on the active tab when an `id` is provided', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); const tabCount = await tabs.count(); @@ -108,7 +119,9 @@ test.describe('Tablist', () => { fastPage, }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); const tabCount = await tabs.count(); @@ -128,7 +141,9 @@ test.describe('Tablist', () => { test('should default the first tab as the active index if `activeid` is NOT provided', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); await expect(tabs.nth(0)).toHaveAttribute('aria-selected', 'true'); }); @@ -139,7 +154,9 @@ test.describe('Tablist', () => { fastPage, }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); const secondTab = tabs.nth(1); @@ -156,7 +173,9 @@ test.describe('Tablist', () => { fastPage, }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); + + await fastPage.setTemplate(); await expect(tabs.nth(0)).toHaveAttribute('aria-selected', 'true'); @@ -175,9 +194,11 @@ test.describe('Tablist', () => { test('should set the `appearance` property to match the `appearance` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const appearance of Object.values(TablistAppearance)) { await test.step(appearance, async () => { - await fastPage.setTemplate({ attributes: { appearance } }); + await fastPage.updateTemplate(element, { attributes: { appearance } }); await expect(element).toHaveJSProperty('appearance', appearance); @@ -189,9 +210,11 @@ test.describe('Tablist', () => { test('should set the `size` property to match the `size` attribute', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + for (const size of Object.values(TablistSize)) { await test.step(size, async () => { - await fastPage.setTemplate({ attributes: { size } }); + await fastPage.updateTemplate(element, { attributes: { size } }); await expect(element).toHaveJSProperty('size', size); @@ -202,13 +225,13 @@ test.describe('Tablist', () => { test('should not allow selecting a tab that has been disabled after it has been connected', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Tab one - Tab two - Tab three + <${TabTagName} id="tab-1">Tab one + <${TabTagName} id="tab-2">Tab two + <${TabTagName} id="tab-3">Tab three `, }); @@ -236,13 +259,13 @@ test.describe('Tablist', () => { test('should allow selecting tab that has been enabled after it has been connected', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Tab one - Tab two - Tab three + <${TabTagName}>Tab one + <${TabTagName} disabled>Tab two + <${TabTagName}>Tab three `, }); @@ -276,13 +299,13 @@ test.describe('Tablist', () => { test('should keep disabled selected tab focusable until it loses selected state', async ({ fastPage }) => { const { element, page } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Tab one - Tab two - Tab three + <${TabTagName}>Tab one + <${TabTagName}>Tab two + <${TabTagName}>Tab three `, }); @@ -307,13 +330,13 @@ test.describe('Tablist', () => { test('should not allow selecting hidden tab using arrow keys', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Tab one - - Tab three + <${TabTagName}>Tab one + <${TabTagName} hidden>Tab two + <${TabTagName}>Tab three `, }); @@ -335,13 +358,13 @@ test.describe('Tablist', () => { test('should not allow selecting hidden tab by pressing End', async ({ fastPage }) => { const { element } = fastPage; - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await fastPage.setTemplate({ innerHTML: /* html */ ` - Tab one - Tab two - + <${TabTagName}>Tab one + <${TabTagName}>Tab two + <${TabTagName} hidden>Tab three `, }); @@ -364,11 +387,11 @@ test.describe('Tablist', () => { test('should associate panel elements with `aria-controls` attributes', async ({ fastPage, page }) => { const { element } = fastPage; await fastPage.setTemplate(` - - Tab one - Tab two - Tab three - + <${tagName}> + <${TabTagName} aria-controls="panel1">Tab one + <${TabTagName} aria-controls="panel2">Tab two + <${TabTagName} aria-controls="panel3">Tab three +
Panel one
Panel two
Panel three
@@ -401,12 +424,12 @@ test.describe('Tablist', () => { await fastPage.setTemplate({ attributes: { orientation: 'vertical' }, innerHTML: /* html */ ` - Tab one - TTab two - Tab three + <${TabTagName}>Tab one + <${TabTagName}>TTab two + <${TabTagName}>Tab three `, }); - const tabs = element.locator('fluent-tab'); + const tabs = element.locator(TabTagName); await expect(tabs.nth(0)).toHaveAttribute('data-hasIndent'); await expect(tabs.nth(1)).toHaveAttribute('data-hasIndent'); diff --git a/packages/web-components/src/text-input/text-input.spec.ts b/packages/web-components/src/text-input/text-input.spec.ts index 4ef00687ec7953..f88e019b164bd0 100644 --- a/packages/web-components/src/text-input/text-input.spec.ts +++ b/packages/web-components/src/text-input/text-input.spec.ts @@ -1,9 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; import type { TextInput } from './text-input.js'; -import { ImplicitSubmissionBlockingTypes } from './text-input.options.js'; +import { ImplicitSubmissionBlockingTypes, tagName } from './text-input.options.js'; test.describe('TextInput', () => { - test.use({ tagName: 'fluent-text-input' }); + test.use({ + tagName, + }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -14,9 +16,9 @@ test.describe('TextInput', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-text-input'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -178,6 +180,8 @@ test.describe('TextInput', () => { test('should have an undefined `value` property when no `value` attribute is set', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('value', undefined); }); @@ -194,13 +198,13 @@ test.describe('TextInput', () => { await fastPage.setTemplate(''); - await page.evaluate(() => { - const textInput = document.createElement('fluent-text-input') as TextInput; + await page.evaluate(tagName => { + const textInput = document.createElement(tagName) as TextInput; textInput.value = 'foo'; document.body.append(textInput); - }); + }, tagName); await expect(element).toHaveJSProperty('value', 'foo'); }); @@ -209,6 +213,8 @@ test.describe('TextInput', () => { const { element } = fastPage; const control = element.locator('input'); + await fastPage.setTemplate(); + await element.evaluate(node => { node.setAttribute('value', 'foo'); }); @@ -224,6 +230,8 @@ test.describe('TextInput', () => { const { element } = fastPage; const control = element.locator('input'); + await fastPage.setTemplate(); + await control.fill('bar'); await element.evaluate(node => { @@ -337,6 +345,8 @@ test.describe('TextInput', () => { test('should fire a `change` event when the internal control emits a `change` event', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + const wasChanged = element.evaluate( node => new Promise(resolve => { @@ -528,7 +538,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName}>
`); @@ -538,6 +548,8 @@ test.describe('TextInput', () => { test('should set the `form` property to `null` when the element is not in a form', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('form', null); }); @@ -548,7 +560,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} form="foo">
`); @@ -562,7 +574,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} form="bar">
`); @@ -578,7 +590,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput">
`); @@ -599,7 +611,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput">
`); @@ -620,7 +632,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput">
`); @@ -641,7 +653,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput">
`); @@ -663,7 +675,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput" required>
`); @@ -678,7 +690,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput" readonly>
`); @@ -696,7 +708,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput" multiple type="email">
`); @@ -748,7 +760,7 @@ test.describe('TextInput', () => { await fastPage.setTemplate(/* html */ `
- + <${tagName} name="testinput">
`); @@ -765,6 +777,8 @@ test.describe('TextInput', () => { test('should change the `value` property when the `current-value` attribute changes', async ({ fastPage, page }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate(node => { node.setAttribute('current-value', 'foo'); }); @@ -775,6 +789,8 @@ test.describe('TextInput', () => { test('should change the `value` property when the `currentValue` property changes', async ({ fastPage, page }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await element.evaluate((node: TextInput) => { node.currentValue = 'foo'; }); @@ -785,6 +801,8 @@ test.describe('TextInput', () => { test('should set the `current-value` attribute to match the `value` property', async ({ fastPage, page }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).not.toHaveAttribute('current-value'); await element.evaluate((node: TextInput) => { @@ -797,6 +815,8 @@ test.describe('TextInput', () => { test('should set the `currentValue` property to match the `value` property', async ({ fastPage, page }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('currentValue', undefined); await element.evaluate((node: TextInput) => { diff --git a/packages/web-components/src/text/text.spec.ts b/packages/web-components/src/text/text.spec.ts index 1e8567164f29f9..63beb0a5047826 100644 --- a/packages/web-components/src/text/text.spec.ts +++ b/packages/web-components/src/text/text.spec.ts @@ -1,8 +1,11 @@ import { expect, test } from '../../test/playwright/index.js'; -import { TextAlign, TextFont, TextSize, TextWeight } from './text.options.js'; +import { tagName, TextAlign, TextFont, TextSize, TextWeight } from './text.options.js'; test.describe('Text Component', () => { - test.use({ tagName: 'fluent-text' }); + test.use({ + tagName, + innerHTML: 'Text', + }); test('should create with document.createElement()', async ({ page, fastPage }) => { await fastPage.setTemplate(); @@ -13,9 +16,9 @@ test.describe('Text Component', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-text'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -28,7 +31,7 @@ test.describe('Text Component', () => { await expect(element).toHaveJSProperty('nowrap', true); await test.step('should set the `nowrap` property to false when the `nowrap` attribute is removed', async () => { - await fastPage.setTemplate({ attributes: {} }); + await element.evaluate(node => node.removeAttribute('nowrap')); await expect(element).toHaveJSProperty('nowrap', false); }); @@ -44,7 +47,7 @@ test.describe('Text Component', () => { await expect(element).toHaveJSProperty('truncate', true); await test.step('should set the `truncate` property to false when the `truncate` attribute is removed', async () => { - await fastPage.setTemplate({ attributes: {} }); + await element.evaluate(node => node.removeAttribute('truncate')); await expect(element).toHaveJSProperty('truncate', false); }); @@ -58,7 +61,7 @@ test.describe('Text Component', () => { await expect(element).toHaveJSProperty('italic', true); await test.step('should set the `italic` property to false when the `italic` attribute is removed', async () => { - await fastPage.setTemplate({ attributes: {} }); + await element.evaluate(node => node.removeAttribute('italic')); await expect(element).toHaveJSProperty('italic', false); }); @@ -74,7 +77,7 @@ test.describe('Text Component', () => { await expect(element).toHaveJSProperty('underline', true); await test.step('should set the `underline` property to false when the `underline` attribute is removed', async () => { - await fastPage.setTemplate({ attributes: {} }); + await element.evaluate(node => node.removeAttribute('underline')); await expect(element).toHaveJSProperty('underline', false); }); @@ -90,7 +93,7 @@ test.describe('Text Component', () => { await expect(element).toHaveJSProperty('strikethrough', true); await test.step('should set the `strikethrough` property to false when the `strikethrough` attribute is removed', async () => { - await fastPage.setTemplate({ attributes: {} }); + await element.evaluate(node => node.removeAttribute('strikethrough')); await expect(element).toHaveJSProperty('strikethrough', false); }); diff --git a/packages/web-components/src/textarea/textarea.spec.ts b/packages/web-components/src/textarea/textarea.spec.ts index 8da1fb69475ece..5d9bff314906f4 100644 --- a/packages/web-components/src/textarea/textarea.spec.ts +++ b/packages/web-components/src/textarea/textarea.spec.ts @@ -1,11 +1,12 @@ import { expect, test } from '../../test/playwright/index.js'; -import { TextAreaAppearance, TextAreaResize, TextAreaSize } from './textarea.options.js'; +import { tagName as LabelTagName } from '../label/label.options.js'; import type { TextArea } from './textarea.js'; +import { tagName, TextAreaAppearance, TextAreaResize, TextAreaSize } from './textarea.options.js'; test.describe('TextArea', () => { test.use({ - tagName: 'fluent-textarea', - waitFor: ['fluent-label'], + tagName, + waitFor: [LabelTagName], }); test('should create with document.createElement()', async ({ page, fastPage }) => { @@ -17,9 +18,9 @@ test.describe('TextArea', () => { hasError = true; }); - await page.evaluate(() => { - document.createElement('fluent-textarea'); - }); + await page.evaluate(tagName => { + document.createElement(tagName); + }, tagName); expect(hasError).toBe(false); }); @@ -28,12 +29,16 @@ test.describe('TextArea', () => { test('should not have a role on element internals', async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('elementInternals.role', null); }); test("should always return 'textarea' for the `type` prop", async ({ fastPage }) => { const { element } = fastPage; + await fastPage.setTemplate(); + await expect(element).toHaveJSProperty('type', 'textarea'); }); @@ -69,8 +74,8 @@ test.describe('TextArea', () => { await fastPage.setTemplate(/* html */ ` - -