feat(concerts): show artwork-themed event details in app

This commit is contained in:
zarzet committed 2026-09-25 12:00:28 +07:00
1 parent ab58cdbb0c
commit abb8dc4a42
18 files changed
+1047 -23

No files matched your search

@@ -185,6 +185,7 @@ impl Backend {
"album" => "getAlbum",
"playlist" => "getPlaylist",
"artist" => "getArtist",
"concert" => "getConcert",
_ => {
return Err(ResolverError::Failed(format!(
"unsupported provider resource type: {kind}"
@@ -393,6 +394,7 @@ fn response(kind: &str, value: &Value, check: &Check<'_>) -> Result<Value, Resol
check().map_err(ResolverError::Cancelled)?;
let cover = text(value, "cover_url");
Ok(match kind {
"concert" => json!({"concert": value}),
// Move normalized values into the envelope. json! serializes borrowed
// expressions, duplicating every field of an already-built track list.
"track" => Map::from_iter([("track".into(), track(value, "", 0))]).into(),
@@ -21,11 +21,19 @@ function getArtist(id) {
return {id, name: "Example Artist", image_url: "https://example.invalid/portrait.jpg",
concerts: id === "bad-concerts" ? {} : [{id: "event-1", location: "Example City",
venue: "Example Hall", startAt: "2026-10-07T01:00:00Z", timeZone: "America/New_York",
url: "https://example.invalid/events/1"}],
url: "https://example.invalid/events/1", detailId: "event-1"}],
headerLogo: "https://example.invalid/logo.png", albumsNext: "artist-page-2", albums: []};
}
function handleUrl() { return {type: "artist", artist: getArtist("artist-1")}; }
registerExtension({getAlbum: collection, getPlaylist: collection, getArtist, handleUrl});
function getConcert(id) {
return {id, artistName: "Example Artist", title: "Example Show", venue: "Example Hall",
address: "123 Example Street", startAt: "2026-10-07T01:00:00Z",
endAt: "2026-10-07T04:00:00Z", timeZone: "America/New_York",
ticketUrl: "https://example.invalid/tickets/1", mapUrl: "https://example.invalid/maps/1",
coverUrl: "https://example.invalid/artist.jpg", attribution: "Example Events",
setList: {id: "list-1", name: "Concert Set List", coverUrl: "https://example.invalid/list.jpg"}};
}
registerExtension({getAlbum: collection, getPlaylist: collection, getArtist, getConcert, handleUrl});
"#;
fn fixture() -> (tempfile::TempDir, Backend) {
@@ -54,6 +62,30 @@ fn fixture() -> (tempfile::TempDir, Backend) {
(root, backend)
}
#[test]
fn concert_details_preserve_generic_actions_and_set_list() {
let (_root, backend) = fixture();
let result: Value = serde_json::from_str(
&backend
.get_provider_metadata_json(ID, "concert", "event-1", &|| Ok(()))
.unwrap(),
)
.unwrap();
let detail = &result["concert"];
assert_eq!(detail["id"], "event-1");
assert_eq!(detail["artist_name"], "Example Artist");
assert_eq!(detail["start_at"], "2026-10-07T01:00:00Z");
assert_eq!(detail["end_at"], "2026-10-07T04:00:00Z");
assert_eq!(detail["ticket_url"], "https://example.invalid/tickets/1");
assert_eq!(detail["map_url"], "https://example.invalid/maps/1");
assert_eq!(detail["set_list"]["id"], "list-1");
assert_eq!(
detail["set_list"]["cover_url"],
"https://example.invalid/list.jpg"
);
assert_eq!(detail["attribution"], "Example Events");
}
#[test]
fn response_envelopes_preserve_json_and_cancellation() {
let value = json!({