feat: File upload support (#11108)

* build: bump discord-api-types

* feat: add support

* docs: correct examples

* fix(MappedComponentTypes): fix description

Co-authored-by: advaith <advaithj1@gmail.com>

* fix: use `z.int()`

* chore: remove errors

---------

Co-authored-by: advaith <advaithj1@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Jiralite
2025-10-24 11:16:05 +01:00
committed by GitHub
parent 63b5923deb
commit c84024968e
9 changed files with 257 additions and 9 deletions

View File

@@ -0,0 +1,59 @@
import type { APIFileUploadComponent } from 'discord-api-types/v10';
import { ComponentType } from 'discord-api-types/v10';
import { describe, test, expect } from 'vitest';
import { FileUploadBuilder } from '../../src/components/fileUpload/FileUpload.js';
const fileUploadComponent = () => new FileUploadBuilder();
describe('File Upload Components', () => {
describe('Assertion Tests', () => {
test('GIVEN valid fields THEN builder does not throw', () => {
expect(() => {
fileUploadComponent().setCustomId('foobar').toJSON();
}).not.toThrowError();
expect(() => {
fileUploadComponent().setCustomId('foobar').setMinValues(2).setMaxValues(9).toJSON();
}).not.toThrowError();
});
});
test('GIVEN invalid fields THEN builder throws', () => {
expect(() => fileUploadComponent().toJSON()).toThrowError();
expect(() => fileUploadComponent().setCustomId('test').setId(4.4).toJSON()).toThrowError();
expect(() => {
fileUploadComponent().setCustomId('a'.repeat(500)).toJSON();
}).toThrowError();
expect(() => {
fileUploadComponent().setCustomId('a').setMaxValues(55).toJSON();
}).toThrowError();
expect(() => {
fileUploadComponent().setCustomId('a').setMinValues(-1).toJSON();
}).toThrowError();
});
test('GIVEN valid input THEN valid JSON outputs are given', () => {
const fileUploadData = {
type: ComponentType.FileUpload,
custom_id: 'custom id',
min_values: 5,
max_values: 6,
required: false,
} satisfies APIFileUploadComponent;
expect(new FileUploadBuilder(fileUploadData).toJSON()).toEqual(fileUploadData);
expect(
fileUploadComponent()
.setCustomId(fileUploadData.custom_id)
.setMaxValues(fileUploadData.max_values)
.setMinValues(fileUploadData.min_values)
.setRequired(fileUploadData.required)
.toJSON(),
).toEqual(fileUploadData);
});
});

View File

@@ -1,4 +1,9 @@
import type { APILabelComponent, APIStringSelectComponent, APITextInputComponent } from 'discord-api-types/v10';
import type {
APIFileUploadComponent,
APILabelComponent,
APIStringSelectComponent,
APITextInputComponent,
} from 'discord-api-types/v10';
import { ComponentType, TextInputStyle } from 'discord-api-types/v10';
import { describe, test, expect } from 'vitest';
import { LabelBuilder } from '../../src/index.js';
@@ -27,6 +32,14 @@ describe('Label components', () => {
)
.toJSON(),
).not.toThrow();
expect(() =>
new LabelBuilder()
.setLabel('label')
.setId(5)
.setFileUploadComponent((fileUpload) => fileUpload.setCustomId('test'))
.toJSON(),
).not.toThrow();
});
test('GIVEN invalid fields THEN build does throw', () => {
@@ -40,6 +53,13 @@ describe('Label components', () => {
.setStringSelectMenuComponent((stringSelectMenu) => stringSelectMenu)
.toJSON(),
).toThrow();
expect(() =>
new LabelBuilder()
.setLabel('l'.repeat(1_000))
.setFileUploadComponent((fileUpload) => fileUpload)
.toJSON(),
).toThrow();
});
test('GIVEN valid input THEN valid JSON outputs are given', () => {
@@ -73,6 +93,19 @@ describe('Label components', () => {
id: 5,
} satisfies APILabelComponent;
const labelWithFileUploadData = {
type: ComponentType.Label,
component: {
type: ComponentType.FileUpload,
custom_id: 'custom_id',
min_values: 9,
required: true,
} satisfies APIFileUploadComponent,
label: 'label',
description: 'description',
id: 5,
} satisfies APILabelComponent;
expect(new LabelBuilder(labelWithTextInputData).toJSON()).toEqual(labelWithTextInputData);
expect(new LabelBuilder(labelWithStringSelectData).toJSON()).toEqual(labelWithStringSelectData);
@@ -104,6 +137,15 @@ describe('Label components', () => {
.setId(5)
.toJSON(),
).toEqual(labelWithStringSelectData);
expect(
new LabelBuilder()
.setFileUploadComponent((fileUpload) => fileUpload.setCustomId('custom_id').setMinValues(9).setRequired())
.setLabel('label')
.setDescription('description')
.setId(5)
.toJSON(),
).toEqual(labelWithFileUploadData);
});
});
});