diff --git a/packages/builders/__tests__/components/selectMenu.test.ts b/packages/builders/__tests__/components/selectMenu.test.ts index f7ab28144..6e0c887dc 100644 --- a/packages/builders/__tests__/components/selectMenu.test.ts +++ b/packages/builders/__tests__/components/selectMenu.test.ts @@ -29,6 +29,20 @@ const selectMenuData: APISelectMenuComponent = { options: [selectMenuOptionData], }; +function makeStringSelectMenuWithOptions() { + const selectMenu = new StringSelectMenuBuilder(); + selectMenu.addOptions( + { label: 'foo', value: 'bar' }, + { label: 'foo2', value: 'bar2' }, + { label: 'foo3', value: 'bar3' }, + ); + return selectMenu; +} + +function mapStringSelectMenuOptionBuildersToJson(selectMenu: StringSelectMenuBuilder) { + return selectMenu.options.map((option) => option.toJSON()); +} + describe('Select Menu Components', () => { describe('Assertion Tests', () => { test('GIVEN valid inputs THEN Select Menu does not throw', () => { @@ -176,5 +190,40 @@ describe('Select Menu Components', () => { ).toEqual(selectMenuData); expect(new StringSelectMenuOptionBuilder(selectMenuOptionData).toJSON()).toEqual(selectMenuOptionData); }); + + test('GIVEN a StringSelectMenuBuilder using StringSelectMenuBuilder#spliceOptions works', () => { + expect( + mapStringSelectMenuOptionBuildersToJson(makeStringSelectMenuWithOptions().spliceOptions(0, 1)), + ).toStrictEqual([ + { label: 'foo2', value: 'bar2' }, + { label: 'foo3', value: 'bar3' }, + ]); + + expect( + mapStringSelectMenuOptionBuildersToJson( + makeStringSelectMenuWithOptions().spliceOptions(0, 1, selectMenuOptionData), + ), + ).toStrictEqual([selectMenuOptionData, { label: 'foo2', value: 'bar2' }, { label: 'foo3', value: 'bar3' }]); + + expect( + mapStringSelectMenuOptionBuildersToJson( + makeStringSelectMenuWithOptions().spliceOptions(0, 3, selectMenuOptionData), + ), + ).toStrictEqual([selectMenuOptionData]); + + expect(() => + makeStringSelectMenuWithOptions().spliceOptions( + 0, + 0, + ...Array.from({ length: 26 }, () => selectMenuOptionData), + ), + ).toThrowError(); + + expect(() => + makeStringSelectMenuWithOptions() + .setOptions(Array.from({ length: 25 }, () => selectMenuOptionData)) + .spliceOptions(-1, 2, selectMenuOptionData, selectMenuOptionData), + ).toThrowError(); + }); }); }); diff --git a/packages/builders/src/components/selectMenu/StringSelectMenu.ts b/packages/builders/src/components/selectMenu/StringSelectMenu.ts index ed5f928c1..d202e13d7 100644 --- a/packages/builders/src/components/selectMenu/StringSelectMenu.ts +++ b/packages/builders/src/components/selectMenu/StringSelectMenu.ts @@ -77,18 +77,61 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder) { + return this.spliceOptions(0, this.options.length, ...options); + } + + /** + * Removes, replaces, or inserts options in the string select menu. + * + * @remarks + * This method behaves similarly + * to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice}. + * + * It's useful for modifying and adjusting order of the already-existing options of a string select menu. + * @example + * Remove the first option + * ```ts + * selectMenu.spliceOptions(0, 1); + * ``` + * @example + * Remove the first n option + * ```ts + * const n = 4 + * selectMenu.spliceOptions(0, n); + * ``` + * @example + * Remove the last option + * ```ts + * selectMenu.spliceOptions(-1, 1); + * ``` + * @param index - The index to start at + * @param deleteCount - The number of options to remove + * @param options - The replacing option objects or builders + */ + public spliceOptions( + index: number, + deleteCount: number, + ...options: RestOrArray + ) { // eslint-disable-next-line no-param-reassign options = normalizeArray(options); - optionsLengthValidator.parse(options.length); - this.options.splice( - 0, - this.options.length, + + const clone = [...this.options]; + + clone.splice( + index, + deleteCount, ...options.map((option) => option instanceof StringSelectMenuOptionBuilder ? option : new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(option)), ), ); + + optionsLengthValidator.parse(clone.length); + + this.options.splice(0, this.options.length, ...clone); + return this; }