WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit fb7f7a0

Browse files
Card art accessibility improvements (#114)
* feat: make error overlay more accessible * feat: add vh text for loading overlay * chore: document that error overlay matters more than loading overlay * chore: add random card face choice logic * chore: add test for flavor text mask * fix: apply PR feedback * fix: apply some padding * Update src/components/CardArt.vue --------- Co-authored-by: Scarlett <[email protected]>
1 parent f444297 commit fb7f7a0

File tree

3 files changed

+184
-3
lines changed

3 files changed

+184
-3
lines changed

src/components/CardArt.vue

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,24 @@ const showErrorOverlay = computed(() => {
4040
<template>
4141
<div class="art-frame">
4242
<div v-if="showErrorOverlay" class="overlay error">
43-
<div class="shape-x"></div>
43+
<div>
44+
<div class="shape-x"></div>
45+
<p>There was an error loading the next card. You should skip this one.</p>
46+
</div>
4447
</div>
4548
<div v-else-if="showLoadingOverlay" class="overlay loading">
4649
<LoadingPulser class="pulser" />
50+
<p class="vh">Loading next card</p>
4751
</div>
4852
<div class="flavor-mask" v-if="card.flavor_name">Hint: this print has a flavor name.</div>
49-
<img alt="" class="vh preload" :src="imageUri" :onload="onLoad" :onerror="onError" />
53+
<img
54+
alt=""
55+
class="vh preload"
56+
:src="imageUri"
57+
:onload="onLoad"
58+
:onerror="onError"
59+
data-testid="card-art-preload"
60+
/>
5061
<img :src="imageUri" />
5162
</div>
5263
</template>
@@ -74,12 +85,15 @@ $default-art-width: 626px;
7485
display: flex;
7586
align-items: center;
7687
justify-content: center;
88+
text-align: center;
89+
padding: 10px;
7790
7891
background: rgba(0 0 0 / 0.5);
7992
}
8093
8194
.shape-x {
8295
color: var(--c-salmon);
96+
margin: auto;
8397
}
8498
8599
img {
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { fireEvent, render, screen } from "@testing-library/vue";
2+
import CardArt from "../CardArt.vue";
3+
import { LoadingStatus } from "../../store";
4+
import { CardBank } from "../../models/__test__/card-bank.util";
5+
6+
describe("CardArt", () => {
7+
it("shows an error overlay if loadingNext prop is Failed", async () => {
8+
const { rerender } = render(CardArt, {
9+
props: {
10+
card: CardBank.ArborElf,
11+
loadingNext: LoadingStatus.Success,
12+
},
13+
});
14+
expect(
15+
screen.queryByText("There was an error loading the next card. You should skip this one.")
16+
).not.toBeInTheDocument();
17+
18+
await rerender({
19+
loadingNext: LoadingStatus.Failed,
20+
});
21+
expect(
22+
screen.queryByText("There was an error loading the next card. You should skip this one.")
23+
).toBeInTheDocument();
24+
});
25+
26+
it("shows an error overlay if the card image fails to load", async () => {
27+
render(CardArt, {
28+
props: {
29+
card: CardBank.ArborElf,
30+
loadingNext: LoadingStatus.Success,
31+
},
32+
});
33+
expect(
34+
screen.queryByText("There was an error loading the next card. You should skip this one.")
35+
).not.toBeInTheDocument();
36+
37+
await fireEvent.error(screen.getByTestId("card-art-preload"));
38+
39+
expect(
40+
screen.queryByText("There was an error loading the next card. You should skip this one.")
41+
).toBeInTheDocument();
42+
});
43+
44+
it("starts out with a loading overlay until image loads", async () => {
45+
render(CardArt, {
46+
props: {
47+
card: CardBank.ArborElf,
48+
loadingNext: LoadingStatus.Success,
49+
},
50+
});
51+
52+
expect(screen.queryByText("Loading next card")).toBeInTheDocument();
53+
54+
await fireEvent.load(screen.getByTestId("card-art-preload"));
55+
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument();
56+
});
57+
58+
it("shows a loading overlay if loadingNext prop is Pending", async () => {
59+
const { rerender } = render(CardArt, {
60+
props: {
61+
card: CardBank.ArborElf,
62+
loadingNext: LoadingStatus.Success,
63+
},
64+
});
65+
await fireEvent.load(screen.getByTestId("card-art-preload"));
66+
67+
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument();
68+
69+
await rerender({
70+
loadingNext: LoadingStatus.Pending,
71+
});
72+
expect(screen.queryByText("Loading next card")).toBeInTheDocument();
73+
});
74+
75+
it("shows a loading overlay when the card image uri changes", async () => {
76+
const { rerender } = render(CardArt, {
77+
props: {
78+
card: CardBank.ArborElf,
79+
loadingNext: LoadingStatus.Success,
80+
},
81+
});
82+
await fireEvent.load(screen.getByTestId("card-art-preload"));
83+
84+
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument();
85+
86+
await rerender({
87+
card: CardBank.Alesha,
88+
});
89+
expect(screen.getByText("Loading next card")).toBeInTheDocument();
90+
});
91+
92+
it("prefers error overlay over loading overlay if both would apply", async () => {
93+
render(CardArt, {
94+
props: {
95+
card: CardBank.ArborElf,
96+
loadingNext: LoadingStatus.Pending,
97+
},
98+
});
99+
await fireEvent.error(screen.getByTestId("card-art-preload"));
100+
101+
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument();
102+
expect(
103+
screen.queryByText("There was an error loading the next card. You should skip this one.")
104+
).toBeInTheDocument();
105+
});
106+
107+
it("uses art crop for a card with a top level image uris object", async () => {
108+
render(CardArt, {
109+
props: {
110+
card: CardBank.ArborElf,
111+
loadingNext: LoadingStatus.Success,
112+
},
113+
});
114+
115+
// just a double check that this card does have an art crop
116+
expect(CardBank.ArborElf.image_uris?.art_crop).toBeTruthy();
117+
expect(screen.getByTestId("card-art-preload")).toHaveAttribute(
118+
"src",
119+
CardBank.ArborElf.image_uris?.art_crop
120+
);
121+
});
122+
123+
it("uses a random face from a double sided card", async () => {
124+
const mathSpy = vi.spyOn(Math, "random").mockReturnValue(0.3);
125+
const { rerender } = render(CardArt, {
126+
props: {
127+
card: CardBank.HeartOfTheExplorer,
128+
loadingNext: LoadingStatus.Success,
129+
},
130+
});
131+
132+
// just a double check that this card does have an art crop
133+
const expectedFirstFaceArtCrop = CardBank.HeartOfTheExplorer.card_faces[0].image_uris?.art_crop;
134+
expect(expectedFirstFaceArtCrop).toBeTruthy();
135+
expect(screen.getByTestId("card-art-preload")).toHaveAttribute("src", expectedFirstFaceArtCrop);
136+
137+
mathSpy.mockReturnValue(0.7);
138+
await rerender({
139+
card: CardBank.DraculaLordOfBlood,
140+
});
141+
142+
// just a double check that this card does have an art crop
143+
const expectedSecondFaceArtCrop =
144+
CardBank.HeartOfTheExplorer.card_faces[1].image_uris?.art_crop;
145+
expect(expectedSecondFaceArtCrop).toBeTruthy();
146+
expect(screen.getByTestId("card-art-preload")).toHaveAttribute(
147+
"src",
148+
expectedSecondFaceArtCrop
149+
);
150+
});
151+
152+
it("provides a flavor mask for cards that have a flavor name", async () => {
153+
const { rerender } = render(CardArt, {
154+
props: {
155+
card: CardBank.ArborElf,
156+
loadingNext: LoadingStatus.Success,
157+
},
158+
});
159+
160+
expect(screen.queryByText("Hint: this print has a flavor name.")).not.toBeInTheDocument();
161+
162+
await rerender({
163+
card: CardBank.Eleven,
164+
});
165+
expect(screen.queryByText("Hint: this print has a flavor name.")).toBeInTheDocument();
166+
});
167+
});

src/models/__test__/card.util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function makeCard<T extends ScryfallCard>(overrides: Partial<T> = {}): T
2929
scryfall_uri: "<scryfall uri>",
3030
type_line: "<type line>",
3131
set: "<set code>",
32-
image_uris: makeImageUris(),
32+
image_uris: makeImageUris(overrides.name),
3333
...overrides,
3434
};
3535
return card as T;

0 commit comments

Comments
 (0)