Skip to content

Commit 142f91c

Browse files
authored
Merge branch 'main' into release-please--branches--main--components--miner
2 parents 50d9c52 + a752b8f commit 142f91c

44 files changed

Lines changed: 3898 additions & 141 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/loopover-ui/public/openapi.json

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14347,6 +14347,186 @@
1434714347
]
1434814348
}
1434914349
]
14350+
},
14351+
"ContributorPrOutcomes": {
14352+
"type": "object",
14353+
"properties": {
14354+
"login": {
14355+
"type": "string"
14356+
},
14357+
"count": {
14358+
"type": "number"
14359+
},
14360+
"summary": {
14361+
"type": "string"
14362+
},
14363+
"outcomes": {
14364+
"type": "array",
14365+
"items": {
14366+
"type": "object",
14367+
"properties": {
14368+
"repoFullName": {
14369+
"type": "string"
14370+
},
14371+
"pullNumber": {
14372+
"type": "number",
14373+
"nullable": true
14374+
},
14375+
"outcome": {
14376+
"type": "string",
14377+
"enum": [
14378+
"merged"
14379+
]
14380+
},
14381+
"attribution": {
14382+
"type": "string"
14383+
},
14384+
"deeplink": {
14385+
"type": "string"
14386+
},
14387+
"recordedAt": {
14388+
"type": "string"
14389+
}
14390+
},
14391+
"required": [
14392+
"repoFullName",
14393+
"pullNumber",
14394+
"outcome",
14395+
"attribution",
14396+
"deeplink",
14397+
"recordedAt"
14398+
]
14399+
}
14400+
}
14401+
},
14402+
"required": [
14403+
"login",
14404+
"count",
14405+
"summary",
14406+
"outcomes"
14407+
]
14408+
},
14409+
"NotificationFeed": {
14410+
"type": "object",
14411+
"properties": {
14412+
"login": {
14413+
"type": "string"
14414+
},
14415+
"unreadCount": {
14416+
"type": "number"
14417+
},
14418+
"notifications": {
14419+
"type": "array",
14420+
"items": {
14421+
"$ref": "#/components/schemas/NotificationFeedItem"
14422+
}
14423+
}
14424+
},
14425+
"required": [
14426+
"login",
14427+
"unreadCount",
14428+
"notifications"
14429+
]
14430+
},
14431+
"NotificationFeedItem": {
14432+
"type": "object",
14433+
"properties": {
14434+
"id": {
14435+
"type": "string"
14436+
},
14437+
"eventType": {
14438+
"type": "string"
14439+
},
14440+
"repoFullName": {
14441+
"type": "string"
14442+
},
14443+
"pullNumber": {
14444+
"type": "number",
14445+
"nullable": true
14446+
},
14447+
"title": {
14448+
"type": "string"
14449+
},
14450+
"body": {
14451+
"type": "string"
14452+
},
14453+
"deeplink": {
14454+
"type": "string"
14455+
},
14456+
"status": {
14457+
"type": "string",
14458+
"enum": [
14459+
"delivered",
14460+
"read"
14461+
]
14462+
},
14463+
"createdAt": {
14464+
"type": "string"
14465+
}
14466+
},
14467+
"required": [
14468+
"id",
14469+
"eventType",
14470+
"repoFullName",
14471+
"pullNumber",
14472+
"title",
14473+
"body",
14474+
"deeplink",
14475+
"status",
14476+
"createdAt"
14477+
]
14478+
},
14479+
"NotificationsMarked": {
14480+
"type": "object",
14481+
"properties": {
14482+
"login": {
14483+
"type": "string"
14484+
},
14485+
"marked": {
14486+
"type": "number"
14487+
}
14488+
},
14489+
"required": [
14490+
"login",
14491+
"marked"
14492+
]
14493+
},
14494+
"ReviewRiskExplanation": {
14495+
"type": "object",
14496+
"properties": {
14497+
"preflight": {
14498+
"$ref": "#/components/schemas/PreflightResult"
14499+
},
14500+
"roleContext": {
14501+
"allOf": [
14502+
{
14503+
"$ref": "#/components/schemas/RoleContext"
14504+
},
14505+
{
14506+
"nullable": true
14507+
}
14508+
]
14509+
},
14510+
"recommendation": {
14511+
"type": "string",
14512+
"enum": [
14513+
"likely_duplicate",
14514+
"maintainer_lane",
14515+
"needs_author",
14516+
"review",
14517+
"watch"
14518+
]
14519+
},
14520+
"summary": {
14521+
"type": "string"
14522+
}
14523+
},
14524+
"required": [
14525+
"preflight",
14526+
"roleContext",
14527+
"recommendation",
14528+
"summary"
14529+
]
1435014530
}
1435114531
},
1435214532
"parameters": {},
@@ -18590,6 +18770,173 @@
1859018770
}
1859118771
]
1859218772
}
18773+
},
18774+
"/v1/contributors/{login}/pr-outcomes": {
18775+
"get": {
18776+
"summary": "Contributor post-merge PR outcome history",
18777+
"parameters": [
18778+
{
18779+
"schema": {
18780+
"type": "string"
18781+
},
18782+
"required": true,
18783+
"name": "login",
18784+
"in": "path"
18785+
},
18786+
{
18787+
"schema": {
18788+
"type": "integer",
18789+
"minimum": 0,
18790+
"exclusiveMinimum": true,
18791+
"maximum": 100
18792+
},
18793+
"required": false,
18794+
"name": "limit",
18795+
"in": "query"
18796+
}
18797+
],
18798+
"responses": {
18799+
"200": {
18800+
"description": "Self-scoped post-merge outcome records with public-safe attribution (mirrors loopover_pr_outcome).",
18801+
"content": {
18802+
"application/json": {
18803+
"schema": {
18804+
"$ref": "#/components/schemas/ContributorPrOutcomes"
18805+
}
18806+
}
18807+
}
18808+
}
18809+
},
18810+
"security": [
18811+
{
18812+
"LoopOverBearer": []
18813+
},
18814+
{
18815+
"LoopOverSessionCookie": []
18816+
}
18817+
]
18818+
}
18819+
},
18820+
"/v1/contributors/{login}/notifications": {
18821+
"get": {
18822+
"summary": "Contributor badge notification feed",
18823+
"parameters": [
18824+
{
18825+
"schema": {
18826+
"type": "string"
18827+
},
18828+
"required": true,
18829+
"name": "login",
18830+
"in": "path"
18831+
}
18832+
],
18833+
"responses": {
18834+
"200": {
18835+
"description": "The contributor's own badge notification feed (self-scoped), newest first, with an unread count.",
18836+
"content": {
18837+
"application/json": {
18838+
"schema": {
18839+
"$ref": "#/components/schemas/NotificationFeed"
18840+
}
18841+
}
18842+
}
18843+
}
18844+
},
18845+
"security": [
18846+
{
18847+
"LoopOverBearer": []
18848+
},
18849+
{
18850+
"LoopOverSessionCookie": []
18851+
}
18852+
]
18853+
}
18854+
},
18855+
"/v1/contributors/{login}/notifications/read": {
18856+
"post": {
18857+
"summary": "Mark contributor notifications read",
18858+
"parameters": [
18859+
{
18860+
"schema": {
18861+
"type": "string"
18862+
},
18863+
"required": true,
18864+
"name": "login",
18865+
"in": "path"
18866+
}
18867+
],
18868+
"requestBody": {
18869+
"content": {
18870+
"application/json": {
18871+
"schema": {
18872+
"type": "object",
18873+
"properties": {
18874+
"ids": {
18875+
"type": "array",
18876+
"items": {
18877+
"type": "string"
18878+
}
18879+
}
18880+
}
18881+
}
18882+
}
18883+
}
18884+
},
18885+
"responses": {
18886+
"200": {
18887+
"description": "Marks the contributor's delivered badge notifications read; an absent/empty ids array marks all.",
18888+
"content": {
18889+
"application/json": {
18890+
"schema": {
18891+
"$ref": "#/components/schemas/NotificationsMarked"
18892+
}
18893+
}
18894+
}
18895+
},
18896+
"400": {
18897+
"description": "Invalid mark-read body"
18898+
}
18899+
},
18900+
"security": [
18901+
{
18902+
"LoopOverBearer": []
18903+
},
18904+
{
18905+
"LoopOverSessionCookie": []
18906+
}
18907+
]
18908+
}
18909+
},
18910+
"/v1/preflight/review-risk": {
18911+
"post": {
18912+
"summary": "Explain review risk for a planned pull request",
18913+
"responses": {
18914+
"200": {
18915+
"description": "Review-risk explanation with preflight, role context, and recommendation",
18916+
"content": {
18917+
"application/json": {
18918+
"schema": {
18919+
"$ref": "#/components/schemas/ReviewRiskExplanation"
18920+
}
18921+
}
18922+
}
18923+
},
18924+
"400": {
18925+
"description": "Invalid preflight input"
18926+
},
18927+
"403": {
18928+
"description": "Forbidden when contributorLogin does not match the authenticated session"
18929+
}
18930+
},
18931+
"security": [
18932+
{
18933+
"LoopOverBearer": []
18934+
},
18935+
{
18936+
"LoopOverSessionCookie": []
18937+
}
18938+
]
18939+
}
1859318940
}
1859418941
},
1859518942
"servers": [
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { describe, expect, it } from "vitest";
3+
4+
import {
5+
Accordion,
6+
AccordionContent,
7+
AccordionItem,
8+
AccordionTrigger,
9+
} from "@loopover/ui-kit/components/accordion";
10+
11+
// #7015: every other styled interactive trigger in ui-kit (button, tabs, toggle, switch, checkbox, slider)
12+
// applies a focus-visible:ring-* class; AccordionTrigger was the one that didn't, leaving keyboard users with
13+
// no visible indication of focus when tabbing to an accordion header.
14+
describe("AccordionTrigger focus-visible indicator (#7015)", () => {
15+
it("pairs the trigger with the kit's standard focus-visible ring classes", () => {
16+
render(
17+
<Accordion type="single" collapsible>
18+
<AccordionItem value="item-1">
19+
<AccordionTrigger>Section</AccordionTrigger>
20+
<AccordionContent>Details</AccordionContent>
21+
</AccordionItem>
22+
</Accordion>,
23+
);
24+
const trigger = screen.getByRole("button", { name: "Section" });
25+
expect(trigger.className).toContain("focus-visible:outline-none");
26+
expect(trigger.className).toContain("focus-visible:ring-2");
27+
expect(trigger.className).toContain("focus-visible:ring-ring");
28+
expect(trigger.className).toContain("focus-visible:ring-offset-2");
29+
});
30+
});

0 commit comments

Comments
 (0)