-
Notifications
You must be signed in to change notification settings - Fork 2
Card art accessibility improvements #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
47614bc
7c34b14
7d0930c
9f89584
27732cb
35f38e5
9e65846
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,13 +40,24 @@ const showErrorOverlay = computed(() => { | |
<template> | ||
<div class="art-frame"> | ||
<div v-if="showErrorOverlay" class="overlay error"> | ||
<div class="shape-x"></div> | ||
<div> | ||
<div class="shape-x"></div> | ||
<p>There was an error loading the next card. You should skip this one.</p> | ||
</div> | ||
</div> | ||
<div v-else-if="showLoadingOverlay" class="overlay loading"> | ||
<LoadingPulser class="pulser" /> | ||
<p class="vh">Loading next card</p> | ||
</div> | ||
<div class="flavor-mask" v-if="card.flavor_name">Hint: this print has a flavor name.</div> | ||
<img alt="" class="vh preload" :src="imageUri" :onload="onLoad" :onerror="onError" /> | ||
<img | ||
alt="" | ||
class="vh preload" | ||
:src="imageUri" | ||
:onload="onLoad" | ||
:onerror="onError" | ||
data-testid="card-art-preload" | ||
/> | ||
<img :src="imageUri" /> | ||
</div> | ||
</template> | ||
|
@@ -74,12 +85,15 @@ $default-art-width: 626px; | |
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
text-align: center; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. both the style changes here are to make the text and x in error overlay be centered. |
||
padding: 1rem; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added some padding here because the class/saga art crops don't give you much space and the text was butting up against the edge. |
||
|
||
background: rgba(0 0 0 / 0.5); | ||
} | ||
|
||
.shape-x { | ||
color: var(--c-salmon); | ||
margin: auto; | ||
} | ||
|
||
img { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { fireEvent, render, screen } from "@testing-library/vue"; | ||
import CardArt from "../CardArt.vue"; | ||
import { LoadingStatus } from "../../store"; | ||
import { CardBank } from "../../models/__test__/card-bank.util"; | ||
|
||
describe("CardArt", () => { | ||
it("shows an error overlay if loadingNext prop is Failed", async () => { | ||
const { rerender } = render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
expect( | ||
screen.queryByText("There was an error loading the next card. You should skip this one.") | ||
).not.toBeInTheDocument(); | ||
|
||
await rerender({ | ||
loadingNext: LoadingStatus.Failed, | ||
}); | ||
expect( | ||
screen.queryByText("There was an error loading the next card. You should skip this one.") | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it("shows an error overlay if the card image fails to load", async () => { | ||
render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
expect( | ||
screen.queryByText("There was an error loading the next card. You should skip this one.") | ||
).not.toBeInTheDocument(); | ||
|
||
await fireEvent.error(screen.getByTestId("card-art-preload")); | ||
|
||
expect( | ||
screen.queryByText("There was an error loading the next card. You should skip this one.") | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it("starts out with a loading overlay until image loads", async () => { | ||
render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
|
||
expect(screen.queryByText("Loading next card")).toBeInTheDocument(); | ||
|
||
await fireEvent.load(screen.getByTestId("card-art-preload")); | ||
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument(); | ||
}); | ||
|
||
it("shows a loading overlay if loadingNext prop is Pending", async () => { | ||
const { rerender } = render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
await fireEvent.load(screen.getByTestId("card-art-preload")); | ||
|
||
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument(); | ||
|
||
await rerender({ | ||
loadingNext: LoadingStatus.Pending, | ||
}); | ||
expect(screen.queryByText("Loading next card")).toBeInTheDocument(); | ||
}); | ||
|
||
it("shows a loading overlay when the card image uri changes", async () => { | ||
const { rerender } = render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
await fireEvent.load(screen.getByTestId("card-art-preload")); | ||
|
||
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument(); | ||
|
||
await rerender({ | ||
card: CardBank.Alesha, | ||
}); | ||
expect(screen.getByText("Loading next card")).toBeInTheDocument(); | ||
}); | ||
|
||
it("prefers error overlay over loading overlay if both would apply", async () => { | ||
render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Pending, | ||
}, | ||
}); | ||
await fireEvent.error(screen.getByTestId("card-art-preload")); | ||
|
||
expect(screen.queryByText("Loading next card")).not.toBeInTheDocument(); | ||
expect( | ||
screen.queryByText("There was an error loading the next card. You should skip this one.") | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it("uses art crop for a card with a top level image uris object", async () => { | ||
render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
|
||
// just a double check that this card does have an art crop | ||
expect(CardBank.ArborElf.image_uris?.art_crop).toBeTruthy(); | ||
expect(screen.getByTestId("card-art-preload")).toHaveAttribute( | ||
"src", | ||
CardBank.ArborElf.image_uris?.art_crop | ||
); | ||
}); | ||
|
||
it("uses a random face from a double sided card", async () => { | ||
const mathSpy = vi.spyOn(Math, "random").mockReturnValue(0.3); | ||
const { rerender } = render(CardArt, { | ||
props: { | ||
card: CardBank.HeartOfTheExplorer, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
|
||
// just a double check that this card does have an art crop | ||
const expectedFirstFaceArtCrop = CardBank.HeartOfTheExplorer.card_faces[0].image_uris?.art_crop; | ||
expect(expectedFirstFaceArtCrop).toBeTruthy(); | ||
expect(screen.getByTestId("card-art-preload")).toHaveAttribute("src", expectedFirstFaceArtCrop); | ||
|
||
mathSpy.mockReturnValue(0.7); | ||
await rerender({ | ||
card: CardBank.DraculaLordOfBlood, | ||
}); | ||
|
||
// just a double check that this card does have an art crop | ||
const expectedSecondFaceArtCrop = | ||
CardBank.HeartOfTheExplorer.card_faces[1].image_uris?.art_crop; | ||
expect(expectedSecondFaceArtCrop).toBeTruthy(); | ||
expect(screen.getByTestId("card-art-preload")).toHaveAttribute( | ||
"src", | ||
expectedSecondFaceArtCrop | ||
); | ||
}); | ||
|
||
it("provides a flavor mask for cards that have a flavor name", async () => { | ||
const { rerender } = render(CardArt, { | ||
props: { | ||
card: CardBank.ArborElf, | ||
loadingNext: LoadingStatus.Success, | ||
}, | ||
}); | ||
|
||
expect(screen.queryByText("Hint: this print has a flavor name.")).not.toBeInTheDocument(); | ||
|
||
await rerender({ | ||
card: CardBank.Eleven, | ||
}); | ||
expect(screen.queryByText("Hint: this print has a flavor name.")).toBeInTheDocument(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ export function makeCard<T extends ScryfallCard>(overrides: Partial<T> = {}): T | |
scryfall_uri: "<scryfall uri>", | ||
type_line: "<type line>", | ||
set: "<set code>", | ||
image_uris: makeImageUris(), | ||
image_uris: makeImageUris(overrides.name), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is so that the image uri does change for the computed property, so the watch on the |
||
...overrides, | ||
}; | ||
return card as T; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needed to add a data-testid here to target it in the test to trigger the load and error events.