Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as Sentry from '@sentry/browser';
import { feedbackIntegration } from '@sentry/browser';

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [feedbackIntegration({ colorScheme: 'light' })],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import { sentryTest } from '../../../utils/fixtures';
import { shouldSkipFeedbackTest } from '../../../utils/helpers';

async function drawBox(page: Page, from: { x: number; y: number }, to: { x: number; y: number }): Promise<void> {
await page.mouse.move(from.x, from.y);
await page.mouse.down();
await page.mouse.move(to.x, to.y, { steps: 3 });
await page.mouse.up();
}

sentryTest.beforeEach(async ({ getLocalTestUrl, page, browserName }) => {
sentryTest.skip(shouldSkipFeedbackTest());
sentryTest.skip(browserName !== 'chromium', 'The canvas screen-capture fixture requires Chromium.');

await page.addInitScript(() => {
// The fixture runs over HTTP, but screenshot capture is stubbed below.
Object.defineProperty(window, 'isSecureContext', { value: true });
Object.defineProperty(navigator, 'mediaDevices', {
value: {
getDisplayMedia: async () => {
const canvas = document.createElement('canvas');
canvas.width = 1600;
canvas.height = 1000;
const ctx = canvas.getContext('2d')!;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
return canvas.captureStream();
},
},
configurable: true,
});
});

await page.goto(await getLocalTestUrl({ testDir: __dirname, handleLazyLoadedFeedback: true }));
await page.getByRole('button', { name: 'Report a Bug', exact: true }).click();
await page.getByRole('button', { name: 'Add a screenshot', exact: true }).click();
await expect(page.locator('#foreground')).toBeVisible();
await expect.poll(() => page.locator('#background').evaluate((canvas: HTMLCanvasElement) => canvas.width)).toBe(1600);
});

sentryTest('starts a highlight at the cursor inside an existing box', async ({ page }) => {
const canvas = page.locator('#foreground');
const bounds = (await canvas.boundingBox())!;
const point = (x: number, y: number) => ({ x: bounds.x + x, y: bounds.y + y });
await drawBox(page, point(80, 60), point(280, 240));
await expect(page.locator('.editor__rect')).toHaveCount(1);
const start = point(160, 140);
const end = point(240, 200);

await drawBox(page, start, end);

await expect(page.locator('.editor__rect')).toHaveCount(2);
const box = (await page.locator('.editor__rect').nth(1).boundingBox())!;
expect(box.x).toBeCloseTo(start.x, 0);
expect(box.y).toBeCloseTo(start.y, 0);
expect(box.width).toBeCloseTo(end.x - start.x, 0);
expect(box.height).toBeCloseTo(end.y - start.y, 0);
});

sentryTest('keeps background dimming unchanged while dragging another box', async ({ page }) => {
const canvas = page.locator('#foreground');
const bounds = (await canvas.boundingBox())!;
const backgroundPixel = () =>
canvas.evaluate((element: HTMLCanvasElement) =>
Array.from(element.getContext('2d')!.getImageData(1400, 800, 1, 1).data),
);
await drawBox(page, { x: bounds.x + 80, y: bounds.y + 60 }, { x: bounds.x + 240, y: bounds.y + 180 });
await expect(page.locator('.editor__rect')).toHaveCount(1);
await expect.poll(backgroundPixel).toEqual([0, 0, 0, 64]);

await page.mouse.move(bounds.x + 280, bounds.y + 60);
await page.mouse.down();
await page.mouse.move(bounds.x + 360, bounds.y + 180, { steps: 3 });

expect(await backgroundPixel()).toEqual([0, 0, 0, 64]);
await page.mouse.up();
await expect(page.locator('.editor__rect')).toHaveCount(2);
await expect.poll(backgroundPixel).toEqual([0, 0, 0, 64]);
});
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ interface DrawCommand {
function drawRect(command: DrawCommand, ctx: CanvasRenderingContext2D, color: string): void {
switch (command.type) {
case 'highlight': {
ctx.save();
// creates a shadow around
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.shadowBlur = 50;
Expand All @@ -60,6 +61,7 @@ function drawRect(command: DrawCommand, ctx: CanvasRenderingContext2D, color: st

// cut out the inside of the rectangle
ctx.clearRect(command.x, command.y, command.w, command.h);
ctx.restore();
Comment thread
cursor[bot] marked this conversation as resolved.

break;
}
Comment thread
sentry[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -229,8 +231,8 @@ export function ScreenshotEditorFactory({
const boundingRect = mouseRef.current.getBoundingClientRect();
const startingPoint: DrawCommand = {
type: action,
x: e.offsetX / scaleFactor,
y: e.offsetY / scaleFactor,
x: (e.clientX - boundingRect.x) / scaleFactor,
y: (e.clientY - boundingRect.y) / scaleFactor,
w: 0,
h: 0,
};
Comment thread
sentry[bot] marked this conversation as resolved.
Expand Down
Loading