Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -420,6 +420,46 @@ describe('assetMetadataUtils', () => {
})
})

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

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.

nitpick: (non-blocking) ossShape sets hash: null but none of the three new tests exercise getAssetStoredFilename or getAssetUrlFilename, which are the only functions that consume hash. The field is inert here — either add a stored-filename assertion or drop it to avoid implying coverage that is not there.

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.

nitpick: (non-blocking) ossShape sets hash: null but none of the three new tests exercise getAssetStoredFilename or getAssetUrlFilename, which are the only functions that consume hash. The field is inert here — either add a stored-filename assertion or drop it to avoid implying coverage that is not there.

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.

nitpick: (non-blocking) ossShape sets hash: null but none of the three new tests exercise getAssetStoredFilename or getAssetUrlFilename, which are the only functions that consume hash. The field is inert here — either add a stored-filename assertion or drop it to avoid implying coverage that is not there.

}

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 = {

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.

nitpick: (non-blocking) "honours OSS-emitted display_name when present" exercises the same branch as the existing "falls back to display_name when filename metadata is absent" test at line 365 — identical code path, different fixture string. Per the project parsimony guideline this could be folded into the existing suite or dropped.

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.

nitpick: (non-blocking) "honours OSS-emitted display_name when present" exercises the same branch as the existing "falls back to display_name when filename metadata is absent" test at line 365 — identical code path, different fixture string. Per the project parsimony guideline this could be folded into the existing suite or dropped.

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.

nitpick: (non-blocking) "honours OSS-emitted display_name when present" exercises the same branch as the existing "falls back to display_name when filename metadata is absent" test at line 365 — identical code path, different fixture string. Per the project parsimony guideline this could be folded into the existing suite or dropped.

...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')
})
})

describe('getAssetMetadataDimensions', () => {
it('returns dimensions when width/height are positive integers', () => {
const asset = { ...mockAsset, metadata: { width: 1024, height: 768 } }
Expand Down
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.

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.

nitpick: (non-blocking) every other export in this file opens with an imperative verb (Gets the..., Extracts..., Resolves...) — the new noun-phrase opening "Human-readable filename for UI labels." breaks that consistency.

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.

nitpick: (non-blocking) every other export in this file opens with an imperative verb (Gets the..., Extracts..., Resolves...) — the new noun-phrase opening "Human-readable filename for UI labels." breaks that consistency.

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.

nitpick: (non-blocking) every other export in this file opens with an imperative verb (Gets the..., Extracts..., Resolves...) — the new noun-phrase opening "Human-readable filename for UI labels." breaks that consistency.

* 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.

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.

suggestion: (non-blocking) the shortened docstring drops "Use this helper for labels/titles only" — keeping that positive constraint alongside the existing cross-reference to getAssetFilename would make the display-vs-identifier distinction clear without needing to follow the link.

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.

suggestion: (non-blocking) the shortened docstring drops "Use this helper for labels/titles only" — keeping that positive constraint alongside the existing cross-reference to getAssetFilename would make the display-vs-identifier distinction clear without needing to follow the link.

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.

suggestion: (non-blocking) the shortened docstring drops "Use this helper for labels/titles only" — keeping that positive constraint alongside the existing cross-reference to getAssetFilename would make the display-vs-identifier distinction clear without needing to follow the link.

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