Fix a test, avoid link nesting in article cards
This commit is contained in:
parent
08821d27f4
commit
2edcfd9a79
7 changed files with 46 additions and 36 deletions
|
|
@ -111,7 +111,7 @@ const openMessageMenu = (page: Page, text: string) =>
|
|||
const openEventMenu = (card: Locator) => card.locator(".join").getByRole("button").last().click()
|
||||
|
||||
const articleCard = (page: Page, title: string) =>
|
||||
page.getByRole("link", {name: /Written by/}).filter({hasText: title})
|
||||
page.locator('[data-component="ArticleItem"]').filter({hasText: title})
|
||||
|
||||
// A FieldInline puts its control in the div immediately after its label, which is how one row of
|
||||
// the hosting card is told apart from the others in the same grid.
|
||||
|
|
|
|||
|
|
@ -101,10 +101,12 @@ const expectReactionRoundTrip = async (page: Page, scope: Locator, opener: Locat
|
|||
const shortDate = (seconds: number) =>
|
||||
new Intl.DateTimeFormat(undefined, {dateStyle: "short"}).format(new Date(seconds * 1000))
|
||||
|
||||
const articleCards = (page: Page) => page.getByRole("link", {name: /Written by/})
|
||||
// The card is a div carrying an overlay link, so it is found by its component rather than by a
|
||||
// role — its own contents include a profile button and the room and action links.
|
||||
const articleCards = (page: Page) => page.locator('[data-component="ArticleItem"]')
|
||||
|
||||
const openArticle = (page: Page, title: string) =>
|
||||
articleCards(page).filter({hasText: title}).getByText(title, {exact: true}).click()
|
||||
articleCards(page).filter({hasText: title}).getByRole("link", {name: title, exact: true}).click()
|
||||
|
||||
test("US-037 write and publish an article", async ({seed, as}) => {
|
||||
const scenario = await seed(({relay, user, at}) => {
|
||||
|
|
@ -570,11 +572,11 @@ test("US-041 publish an article from a room", async ({seed, as}) => {
|
|||
const card = articleCards(page).filter({hasText: "Repotting in Winter"})
|
||||
|
||||
await expect(card).toBeVisible()
|
||||
await expect(card.getByRole("link", {name: "#Lounge"})).toBeVisible()
|
||||
await expect(card.getByRole("link", {name: /#\s*Lounge/})).toBeVisible()
|
||||
|
||||
await openArticle(page, "Repotting in Winter")
|
||||
|
||||
const badge = page.getByRole("link", {name: "Posted in #Lounge"})
|
||||
const badge = page.getByRole("link", {name: /Posted in #\s*Lounge/})
|
||||
|
||||
await expect(badge).toBeVisible()
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ test("US-056 autocomplete a mention or a room reference", async ({seed, as}) =>
|
|||
|
||||
await editor.press("Enter")
|
||||
|
||||
await expect(timeline(page).getByRole("link", {name: "#General"})).toHaveAttribute(
|
||||
await expect(timeline(page).getByRole("link", {name: /#\s*General/})).toHaveAttribute(
|
||||
"href",
|
||||
roomPath(space.url, "general"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ test("US-071 content posts show delivery status in place", async ({seed, as}) =>
|
|||
|
||||
await writeArticle(alice, "Signals in the Noise", "Everything worth hearing is quiet.")
|
||||
|
||||
const article = alice.getByRole("link", {name: /Written by/}).filter({hasText: "Signals"})
|
||||
const article = alice.locator('[data-component="ArticleItem"]').filter({hasText: "Signals"})
|
||||
|
||||
await expect(alice.getByRole("heading", {name: "Write an Article"})).toHaveCount(0)
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ test("US-071 content posts show delivery status in place", async ({seed, as}) =>
|
|||
await alice.goto(`${spacePath(quiet)}/articles`)
|
||||
await writeArticle(alice, "Into the Void", "Nobody is listening.")
|
||||
|
||||
const stuck = alice.getByRole("link", {name: /Written by/}).filter({hasText: "Into the Void"})
|
||||
const stuck = alice.locator('[data-component="ArticleItem"]').filter({hasText: "Into the Void"})
|
||||
|
||||
await expect(stuck.getByText("Sending...")).toBeVisible()
|
||||
await expect(stuck.getByRole("button", {name: "Cancel"})).toBeVisible()
|
||||
|
|
@ -497,7 +497,7 @@ test("US-072 a deleted post is marked deleted", async ({seed, as}) => {
|
|||
// A post whose relay never answered, deleted while it is still marked failed.
|
||||
await writeArticle(alice, "Into the Void", "Nobody is listening.")
|
||||
|
||||
const stuck = alice.getByRole("link", {name: /Written by/}).filter({hasText: "Into the Void"})
|
||||
const stuck = alice.locator('[data-component="ArticleItem"]').filter({hasText: "Into the Void"})
|
||||
|
||||
await expect(stuck.getByText("Failed to send!")).toBeVisible()
|
||||
|
||||
|
|
|
|||
|
|
@ -24,29 +24,36 @@
|
|||
const image = article.image()
|
||||
</script>
|
||||
|
||||
<Link
|
||||
class="cv flex flex-col gap-2 card card-interactive w-full"
|
||||
href={makeArticlePath(url, getAddress(event))}>
|
||||
{#if image}
|
||||
<img src={image} alt="" class="h-40 w-full rounded-2xl object-cover" />
|
||||
{/if}
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
<p class="text-xl">{title || "Untitled"}</p>
|
||||
<p class="whitespace-nowrap text-sm opacity-75">
|
||||
{formatTimestamp(article.publishedAt())}
|
||||
</p>
|
||||
<div data-component="ArticleItem" class="cv relative w-full card card-interactive">
|
||||
<!-- An overlay rather than a wrapper: the card carries a profile button and the room and action
|
||||
links, and none of those may sit inside an anchor. -->
|
||||
<Link
|
||||
class="absolute inset-0 rounded-2xl"
|
||||
href={makeArticlePath(url, getAddress(event))}
|
||||
aria-label={title || "Untitled"} />
|
||||
<div class="pointer-events-none relative flex flex-col gap-2">
|
||||
{#if image}
|
||||
<img src={image} alt="" class="h-40 w-full rounded-2xl object-cover" />
|
||||
{/if}
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
<p class="text-xl">{title || "Untitled"}</p>
|
||||
<p class="whitespace-nowrap text-sm opacity-75">
|
||||
{formatTimestamp(article.publishedAt())}
|
||||
</p>
|
||||
</div>
|
||||
<Content
|
||||
event={{content: summary || event.content, tags: event.tags}}
|
||||
{url}
|
||||
expandMode="inline"
|
||||
minLength={100}
|
||||
maxLength={300} />
|
||||
<div
|
||||
class="pointer-events-auto flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
|
||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||
Written by
|
||||
<ProfileLink pubkey={event.pubkey} {url} />
|
||||
</span>
|
||||
<ArticleActions showRoom showActivity {url} {event} />
|
||||
</div>
|
||||
</div>
|
||||
<Content
|
||||
event={{content: summary || event.content, tags: event.tags}}
|
||||
{url}
|
||||
expandMode="inline"
|
||||
minLength={100}
|
||||
maxLength={300} />
|
||||
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
|
||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||
Written by
|
||||
<ProfileLink pubkey={event.pubkey} {url} />
|
||||
</span>
|
||||
<ArticleActions showRoom showActivity {url} {event} />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@
|
|||
{@html renderAsHtml(parsed)}
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm underline"
|
||||
class="pointer-events-auto text-sm underline"
|
||||
onclick={stopPropagation(preventDefault(expand))}>
|
||||
Read more
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
replaceState = false,
|
||||
...restProps
|
||||
}: {
|
||||
children: Snippet
|
||||
children?: Snippet
|
||||
href: string
|
||||
external?: boolean
|
||||
replaceState?: boolean
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
class?: string
|
||||
style?: string
|
||||
"data-tip"?: string
|
||||
"aria-label"?: string
|
||||
} = $props()
|
||||
|
||||
const go = (e: Event) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue