Веб: токен эпика, проверка определённости var(--…), выделение в строке (#108)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a6de46b3f8
commit
9212c19dcf
@ -144,6 +144,27 @@ describe("«Бэклог»", () => {
|
|||||||
await waitFor(() => expect(router.state.location.pathname).toBe("/app/jira/backlog"));
|
await waitFor(() => expect(router.state.location.pathname).toBe("/app/jira/backlog"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("выделение вне строки не мешает открыть карточку", async () => {
|
||||||
|
hub();
|
||||||
|
const router = open("/app/jira/backlog?project=AWPCA");
|
||||||
|
const p = await loaded();
|
||||||
|
window.getSelection()!.selectAllChildren(within(p).getByRole("heading", { name: "AWPCA_Sprint_4" }));
|
||||||
|
await userEvent.click(within(p).getByText("Тема AURORA-1"));
|
||||||
|
await screen.findByRole("dialog");
|
||||||
|
expect(router.state.location.pathname).toBe("/app/jira/issues/AURORA-1");
|
||||||
|
window.getSelection()!.removeAllRanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("щелчок по ссылке ключа открывает карточку один раз", async () => {
|
||||||
|
hub();
|
||||||
|
const router = open("/app/jira/backlog?project=AWPCA");
|
||||||
|
const p = await loaded();
|
||||||
|
await userEvent.click(within(p).getByRole("link", { name: "AURORA-1" }));
|
||||||
|
await screen.findByRole("dialog");
|
||||||
|
await userEvent.click(within(screen.getByRole("dialog")).getByRole("button", { name: "Закрыть" }));
|
||||||
|
await waitFor(() => expect(router.state.location.pathname).toBe("/app/jira/backlog")); // одна запись истории, а не две
|
||||||
|
});
|
||||||
|
|
||||||
it("нет данных доски — «Нужен агент v15 и обновление из Jira» и «Обновить из Jira»", async () => {
|
it("нет данных доски — «Нужен агент v15 и обновление из Jira» и «Обновить из Jira»", async () => {
|
||||||
hub({ data: { board: null, sprints: [], backlog: null, board_issues: null } });
|
hub({ data: { board: null, sprints: [], backlog: null, board_issues: null } });
|
||||||
open("/app/jira/backlog?project=AWPCA");
|
open("/app/jira/backlog?project=AWPCA");
|
||||||
|
|||||||
@ -9,7 +9,8 @@ export function AgileIssueRow({ issue, mark }: { issue: AgileIssue; mark?: strin
|
|||||||
const open = useOpenIssue();
|
const open = useOpenIssue();
|
||||||
const click = (e: MouseEvent) => {
|
const click = (e: MouseEvent) => {
|
||||||
if ((e.target as HTMLElement).closest("a")) return;
|
if ((e.target as HTMLElement).closest("a")) return;
|
||||||
if (window.getSelection()?.toString()) return;
|
const sel = window.getSelection();
|
||||||
|
if (sel && !sel.isCollapsed && sel.containsNode(e.currentTarget, true)) return; // выделен текст этой строки
|
||||||
open(issue.key);
|
open(issue.key);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
/* экраны доски (бэклог, спринт, Kanban): только токены дизайн-системы */
|
/* экраны доски (бэклог, спринт, Kanban): только токены дизайн-системы */
|
||||||
.agile{display:flex;flex-direction:column;gap:var(--space-4);padding-top:var(--space-6)}
|
.agile{display:flex;flex-direction:column;gap:var(--space-4);padding-top:var(--space-6)}
|
||||||
.agile .ui-page-header{margin-bottom:0}
|
.agile .ui-page-header{margin-bottom:0}
|
||||||
.agile__gate{padding-top:var(--space-6)}
|
.agile__gate{min-width:0}
|
||||||
.agile .agile__gate{padding-top:0}
|
|
||||||
.agile__link{color:var(--color-action-primary);font-weight:600;text-decoration:none}
|
.agile__link{color:var(--color-action-primary);font-weight:600;text-decoration:none}
|
||||||
.agile__link:hover{text-decoration:underline}
|
.agile__link:hover{text-decoration:underline}
|
||||||
.agile__empty{margin:0;color:var(--color-text-secondary)}
|
.agile__empty{margin:0;color:var(--color-text-secondary)}
|
||||||
@ -25,7 +24,7 @@
|
|||||||
.agile-row__sp{flex:0 0 32px;text-align:right;color:var(--color-text-secondary)}
|
.agile-row__sp{flex:0 0 32px;text-align:right;color:var(--color-text-secondary)}
|
||||||
.agile-row__mark{flex:0 0 auto;font-size:var(--fs-caption);color:var(--color-status-warning)}
|
.agile-row__mark{flex:0 0 auto;font-size:var(--fs-caption);color:var(--color-status-warning)}
|
||||||
.agile-type{display:inline-flex;flex:0 0 auto;color:var(--color-text-secondary)}
|
.agile-type{display:inline-flex;flex:0 0 auto;color:var(--color-text-secondary)}
|
||||||
.agile-type--epic{color:var(--color-cat-1)}
|
.agile-type--epic{color:var(--k-ui)}
|
||||||
.agile-type--bug{color:var(--color-status-error)}
|
.agile-type--bug{color:var(--color-status-error)}
|
||||||
.agile-type--task{color:var(--color-status-success)}
|
.agile-type--task{color:var(--color-status-success)}
|
||||||
.agile-past{display:flex;flex-direction:column;gap:var(--space-2)}
|
.agile-past{display:flex;flex-direction:column;gap:var(--space-2)}
|
||||||
|
|||||||
@ -71,7 +71,6 @@ export interface IssueDetail extends IssueRow {
|
|||||||
changes?: ChangeEvent[]; // хаб до журнала изменений (#70) поля не шлёт
|
changes?: ChangeEvent[]; // хаб до журнала изменений (#70) поля не шлёт
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ответ GET /agile (доска проекта, спринты, бэклог); поля — как отдаёт хаб
|
// ответ GET /agile (доска проекта, спринты, бэклог); поля — как отдаёт хаб
|
||||||
export interface AgileIssue {
|
export interface AgileIssue {
|
||||||
key: string; summary: string | null; issue_type: string | null; status: string | null; priority: string | null;
|
key: string; summary: string | null; issue_type: string | null; status: string | null; priority: string | null;
|
||||||
|
|||||||
@ -64,6 +64,25 @@ describe("токены AURA", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("использованные токены определены", () => {
|
||||||
|
const defs = (css: string) => new Set([...stripComments(css).matchAll(/(--[\w-]+)\s*:/g)].map((m) => m[1]));
|
||||||
|
// переменные, которые выставляет код страницы (setProperty), а не css
|
||||||
|
const SET_BY_JS = new Set(["--head-h"]);
|
||||||
|
const tokenDefs = defs(readFileSync(TOKENS, "utf8"));
|
||||||
|
it("каждый var(--…) в css определён в tokens.css или в том же файле", () => {
|
||||||
|
const missing: string[] = [];
|
||||||
|
for (const f of cssFiles(SRC)) {
|
||||||
|
if (f === TOKENS) continue;
|
||||||
|
const css = readFileSync(f, "utf8");
|
||||||
|
const local = defs(css);
|
||||||
|
for (const m of stripComments(css).matchAll(/var\(\s*(--[\w-]+)/g)) {
|
||||||
|
if (!tokenDefs.has(m[1]) && !local.has(m[1]) && !SET_BY_JS.has(m[1])) missing.push(`${relative(SRC, f)}: ${m[1]}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect([...new Set(missing)]).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("доска без чередования дорожек (#69, design 9)", () => {
|
describe("доска без чередования дорожек (#69, design 9)", () => {
|
||||||
it("токена --lane-alt нет, правила чётной дорожки нет", () => {
|
it("токена --lane-alt нет, правила чётной дорожки нет", () => {
|
||||||
expect(readFileSync(TOKENS, "utf8")).not.toContain("--lane-alt");
|
expect(readFileSync(TOKENS, "utf8")).not.toContain("--lane-alt");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user