diff --git a/packages/web/src/components/CompactSelect.vue b/packages/web/src/components/CompactSelect.vue index 6c75fa3..0bea214 100644 --- a/packages/web/src/components/CompactSelect.vue +++ b/packages/web/src/components/CompactSelect.vue @@ -11,15 +11,15 @@ options: { value: string; label: string }[]; icon?: string; disabled?: boolean; - /** pixel width of the control */ - width?: number; + /** fixed pixel width, or "100%" to fill the parent block */ + width?: number | string; }>(); defineEmits<{ (e: "update:modelValue", value: string): void }>(); @@ -262,7 +261,7 @@ { value: 'fixed', label: t('reports.status.fixed') }, { value: 'wont_fix', label: t('reports.status.wont_fix') }, ]" - :width="180" + :width="'100%'" :disabled="savingStatus" @update:model-value="setStatus($event)" /> @@ -402,15 +401,20 @@ min-width: 0; } .report-card { - /* kit .card is width:max-content/max-width:340px — report cards fill the grid */ + /* kit .card is width:max-content/max-width:340px — report cards fill the grid; + the kit also wraps content in .card-content (padding:15px), so the padding + lives there and the card itself adds none */ width: 100%; max-width: none; - padding: 18px; + padding: 0; display: flex; flex-direction: column; gap: 12px; min-width: 0; } +.report-card :deep(.card-content) { + padding: 18px; +} .report-card-title { margin: 0; font-size: 12px; diff --git a/packages/web/verify-edit.mjs b/packages/web/verify-edit.mjs new file mode 100644 index 0000000..08028a9 --- /dev/null +++ b/packages/web/verify-edit.mjs @@ -0,0 +1,88 @@ +/** Verify Правки 1-2: full-width status select + icon-only edit button. */ +import { chromium } from "playwright-core"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { homedir } from "node:os"; + +const root = dirname(fileURLToPath(import.meta.url)); +const SERVER = "http://localhost:8001"; +const WEB = "http://localhost:5173"; +const stamp = Date.now(); +const EMAIL = `edit-verify-${stamp}@example.com`; +const PASSWORD = "edit-verify-pass"; + +const executablePath = join(homedir(), ".cache/ms-playwright/chromium-1234/chrome-linux64/chrome"); +const browser = await chromium.launch({ executablePath, headless: true }); + +async function api(path, options = {}) { + const r = await fetch(SERVER + path, options); + if (!r.ok) throw new Error(`API ${path} -> ${r.status}: ${await r.text()}`); + return r.json(); +} + +await api("/api/auth/register", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ nickname: `edit-verify-${stamp}`, email: EMAIL, password: PASSWORD }), +}); +const login = await api("/api/auth/login", { + method: "POST", + headers: { "Content-Type": "application/json", "X-Client": "extension" }, + body: JSON.stringify({ email: EMAIL, password: PASSWORD }), +}); +const auth = { Authorization: `Bearer ${login.token}` }; +const project = await api("/api/projects", { + method: "POST", + headers: { "Content-Type": "application/json", ...auth }, + body: JSON.stringify({ name: "Edit Verify" }), +}); +const note = await api("/api/reports", { + method: "POST", + headers: { "Content-Type": "application/json", ...auth }, + body: JSON.stringify({ + project_id: project.id, + type: "element_note", + title: "Edit button verify", + description: "Some description text", + environment: { user_agent: "verify", browser: "Chromium", os: "Linux", viewport: { w: 1440, h: 900 }, dpr: 1, language: "ru" }, + }), +}); + +// sign in through the UI so canEdit is true (report author = current user) +const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); +await page.goto(`${WEB}/login`); +await page.fill("input[type='text'], input[type='email']", EMAIL); +await page.fill("input[type='password']", PASSWORD); +await page.click("button[type='submit']"); +await page.waitForURL("**/"); +await page.goto(`${WEB}/r/${note.share_token}`); +await page.waitForSelector(".report-details-grid", { timeout: 15000 }); +await page.waitForTimeout(600); +await page.screenshot({ path: "/tmp/ltt-shots/12-edit-verify.png" }); + +const m = await page.evaluate(() => { + const r = (el) => (el ? (({ x, width }) => `${Math.round(x)}+${Math.round(width)}`)(el.getBoundingClientRect()) : "none"); + const select = document.querySelector(".report-details-side .select"); + const card = document.querySelector(".report-details-side .card"); + const btn = document.querySelector(".report-details-main .btn-icon"); + const wrap = document.querySelector(".report-details-side .compact-select"); + const fg = document.querySelector(".report-details-side .form-group"); + const sw = document.querySelector(".report-details-side .select-wrap"); + const selCs = select ? getComputedStyle(select) : null; + return { + compactSelect: r(wrap), + compactStyle: wrap?.getAttribute("style"), + compactComputed: wrap ? getComputedStyle(wrap).width : null, + formGroup: r(fg), + selectWrap: r(sw), + selectWidth: selCs?.width, + select: r(select), + statusCard: r(card), + editButtonClass: btn?.className, + editButtonText: btn?.textContent.trim(), + }; +}); +console.log(JSON.stringify(m, null, 1)); + +await browser.close(); +console.log("VERIFY OK"); \ No newline at end of file