UNPKG

@v4fire/client

Version:

V4Fire client core library

374 lines (285 loc) • 8.5 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import type { Page, JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; import Component from 'tests/helpers/component'; import BOM from 'tests/helpers/bom'; import type bButton from 'form/b-button/b-button'; test.describe('b-button', () => { let buttonNode, buttonCtx: JSHandle<bButton>; test.beforeEach(async ({demoPage}) => { await demoPage.goto(); }); test.describe('providing `type`', () => { test.describe('`file`', () => { test.beforeEach(async ({page}) => { await renderButton(page, { type: 'file' }); }); test('renders a button with a `file` type', async () => { const fileEl = await buttonNode.$('[type="file"]'); test.expect(fileEl).toBeTruthy(); }); test('opens a file chooser on click', async ({page}) => { const event = page.waitForEvent('filechooser'); await buttonNode.click(); await test.expect(event).resolves.toBeTruthy(); }); test.describe('file chooser has been opened, and the file has been selected', () => { let changeEventPr; test.beforeEach(async ({page}) => { const fileChooserPr = page.waitForEvent('filechooser'); changeEventPr = buttonCtx.evaluate((ctx) => ctx.promisifyOnce('change').then(() => undefined)); await buttonNode.click(); const fileChooser = await fileChooserPr; await fileChooser.setFiles({ name: 'somefile.pdf', mimeType: 'application/pdf', buffer: Buffer.from([]) }); }); test('stores the provided file', async () => { const filesLength = await buttonCtx.evaluate((ctx) => ctx.files?.length); test.expect(filesLength).toBe(1); }); test('fires a `change` event', async () => { await test.expect(changeEventPr).resolves.toBeUndefined(); }); test('resets the provided files on the `reset` method call', async () => { await buttonCtx.evaluate((ctx) => ctx.reset()); const filesLength = await buttonCtx.evaluate((ctx) => ctx.files?.length); test.expect(filesLength).toBe(0); }); }); }); test.describe('`submit`', () => { test.beforeEach(async ({page}) => { await renderButton(page, { type: 'submit' }); }); test('renders a button with a `submit` type', async () => { const submitEl = await buttonNode.$('[type="submit"]'); test.expect(submitEl).toBeTruthy(); }); test('fires a `submit` event on click', async ({page}) => { const pr = page.evaluate(() => new Promise<void>((res) => { const form = document.createElement('form'); document.body.prepend(form); form.appendChild(globalThis.buttonNode); form.onsubmit = (e) => { e.preventDefault(); res(); }; })); await buttonNode.click(); await test.expect(pr).resolves.toBeUndefined(); }); }); test.describe('`link`', () => { const url = 'https://someurl.com/'; test.beforeEach(async ({page}) => { await renderButton(page, { href: url, type: 'link' }); }); test('renders a button with the provided `href`', async () => { const linkEl = await buttonNode.$(`[href="${url}"]`); test.expect(linkEl).toBeTruthy(); }); test('navigates to the provided `href`', async ({page}) => { const pr = new Promise(async (res) => { await page.route('**/*', (r) => { if (r.request().isNavigationRequest()) { res(r.request().url()); return r.fulfill({ status: 200 }); } return r.continue(); }); }); await buttonNode.click(); const navigationUrl = await pr; test.expect(navigationUrl).toBe(url); }); }); }); test.describe('`href`', () => { test('provides the base URL to a data provider', async ({page}) => { const pr = new Promise<void>(async (res) => { await page.route('**/api/test/base', (r) => { res(); return r.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({}) }); }); }); await renderButton(page, { href: 'test/base' }); await buttonNode.click(); await test.expect(pr).resolves.toBeUndefined(); }); }); test.describe('providing `disabled`', () => { test.describe('`true`', () => { test('does not fire any click event', async ({page}) => { await renderButton(page, { disabled: true }); await buttonCtx.evaluate((ctx) => ctx.on('click', () => globalThis._t = 1)); await buttonNode.click({force: true}); await BOM.waitForIdleCallback(page); const testVal = await page.evaluate(() => globalThis._t); test.expect(testVal).toBeUndefined(); }); test('does not fire a navigation', async ({page}) => { await renderButton(page, { disabled: true, type: 'link', href: 'https://someurl.com/' }); let hasNavRequest = false; await page.route('**/*', (r) => { if (r.request().isNavigationRequest()) { hasNavRequest = true; } return r.continue(); }); await buttonNode.click({force: true}); await BOM.waitForIdleCallback(page, {sleepAfterIdles: 300}); test.expect(hasNavRequest).toBe(false); }); }); test.describe('`false`', () => { test('fires a `click` event', async ({page}) => { await renderButton(page, { disabled: false }); await buttonCtx.evaluate((ctx) => ctx.on('click', () => globalThis._t = 1)); await buttonNode.click(); await BOM.waitForIdleCallback(page); const testVal = await page.evaluate(() => globalThis._t); test.expect(testVal).toBe(1); }); }); }); test.describe('providing `autofocus`', () => { test('`true`', async ({page}) => { await renderButton(page, { autofocus: true }); const autofocusEl = await buttonNode.$('[autofocus="autofocus"]'); test.expect(autofocusEl).toBeTruthy(); }); test('`false`', async ({page}) => { await renderButton(page, { autofocus: false }); const autofocusEl = await buttonNode.$('[autofocus="autofocus"]'); test.expect(autofocusEl).toBeNull(); }); }); test.describe('providing `tabIndex`', () => { test('`-1`', async ({page}) => { await renderButton(page, { tabIndex: -1 }); const tabIndexEl = await buttonNode.$('[tabindex="-1"]'); test.expect(tabIndexEl).toBeTruthy(); }); test('`1`', async ({page}) => { await renderButton(page, { tabIndex: 1 }); const tabIndexEl = await buttonNode.$('[tabindex="1"]'); test.expect(tabIndexEl).toBeTruthy(); }); }); test.describe('providing `preIcon`', () => { test('`dropdown`', async ({page}) => { const iconName = 'foo'; await renderButton(page, { preIcon: iconName }); const bIcon = await buttonNode.$('.b-icon'), iconProvidedName = await bIcon.evaluate((ctx) => ctx.component.value); test.expect(iconProvidedName).toBe(iconName); }); test('`undefined`', async ({page}) => { await renderButton(page, { preIcon: undefined }); const bIcon = await buttonNode.$('.b-icon'); test.expect(bIcon).toBeNull(); }); }); test.describe('click event', () => { test.beforeEach(async ({page}) => { await renderButton(page); }); test('fires on click', async () => { const pr = buttonCtx.evaluate((ctx) => ctx.promisifyOnce('click').then(() => undefined)); await buttonNode.click(); await test.expect(pr).resolves.toBeUndefined(); }); test('does not emit an event without a click', async ({page}) => { await buttonCtx.evaluate((ctx) => ctx.once('click', () => globalThis._t = 1)); await BOM.waitForIdleCallback(page, {sleepAfterIdles: 400}); const res = await page.evaluate(() => globalThis._t); test.expect(res).toBeUndefined(); }); }); /** * @param page * @param attrs */ async function renderButton(page: Page, attrs: Dictionary = {}) { await Component.createComponent(page, 'b-button', { attrs: { id: 'target', ...attrs }, content: { default: () => 'Hello there general kenobi' } }); buttonNode = await page.waitForSelector('#target'); buttonCtx = await Component.waitForComponentByQuery<bButton>(page, '#target'); await page.evaluate(() => globalThis.buttonNode = document.querySelector('#target')); } });