mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
fix: Adjust label predicates and fix buttons emoji/label behaviour (#11317)
* fix: buttons with custom id * fix: button labels * fix: also add refinement to link buttons --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,13 @@ import {
|
|||||||
type APIButtonComponentWithURL,
|
type APIButtonComponentWithURL,
|
||||||
} from 'discord-api-types/v10';
|
} from 'discord-api-types/v10';
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import { PrimaryButtonBuilder, PremiumButtonBuilder, LinkButtonBuilder } from '../../src/index.js';
|
import {
|
||||||
|
PrimaryButtonBuilder,
|
||||||
|
PremiumButtonBuilder,
|
||||||
|
LinkButtonBuilder,
|
||||||
|
DangerButtonBuilder,
|
||||||
|
SecondaryButtonBuilder,
|
||||||
|
} from '../../src/index.js';
|
||||||
|
|
||||||
const longStr =
|
const longStr =
|
||||||
'looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong';
|
'looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong';
|
||||||
@@ -25,6 +31,26 @@ describe('Button Components', () => {
|
|||||||
button.toJSON();
|
button.toJSON();
|
||||||
}).not.toThrowError();
|
}).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const button = new SecondaryButtonBuilder().setCustomId('custom').setLabel('a'.repeat(80));
|
||||||
|
button.toJSON();
|
||||||
|
}).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const button = new DangerButtonBuilder().setCustomId('custom').setEmoji({ name: 'ok' });
|
||||||
|
button.toJSON();
|
||||||
|
}).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const button = new LinkButtonBuilder().setURL('https://discord.js.org').setLabel('a'.repeat(80));
|
||||||
|
button.toJSON();
|
||||||
|
}).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const button = new LinkButtonBuilder().setURL('https://discord.js.org').setEmoji({ name: 'ok' });
|
||||||
|
button.toJSON();
|
||||||
|
}).not.toThrowError();
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
const button = new PremiumButtonBuilder().setSKUId('123456789012345678');
|
const button = new PremiumButtonBuilder().setSKUId('123456789012345678');
|
||||||
button.toJSON();
|
button.toJSON();
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ const selectMenuWithId = () => new StringSelectMenuBuilder({ custom_id: 'hi' });
|
|||||||
const selectMenuOption = () => new StringSelectMenuOptionBuilder();
|
const selectMenuOption = () => new StringSelectMenuOptionBuilder();
|
||||||
|
|
||||||
const longStr = 'a'.repeat(256);
|
const longStr = 'a'.repeat(256);
|
||||||
|
const selectMenuOptionLabelAboveLimit = 'a'.repeat(101);
|
||||||
|
const selectMenuOptionValueAboveLimit = 'a'.repeat(101);
|
||||||
|
const selectMenuOptionDescriptionAboveLimit = 'a'.repeat(101);
|
||||||
|
|
||||||
const selectMenuOptionData: APISelectMenuOption = {
|
const selectMenuOptionData: APISelectMenuOption = {
|
||||||
label: 'test',
|
label: 'test',
|
||||||
@@ -196,13 +199,13 @@ describe('Select Menu Components', () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
selectMenuOption()
|
selectMenuOption()
|
||||||
.setLabel(longStr)
|
.setLabel(selectMenuOptionLabelAboveLimit)
|
||||||
.setValue(longStr)
|
.setValue(selectMenuOptionValueAboveLimit)
|
||||||
// @ts-expect-error: Invalid default value
|
// @ts-expect-error: Invalid default value
|
||||||
.setDefault(-1)
|
.setDefault(-1)
|
||||||
// @ts-expect-error: Invalid emoji
|
// @ts-expect-error: Invalid emoji
|
||||||
.setEmoji({ name: 1 })
|
.setEmoji({ name: 1 })
|
||||||
.setDescription(longStr)
|
.setDescription(selectMenuOptionDescriptionAboveLimit)
|
||||||
.toJSON();
|
.toJSON();
|
||||||
}).toThrowError();
|
}).toThrowError();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { ButtonStyle, ChannelType, ComponentType, SelectMenuDefaultValueType } f
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { idPredicate, customIdPredicate, snowflakePredicate } from '../Assertions.js';
|
import { idPredicate, customIdPredicate, snowflakePredicate } from '../Assertions.js';
|
||||||
|
|
||||||
const labelPredicate = z.string().min(1).max(80);
|
|
||||||
|
|
||||||
export const emojiPredicate = z
|
export const emojiPredicate = z
|
||||||
.strictObject({
|
.strictObject({
|
||||||
id: snowflakePredicate.optional(),
|
id: snowflakePredicate.optional(),
|
||||||
@@ -19,23 +17,33 @@ const buttonPredicateBase = z.strictObject({
|
|||||||
disabled: z.boolean().optional(),
|
disabled: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonCustomIdPredicateBase = buttonPredicateBase.extend({
|
const buttonLabelPredicate = z.string().min(1).max(80);
|
||||||
|
|
||||||
|
const buttonCustomIdPredicateBase = buttonPredicateBase
|
||||||
|
.extend({
|
||||||
custom_id: customIdPredicate,
|
custom_id: customIdPredicate,
|
||||||
emoji: emojiPredicate.optional(),
|
emoji: emojiPredicate.optional(),
|
||||||
label: labelPredicate,
|
label: buttonLabelPredicate.optional(),
|
||||||
});
|
})
|
||||||
|
.refine((data) => data.emoji !== undefined || data.label !== undefined, {
|
||||||
|
message: 'Buttons with a custom id must have either an emoji or a label.',
|
||||||
|
});
|
||||||
|
|
||||||
const buttonPrimaryPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Primary) });
|
const buttonPrimaryPredicate = buttonCustomIdPredicateBase.safeExtend({ style: z.literal(ButtonStyle.Primary) });
|
||||||
const buttonSecondaryPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Secondary) });
|
const buttonSecondaryPredicate = buttonCustomIdPredicateBase.safeExtend({ style: z.literal(ButtonStyle.Secondary) });
|
||||||
const buttonSuccessPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Success) });
|
const buttonSuccessPredicate = buttonCustomIdPredicateBase.safeExtend({ style: z.literal(ButtonStyle.Success) });
|
||||||
const buttonDangerPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Danger) });
|
const buttonDangerPredicate = buttonCustomIdPredicateBase.safeExtend({ style: z.literal(ButtonStyle.Danger) });
|
||||||
|
|
||||||
const buttonLinkPredicate = buttonPredicateBase.extend({
|
const buttonLinkPredicate = buttonPredicateBase
|
||||||
|
.extend({
|
||||||
style: z.literal(ButtonStyle.Link),
|
style: z.literal(ButtonStyle.Link),
|
||||||
url: z.url({ protocol: /^(?:https?|discord)$/ }).max(512),
|
url: z.url({ protocol: /^(?:https?|discord)$/ }).max(512),
|
||||||
emoji: emojiPredicate.optional(),
|
emoji: emojiPredicate.optional(),
|
||||||
label: labelPredicate,
|
label: buttonLabelPredicate.optional(),
|
||||||
});
|
})
|
||||||
|
.refine((data) => data.emoji !== undefined || data.label !== undefined, {
|
||||||
|
message: 'Link buttons must have either an emoji or a label.',
|
||||||
|
});
|
||||||
|
|
||||||
const buttonPremiumPredicate = buttonPredicateBase.extend({
|
const buttonPremiumPredicate = buttonPredicateBase.extend({
|
||||||
style: z.literal(ButtonStyle.Premium),
|
style: z.literal(ButtonStyle.Premium),
|
||||||
@@ -92,7 +100,7 @@ export const selectMenuRolePredicate = selectMenuBasePredicate.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const selectMenuStringOptionPredicate = z.object({
|
export const selectMenuStringOptionPredicate = z.object({
|
||||||
label: labelPredicate,
|
label: z.string().min(1).max(100),
|
||||||
value: z.string().min(1).max(100),
|
value: z.string().min(1).max(100),
|
||||||
description: z.string().min(1).max(100).optional(),
|
description: z.string().min(1).max(100).optional(),
|
||||||
emoji: emojiPredicate.optional(),
|
emoji: emojiPredicate.optional(),
|
||||||
|
|||||||
Reference in New Issue
Block a user