Skip to content
Closed
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
74 changes: 74 additions & 0 deletions dist/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35204,6 +35204,28 @@
"x",
"y"
]
},
"small": {
"description": "Details about the small preview version of the attachment.",
"oneOf": [
{
"$ref": "#/components/schemas/MetaDetails"
},
{
"type": "null"
}
]
},
"original": {
"description": "Details about the original version of the attachment.",
"oneOf": [
{
"$ref": "#/components/schemas/MetaDetails"
},
{
"type": "null"
}
]
}
}
},
Expand Down Expand Up @@ -35241,6 +35263,58 @@
"description": "Official Mastodon API documentation"
}
},
"MetaDetails": {
"type": "object",
"description": "Metadata details about a media attachment.",
"properties": {
"aspect": {
"description": "The media aspect ratio of the video or image attachment.",
"type": [
"number",
"null"
]
},
"bitrate": {
"description": "The media bitrate of the video or audio attachment.",
"type": [
"integer",
"null"
]
},
"duration": {
"description": "The duration of the video attachment.",
"type": [
"number",
"null"
]
},
"frame_rate": {
"description": "The frame rate of the video attachment.",
"type": [
"string",
"null"
]
},
"height": {
"description": "The height of the attachment in pixels.",
"type": [
"integer",
"null"
]
},
"width": {
"description": "The width of the attachment in pixels.",
"type": [
"integer",
"null"
]
}
},
"externalDocs": {
"url": "https://docs.joinmastodon.org/entities/MetaDetails/#attributes",
"description": "Official Mastodon API documentation"
}
},
"Notification": {
"type": "object",
"description": "Represents a notification of an event relevant to the user.",
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/parsers/EntityParser.draft.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ describe('EntityParser - Draft File Handling', () => {
// This test validates that only explicit draft: true is filtered
// This is implicitly tested by checking that we still get a reasonable number of entities
const entities = parser.parseAllEntities();
expect(entities.length).toBe(91); // Exact count after removing EncryptedMessage and entities from blocked files (increased due to extracted nested entities + Admin::DimensionData + DiscoverOauthServerConfigurationResponse + OEmbedResponse)
expect(entities.length).toBe(92); // Exact count after removing EncryptedMessage and entities from blocked files (increased due to extracted nested entities + Admin::DimensionData + DiscoverOauthServerConfigurationResponse + OEmbedResponse + MetaDetails)
});
});
85 changes: 85 additions & 0 deletions src/__tests__/parsers/EntityParser.metadetails.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { EntityParser } from '../../parsers/EntityParser';

describe('EntityParser - MetaDetails Entity', () => {
let entities: ReturnType<EntityParser['parseAllEntities']>;

beforeAll(() => {
const parser = new EntityParser();
entities = parser.parseAllEntities();
});

test('should parse MetaDetails entity', () => {
const metaDetails = entities.find((e) => e.name === 'MetaDetails');

expect(metaDetails).toBeDefined();
expect(metaDetails?.description).toBe(
'Metadata details about a media attachment.'
);
});

test('MetaDetails should have all required properties', () => {
const metaDetails = entities.find((e) => e.name === 'MetaDetails');

expect(metaDetails).toBeDefined();
expect(metaDetails?.attributes).toBeDefined();

const attributeNames = metaDetails?.attributes.map((attr) => attr.name);
expect(attributeNames).toContain('width');
expect(attributeNames).toContain('height');
expect(attributeNames).toContain('frame_rate');
expect(attributeNames).toContain('duration');
expect(attributeNames).toContain('bitrate');
expect(attributeNames).toContain('aspect');
});

test('MetaDetails properties should be nullable', () => {
const metaDetails = entities.find((e) => e.name === 'MetaDetails');

expect(metaDetails).toBeDefined();
expect(metaDetails?.attributes).toBeDefined();

// All properties should be nullable
metaDetails?.attributes.forEach((attr) => {
expect(attr.nullable).toBe(true);
});
});

test('MediaAttachment should have meta[small] and meta[original] properties', () => {
const mediaAttachment = entities.find((e) => e.name === 'MediaAttachment');

expect(mediaAttachment).toBeDefined();
expect(mediaAttachment?.attributes).toBeDefined();

const attributeNames = mediaAttachment?.attributes.map((attr) => attr.name);
expect(attributeNames).toContain('meta[small]');
expect(attributeNames).toContain('meta[original]');
});

test('MediaAttachment meta[small] should reference MetaDetails', () => {
const mediaAttachment = entities.find((e) => e.name === 'MediaAttachment');

expect(mediaAttachment).toBeDefined();

const metaSmall = mediaAttachment?.attributes.find(
(attr) => attr.name === 'meta[small]'
);
expect(metaSmall).toBeDefined();
expect(metaSmall?.type).toContain('MetaDetails');
expect(metaSmall?.optional).toBe(true);
expect(metaSmall?.nullable).toBe(true);
});

test('MediaAttachment meta[original] should reference MetaDetails', () => {
const mediaAttachment = entities.find((e) => e.name === 'MediaAttachment');

expect(mediaAttachment).toBeDefined();

const metaOriginal = mediaAttachment?.attributes.find(
(attr) => attr.name === 'meta[original]'
);
expect(metaOriginal).toBeDefined();
expect(metaOriginal?.type).toContain('MetaDetails');
expect(metaOriginal?.optional).toBe(true);
expect(metaOriginal?.nullable).toBe(true);
});
});