Skip to content
Open
40 changes: 40 additions & 0 deletions src/platform/assets/utils/assetMetadataUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,44 @@ describe('assetMetadataUtils', () => {
expect(getAssetCardTitle(asset)).toBe('pretty.png')
})
})

describe('unified asset response shape (BE-808 RFC)', () => {
// Cloud asset: `asset.name` is a content hash; `display_name` carries
// the user-facing label.
const cloudShape: AssetItem = {
...mockAsset,
id: 'cloud-asset-id',
name: 'blake3:abc1234567890def.png',
hash: 'blake3:abc1234567890def.png',
display_name: 'sunset.png'
}

// OSS asset: `asset.name` is already the filename; `display_name` is
// nullable per BE-1045 spec — clients fall back to `asset.name`.
const ossShape: AssetItem = {
...mockAsset,
id: 'oss-asset-id',
name: 'sunset.png',
hash: null,
display_name: undefined
}

it('renders the same label for the Cloud and OSS shapes via getAssetDisplayFilename', () => {
expect(getAssetDisplayFilename(cloudShape)).toBe('sunset.png')
expect(getAssetDisplayFilename(ossShape)).toBe('sunset.png')
})

it('renders the same label via getAssetCardTitle', () => {
expect(getAssetCardTitle(cloudShape)).toBe('sunset.png')
expect(getAssetCardTitle(ossShape)).toBe('sunset.png')
})

it('honours OSS-emitted display_name when present', () => {
const ossWithDisplayName: AssetItem = {
...ossShape,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: name: 'sunset.png' is already inherited from ...ossShape — the explicit re-assignment is a no-op and slightly muddies what the test is varying (the display_name field). Safe to drop.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — dropped the redundant re-assignment; the fixture now only varies display_name.

display_name: 'Curated Sunset'
}
expect(getAssetDisplayFilename(ossWithDisplayName)).toBe('Curated Sunset')
})
})
})
12 changes: 4 additions & 8 deletions src/platform/assets/utils/assetMetadataUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,9 @@ export function getAssetStoredFilename(asset: AssetItem): string {
}

/**
* Gets the human-readable filename to render in UI surfaces.
* Fallback chain: user_metadata.filename → metadata.filename →
* asset.display_name → asset.name.
*
* `display_name` is populated by queue output mappers in Cloud where
* `asset.name` is a content hash. Use this helper for labels/titles only;
* for serialized identifiers use {@link getAssetFilename}.
* Human-readable filename for UI labels.
* Fallback: user_metadata.filename → metadata.filename → display_name → asset.name.
* For serialized identifiers use {@link getAssetFilename}.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the trimmed docstring loses the useful "queue output mappers in Cloud populate display_name" context. Since useMissingMediaInteractions.getMediaDisplayName now relies on that contract, consider keeping one short sentence about who populates display_name.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally left as-is. The empirical Cloud probe (PR description §6) showed display_name is null across all sampled Cloud assets and asset.name is already a friendly filename — so the "queue output mappers populate display_name" framing is not current production behaviour and was deliberately dropped to avoid a misleading docstring. Per the BE-808 RFC display_name is the unified field both backends emit once BE-1043/1044 land; the docstring reflects that contract rather than naming a specific (currently inaccurate) populator.

export function getAssetDisplayFilename(asset: AssetItem): string {
return (
Expand All @@ -208,7 +204,7 @@ export function getAssetDisplayFilename(asset: AssetItem): string {
* Prefers a user-curated name (user_metadata.name / metadata.name) when it
* actually differs from asset.name, so a user-renamed model keeps its
* display name. Falls through to {@link getAssetDisplayFilename} when the
* curated name is absent or equal to asset.name (Cloud hash case).
* curated name is absent or equal to asset.name (hash-keyed asset case).
*/
export function getAssetCardTitle(asset: AssetItem): string {
const curatedName = getStringProperty(asset, 'name')
Expand Down
Loading