202 lines
7.2 KiB
TypeScript
202 lines
7.2 KiB
TypeScript
/**
|
|
* Copyright Microsoft Corporation. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { expect, browserTest as test } from '../config/browserTest';
|
|
|
|
test.skip(({ mode }) => mode !== 'default', 'Annotations use an open shadow root only in default mode');
|
|
|
|
test('should show annotation on click', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 5000 });
|
|
page.click('button').catch(() => {});
|
|
|
|
await expect(page.locator('x-pw-highlight')).toBeVisible();
|
|
await expect(page.locator('x-pw-action-point')).toBeVisible();
|
|
await expect(page.locator('x-pw-title')).toBeVisible();
|
|
await expect(page.locator('x-pw-title')).toHaveText(/click/i);
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('should render annotation styles', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 5000, fontSize: 32 });
|
|
page.click('button').catch(() => {});
|
|
|
|
// Highlight box: blue overlay with non-zero dimensions.
|
|
const highlight = page.locator('x-pw-highlight');
|
|
await expect(highlight).toBeVisible();
|
|
const highlightStyle = await highlight.evaluate((el: HTMLElement) => ({
|
|
backgroundColor: el.style.backgroundColor,
|
|
borderColor: el.style.borderColor,
|
|
}));
|
|
expect(highlightStyle.backgroundColor).toBe('rgba(0, 128, 255, 0.15)');
|
|
expect(highlightStyle.borderColor).toBe('rgba(0, 128, 255, 0.6)');
|
|
const box = await highlight.boundingBox();
|
|
expect(box!.width).toBeGreaterThan(0);
|
|
expect(box!.height).toBeGreaterThan(0);
|
|
|
|
// Action point: 20x20 red circle.
|
|
const actionPoint = page.locator('x-pw-action-point');
|
|
await expect(actionPoint).toBeVisible();
|
|
const apStyle = await actionPoint.evaluate((el: HTMLElement) => {
|
|
const cs = getComputedStyle(el);
|
|
return { width: cs.width, height: cs.height, background: cs.backgroundColor, borderRadius: cs.borderRadius };
|
|
});
|
|
expect(apStyle.width).toBe('20px');
|
|
expect(apStyle.height).toBe('20px');
|
|
expect(apStyle.background).toBe('rgb(255, 0, 0)');
|
|
expect(apStyle.borderRadius).toBe('10px');
|
|
|
|
// Title: white text, dark background, positioned top-right by default, custom fontSize.
|
|
const title = page.locator('x-pw-title');
|
|
await expect(title).toBeVisible();
|
|
const titleStyle = await title.evaluate((el: HTMLElement) => {
|
|
const cs = getComputedStyle(el);
|
|
return {
|
|
color: cs.color, borderRadius: cs.borderRadius, padding: cs.padding,
|
|
top: el.style.top, right: el.style.right, fontSize: el.style.fontSize,
|
|
};
|
|
});
|
|
expect(titleStyle.color).toBe('rgb(255, 255, 255)');
|
|
expect(titleStyle.borderRadius).toBe('6px');
|
|
expect(titleStyle.padding).toBe('6px');
|
|
expect(titleStyle.top).toBe('6px');
|
|
expect(titleStyle.right).toBe('6px');
|
|
expect(titleStyle.fontSize).toBe('32px');
|
|
|
|
await context.close();
|
|
});
|
|
|
|
for (const { position, expected } of [
|
|
{ position: 'top-left' as const, expected: { top: '6px', left: '6px' } },
|
|
{ position: 'top' as const, expected: { top: '6px', left: '50%' } },
|
|
{ position: 'bottom-left' as const, expected: { bottom: '6px', left: '6px' } },
|
|
{ position: 'bottom' as const, expected: { bottom: '6px', left: '50%' } },
|
|
{ position: 'bottom-right' as const, expected: { bottom: '6px', right: '6px' } },
|
|
] as const) {
|
|
test(`should position title at ${position}`, async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 5000, position });
|
|
page.click('button').catch(() => {});
|
|
|
|
const title = page.locator('x-pw-title');
|
|
await expect(title).toBeVisible();
|
|
|
|
const titleStyle = await title.evaluate((el: HTMLElement) => ({
|
|
top: el.style.top,
|
|
bottom: el.style.bottom,
|
|
left: el.style.left,
|
|
right: el.style.right,
|
|
})) as any;
|
|
|
|
for (const [key, value] of Object.entries(expected))
|
|
expect(titleStyle[key]).toBe(value);
|
|
|
|
await context.close();
|
|
});
|
|
}
|
|
|
|
test('should clear annotation after duration', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 1000 });
|
|
await page.click('button');
|
|
|
|
await expect(page.locator('x-pw-action-point')).toBeHidden();
|
|
await expect(page.locator('x-pw-title')).toBeHidden();
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('should annotate fill action', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/textarea.html');
|
|
|
|
await page.screencast.showActions({ duration: 5000 });
|
|
page.fill('textarea', 'hello').catch(() => {});
|
|
|
|
const title = page.locator('x-pw-title');
|
|
await expect(title).toBeVisible();
|
|
await expect(title).toHaveText(/fill/i);
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('should stop showing actions after dispose', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
const actions = await page.screencast.showActions({ duration: 1000 });
|
|
await page.click('button');
|
|
await actions.dispose();
|
|
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
await page.click('button');
|
|
|
|
await expect(page.locator('x-pw-title')).toBeHidden();
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('should stop showing actions after hideActions', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 1000 });
|
|
await page.click('button');
|
|
await page.screencast.hideActions();
|
|
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
await page.click('button');
|
|
|
|
await expect(page.locator('x-pw-title')).toBeHidden();
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('should survive navigation', async ({ browser, server }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
|
|
await page.screencast.showActions({ duration: 5000 });
|
|
page.click('button').catch(() => {});
|
|
|
|
await expect(page.locator('x-pw-title')).toBeVisible();
|
|
|
|
await page.goto(server.PREFIX + '/input/button.html');
|
|
page.click('button').catch(() => {});
|
|
|
|
await expect(page.locator('x-pw-title')).toBeVisible();
|
|
|
|
await context.close();
|
|
});
|