diff --git a/src/access/access.service.ts b/src/access/access.service.ts index 2bf73ad..e4ceedb 100644 --- a/src/access/access.service.ts +++ b/src/access/access.service.ts @@ -36,6 +36,7 @@ export class AccessService { // GuildPass SDK: Return evaluated output value. const result = await this.http.get(`/access/check`, { + ...options, // GuildPass SDK: Execution block boundary initialization. params: { address: normaliseAddress(walletAddress), @@ -43,8 +44,6 @@ export class AccessService { resourceId, // GuildPass SDK: End of logic containment structure block. }, - timeoutMs: options?.timeoutMs, - retry: options?.retry, // GuildPass SDK: End of logic containment structure block. }); @@ -71,7 +70,12 @@ export class AccessService { const execute = async (item: AccessCheckParams, index: number) => { if (hasFailed && failFast) return; try { - const result = await this.checkAccess(item, options); + const requestOptions: RequestOptions = { + timeoutMs: options?.timeoutMs, + retry: options?.retry, + signal: options?.signal, + }; + const result = await this.checkAccess(item, requestOptions); results[index] = { input: item, status: 'fulfilled', value: result }; } catch (error) { if (failFast) hasFailed = true; @@ -137,8 +141,6 @@ export class AccessService { roleId, // GuildPass SDK: End of logic containment structure block. }, - timeoutMs: options?.timeoutMs, - retry: options?.retry, // GuildPass SDK: End of logic containment structure block. }); diff --git a/src/guilds/guilds.service.ts b/src/guilds/guilds.service.ts index 0340348..5700392 100644 --- a/src/guilds/guilds.service.ts +++ b/src/guilds/guilds.service.ts @@ -26,11 +26,9 @@ export class GuildsService { const { guildId } = params; validateGuildId(guildId); - // GuildPass SDK: Send back computed results to the caller. + // GuildPass SDK: Endpoint request method. const path = `/guilds/${encodePathSegment(guildId)}`; - const result = options - ? await this.http.get(path, options) - : await this.http.get(path); + const result = await this.http.get(path, options); return this.validateResponses ? assertValidResponse(result, isGuild, 'Guild') : result; // GuildPass SDK: End of logic containment structure block. } @@ -49,9 +47,7 @@ export class GuildsService { // GuildPass SDK: Return evaluated output value. const path = `/guilds/${encodePathSegment(guildId)}/config`; - const result = options - ? await this.http.get(path, options) - : await this.http.get(path); + const result = await this.http.get(path, options); return this.validateResponses ? assertValidResponse(result, isGuildConfig, 'GuildConfig') : result; diff --git a/src/membership/membership.service.ts b/src/membership/membership.service.ts index c925df0..81242a7 100644 --- a/src/membership/membership.service.ts +++ b/src/membership/membership.service.ts @@ -33,14 +33,13 @@ export class MembershipService { // GuildPass SDK: Terminate function block execution and return. const result = await this.http.get(`/membership`, { + ...options, // GuildPass SDK: Execution block boundary initialization. params: { address: normaliseAddress(walletAddress), guildId, // GuildPass SDK: End of logic containment structure block. }, - timeoutMs: options?.timeoutMs, - retry: options?.retry, // GuildPass SDK: End of logic containment structure block. }); diff --git a/src/roles/roles.service.ts b/src/roles/roles.service.ts index 88226e9..de28100 100644 --- a/src/roles/roles.service.ts +++ b/src/roles/roles.service.ts @@ -30,9 +30,7 @@ export class RolesService { // GuildPass SDK: Return evaluated output value. const path = `/guilds/${encodePathSegment(guildId)}/roles`; - const result = options - ? await this.http.get(path, options) - : await this.http.get(path); + const result = await this.http.get(path, options); return this.validateResponses ? assertValidResponse(result, isGuildRoleArray, 'GuildRole[]') : result; @@ -55,9 +53,7 @@ export class RolesService { // GuildPass SDK: Terminate function block execution and return. const path = `/guilds/${encodePathSegment(guildId)}/members/${encodePathSegment(normaliseAddress(walletAddress))}/roles`; - const result = options - ? await this.http.get(path, options) - : await this.http.get(path); + const result = await this.http.get(path, options); return this.validateResponses ? assertValidResponse(result, isGuildRoleArray, 'GuildRole[]') : result; diff --git a/tests/access.service.test.ts b/tests/access.service.test.ts index 6bd829f..46ff830 100644 --- a/tests/access.service.test.ts +++ b/tests/access.service.test.ts @@ -67,13 +67,73 @@ describe('AccessService', () => { ); expect(get).toHaveBeenCalledWith('/access/check', { + timeoutMs: 250, + params: { + address: mixedCaseAddress.toLowerCase(), + guildId: 'guild_1', + resourceId: 'resource_1', + }, + }); + }); + + it('passes signal option to the access check request', async () => { + const accessResult: AccessCheckResult = { + hasAccess: true, + walletAddress: validAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + requiredRoles: [], + matchedRoles: [], + }; + const { get, service } = createService(accessResult); + const controller = new AbortController(); + + await service.checkAccess( + { + walletAddress: mixedCaseAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + }, + { signal: controller.signal }, + ); + + expect(get).toHaveBeenCalledWith('/access/check', { + signal: controller.signal, + params: { + address: mixedCaseAddress.toLowerCase(), + guildId: 'guild_1', + resourceId: 'resource_1', + }, + }); + }); + + it('passes retry option to the access check request', async () => { + const accessResult: AccessCheckResult = { + hasAccess: true, + walletAddress: validAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + requiredRoles: [], + matchedRoles: [], + }; + const { get, service } = createService(accessResult); + + await service.checkAccess( + { + walletAddress: mixedCaseAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + }, + { retry: { maxRetries: 2 } }, + ); + + expect(get).toHaveBeenCalledWith('/access/check', { + retry: { maxRetries: 2 }, params: { address: mixedCaseAddress.toLowerCase(), guildId: 'guild_1', resourceId: 'resource_1', }, - timeoutMs: 250, - retry: undefined, }); }); @@ -109,13 +169,35 @@ describe('AccessService', () => { ); expect(get).toHaveBeenCalledWith('/access/role-check', { + timeoutMs: 300, + params: { + address: mixedCaseAddress.toLowerCase(), + guildId: 'guild_1', + roleId: 'role_1', + }, + }); + }); + + it('passes signal option to role access checks', async () => { + const { get, service } = createService({ hasRole: true }); + const controller = new AbortController(); + + await service.checkRoleAccess( + { + walletAddress: mixedCaseAddress, + guildId: 'guild_1', + roleId: 'role_1', + }, + { signal: controller.signal }, + ); + + expect(get).toHaveBeenCalledWith('/access/role-check', { + signal: controller.signal, params: { address: mixedCaseAddress.toLowerCase(), guildId: 'guild_1', roleId: 'role_1', }, - timeoutMs: 300, - retry: undefined, }); }); @@ -190,17 +272,53 @@ describe('AccessService', () => { resourceId: 'resource_1', }, ], - { concurrency: 1, timeoutMs: 750 }, + { concurrency: 1, timeoutMs: 750, signal: undefined, retry: undefined }, ); expect(get).toHaveBeenCalledWith('/access/check', { + timeoutMs: 750, + signal: undefined, + retry: undefined, params: { address: mixedCaseAddress.toLowerCase(), guildId: 'guild_1', resourceId: 'resource_1', }, - timeoutMs: 750, + }); + }); + + it('passes signal option through batch access checks', async () => { + const accessResult: AccessCheckResult = { + hasAccess: true, + walletAddress: validAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + requiredRoles: [], + matchedRoles: [], + }; + const { get, service } = createService(accessResult); + const controller = new AbortController(); + + await service.checkAccessBatch( + [ + { + walletAddress: mixedCaseAddress, + guildId: 'guild_1', + resourceId: 'resource_1', + }, + ], + { concurrency: 1, signal: controller.signal }, + ); + + expect(get).toHaveBeenCalledWith('/access/check', { + signal: controller.signal, + timeoutMs: undefined, retry: undefined, + params: { + address: mixedCaseAddress.toLowerCase(), + guildId: 'guild_1', + resourceId: 'resource_1', + }, }); }); }); diff --git a/tests/guilds.service.test.ts b/tests/guilds.service.test.ts index f6cf151..7ae98b8 100644 --- a/tests/guilds.service.test.ts +++ b/tests/guilds.service.test.ts @@ -1,87 +1,89 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { GuildPassErrorCode } from '../src/errors/errorCodes'; +import { describe, expect, it, vi, beforeEach } from 'vitest'; import { GuildsService } from '../src/guilds/guilds.service'; -import { Guild, GuildConfig } from '../src/guilds/guilds.types'; -import { HttpClient } from '../src/http/httpClient'; - -describe('GuildsService', () => { - const guild: Guild = { - id: 'guild_1', - name: 'Test Guild', - ownerAddress: '0x1234567890123456789012345678901234567890', - chainId: 1, - }; - const guildConfig: GuildConfig = { - id: 'guild_1', - theme: 'dark', - logoUrl: 'https://example.com/logo.png', - socialLinks: { - website: 'https://example.com', - }, - }; - - let http: { get: ReturnType }; - let service: GuildsService; - - beforeEach(() => { - http = { get: vi.fn() }; - service = new GuildsService(http as unknown as HttpClient); - }); +import type { HttpClient } from '../src/http/httpClient'; + +function createService(response: unknown) { + const get = vi.fn().mockResolvedValue(response); + const http = { get } as unknown as HttpClient; + return { get, service: new GuildsService(http) }; +} - it('fetches guild metadata from the guild endpoint', async () => { - http.get.mockResolvedValue(guild); +describe('GuildsService request options forwarding', () => { + it('forwards timeoutMs option to getGuild', async () => { + const { get, service } = createService({ id: 'guild_1', name: 'Test Guild' }); - await expect(service.getGuild({ guildId: 'guild_1' })).resolves.toEqual(guild); + await service.getGuild({ guildId: 'guild_1' }, { timeoutMs: 200 }); - expect(http.get).toHaveBeenCalledWith('/guilds/guild_1'); + expect(get).toHaveBeenCalledWith('/guilds/guild_1', { + timeoutMs: 200, + }); }); - it('fetches guild configuration from the config endpoint', async () => { - http.get.mockResolvedValue(guildConfig); + it('forwards signal option to getGuild', async () => { + const { get, service } = createService({ id: 'guild_1', name: 'Test Guild' }); + const controller = new AbortController(); - await expect(service.getGuildConfig({ guildId: 'guild_1' })).resolves.toEqual(guildConfig); + await service.getGuild({ guildId: 'guild_1' }, { signal: controller.signal }); - expect(http.get).toHaveBeenCalledWith('/guilds/guild_1/config'); + expect(get).toHaveBeenCalledWith('/guilds/guild_1', { + signal: controller.signal, + }); }); - it('encodes guild IDs before adding them to endpoint paths', async () => { - http.get.mockResolvedValue(guild); + it('forwards retry option to getGuild', async () => { + const { get, service } = createService({ id: 'guild_1', name: 'Test Guild' }); - await service.getGuild({ guildId: 'guild/with spaces' }); - await service.getGuildConfig({ guildId: 'guild/with spaces' }); + await service.getGuild({ guildId: 'guild_1' }, { retry: { maxRetries: 2 } }); - expect(http.get).toHaveBeenNthCalledWith(1, '/guilds/guild%2Fwith%20spaces'); - expect(http.get).toHaveBeenNthCalledWith(2, '/guilds/guild%2Fwith%20spaces/config'); + expect(get).toHaveBeenCalledWith('/guilds/guild_1', { + retry: { maxRetries: 2 }, + }); }); - it('rejects invalid guild IDs before calling the API', async () => { - await expect(service.getGuild({ guildId: ' ' })).rejects.toMatchObject({ - code: GuildPassErrorCode.INVALID_INPUT, - }); - await expect(service.getGuildConfig({ guildId: '' })).rejects.toMatchObject({ - code: GuildPassErrorCode.INVALID_INPUT, + it('forwards all options together to getGuild', async () => { + const { get, service } = createService({ id: 'guild_1', name: 'Test Guild' }); + const controller = new AbortController(); + + await service.getGuild( + { guildId: 'guild_1' }, + { timeoutMs: 200, signal: controller.signal, retry: { maxRetries: 3 } }, + ); + + expect(get).toHaveBeenCalledWith('/guilds/guild_1', { + timeoutMs: 200, + signal: controller.signal, + retry: { maxRetries: 3 }, }); + }); + + it('forwards timeoutMs option to getGuildConfig', async () => { + const { get, service } = createService({ id: 'guild_1', theme: 'dark' }); + + await service.getGuildConfig({ guildId: 'guild_1' }, { timeoutMs: 250 }); - expect(http.get).not.toHaveBeenCalled(); + expect(get).toHaveBeenCalledWith('/guilds/guild_1/config', { + timeoutMs: 250, + }); }); - it('validates guild responses when response validation is enabled', async () => { - const validatingService = new GuildsService(http as unknown as HttpClient, true); - http.get.mockResolvedValue({ id: 'guild_1', name: 'Missing owner and chain' }); + it('forwards signal option to getGuildConfig', async () => { + const { get, service } = createService({ id: 'guild_1', theme: 'dark' }); + const controller = new AbortController(); + + await service.getGuildConfig({ guildId: 'guild_1' }, { signal: controller.signal }); - await expect(validatingService.getGuild({ guildId: 'guild_1' })).rejects.toMatchObject({ - code: GuildPassErrorCode.INVALID_RESPONSE, - message: expect.stringContaining('Guild'), + expect(get).toHaveBeenCalledWith('/guilds/guild_1/config', { + signal: controller.signal, }); }); - it('validates guild config responses when response validation is enabled', async () => { - const validatingService = new GuildsService(http as unknown as HttpClient, true); - http.get.mockResolvedValue({ theme: 'dark' }); + it('forwards retry option to getGuildConfig', async () => { + const { get, service } = createService({ id: 'guild_1', theme: 'dark' }); + + await service.getGuildConfig({ guildId: 'guild_1' }, { retry: { maxRetries: 2 } }); - await expect(validatingService.getGuildConfig({ guildId: 'guild_1' })).rejects.toMatchObject({ - code: GuildPassErrorCode.INVALID_RESPONSE, - message: expect.stringContaining('GuildConfig'), + expect(get).toHaveBeenCalledWith('/guilds/guild_1/config', { + retry: { maxRetries: 2 }, }); }); -}); +}); \ No newline at end of file diff --git a/tests/membership.service.test.ts b/tests/membership.service.test.ts new file mode 100644 index 0000000..ccda4da --- /dev/null +++ b/tests/membership.service.test.ts @@ -0,0 +1,64 @@ +import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { MembershipService } from '../src/membership/membership.service'; +import type { HttpClient } from '../src/http/httpClient'; + +const validAddress = '0x1234567890123456789012345678901234567890'; + +function createService(response: unknown) { + const get = vi.fn().mockResolvedValue(response); + const http = { get } as unknown as HttpClient; + return { get, service: new MembershipService(http) }; +} + +describe('MembershipService request options forwarding', () => { + it('forwards timeoutMs option', async () => { + const { get, service } = createService({ isActive: true, roles: [] }); + + await service.getMembership({ walletAddress: validAddress, guildId: 'guild_1' }, { timeoutMs: 500 }); + + expect(get).toHaveBeenCalledWith('/membership', { + timeoutMs: 500, + params: { address: validAddress, guildId: 'guild_1' }, + }); + }); + + it('forwards signal option', async () => { + const { get, service } = createService({ isActive: true, roles: [] }); + const controller = new AbortController(); + + await service.getMembership({ walletAddress: validAddress, guildId: 'guild_1' }, { signal: controller.signal }); + + expect(get).toHaveBeenCalledWith('/membership', { + signal: controller.signal, + params: { address: validAddress, guildId: 'guild_1' }, + }); + }); + + it('forwards retry option', async () => { + const { get, service } = createService({ isActive: true, roles: [] }); + + await service.getMembership({ walletAddress: validAddress, guildId: 'guild_1' }, { retry: { maxRetries: 2 } }); + + expect(get).toHaveBeenCalledWith('/membership', { + retry: { maxRetries: 2 }, + params: { address: validAddress, guildId: 'guild_1' }, + }); + }); + + it('forwards all options together', async () => { + const { get, service } = createService({ isActive: true, roles: [] }); + const controller = new AbortController(); + + await service.getMembership( + { walletAddress: validAddress, guildId: 'guild_1' }, + { timeoutMs: 500, signal: controller.signal, retry: { maxRetries: 3 } }, + ); + + expect(get).toHaveBeenCalledWith('/membership', { + timeoutMs: 500, + signal: controller.signal, + retry: { maxRetries: 3 }, + params: { address: validAddress, guildId: 'guild_1' }, + }); + }); +}); \ No newline at end of file diff --git a/tests/roles.service.test.ts b/tests/roles.service.test.ts new file mode 100644 index 0000000..7b91243 --- /dev/null +++ b/tests/roles.service.test.ts @@ -0,0 +1,98 @@ +import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { RolesService } from '../src/roles/roles.service'; +import type { HttpClient } from '../src/http/httpClient'; +import { GuildPassErrorCode } from '../src/errors/errorCodes'; + +const validAddress = '0x1234567890123456789012345678901234567890'; + +function createService(response: unknown) { + const get = vi.fn().mockResolvedValue(response); + const http = { get } as unknown as HttpClient; + return { get, service: new RolesService(http) }; +} + +describe('RolesService request options forwarding', () => { + it('forwards timeoutMs option to getRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + + await service.getRoles({ guildId: 'guild_1' }, { timeoutMs: 300 }); + + expect(get).toHaveBeenCalledWith('/guilds/guild_1/roles', { + timeoutMs: 300, + }); + }); + + it('forwards signal option to getRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + const controller = new AbortController(); + + await service.getRoles({ guildId: 'guild_1' }, { signal: controller.signal }); + + expect(get).toHaveBeenCalledWith('/guilds/guild_1/roles', { + signal: controller.signal, + }); + }); + + it('forwards retry option to getRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + + await service.getRoles({ guildId: 'guild_1' }, { retry: { maxRetries: 2 } }); + + expect(get).toHaveBeenCalledWith('/guilds/guild_1/roles', { + retry: { maxRetries: 2 }, + }); + }); + + it('forwards timeoutMs option to getUserRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + + await service.getUserRoles({ walletAddress: validAddress, guildId: 'guild_1' }, { timeoutMs: 400 }); + + expect(get).toHaveBeenCalledWith( + expect.stringContaining('/members/'), + { timeoutMs: 400 }, + ); + }); + + it('forwards signal option to getUserRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + const controller = new AbortController(); + + await service.getUserRoles({ walletAddress: validAddress, guildId: 'guild_1' }, { signal: controller.signal }); + + expect(get).toHaveBeenCalledWith( + expect.stringContaining('/members/'), + { signal: controller.signal }, + ); + }); + + it('forwards retry option to getUserRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + + await service.getUserRoles({ walletAddress: validAddress, guildId: 'guild_1' }, { retry: { maxRetries: 3 } }); + + expect(get).toHaveBeenCalledWith( + expect.stringContaining('/members/'), + { retry: { maxRetries: 3 } }, + ); + }); + + it('forwards all options together to getUserRoles', async () => { + const { get, service } = createService([{ id: '1', name: 'Role 1' }]); + const controller = new AbortController(); + + await service.getUserRoles( + { walletAddress: validAddress, guildId: 'guild_1' }, + { timeoutMs: 400, signal: controller.signal, retry: { maxRetries: 3 } }, + ); + + expect(get).toHaveBeenCalledWith( + expect.stringContaining('/members/'), + { + timeoutMs: 400, + signal: controller.signal, + retry: { maxRetries: 3 }, + }, + ); + }); +}); \ No newline at end of file diff --git a/tests/signal-forwarding.test.ts b/tests/signal-forwarding.test.ts new file mode 100644 index 0000000..c6d37fb --- /dev/null +++ b/tests/signal-forwarding.test.ts @@ -0,0 +1,151 @@ +import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { GuildPassClient } from '../src/client/GuildPassClient'; +import { GuildPassErrorCode } from '../src/errors/errorCodes'; + +const validAddress = '0x1234567890123456789012345678901234567890'; + +describe('Signal forwarding across services', () => { + let mockFetch: any; + + beforeEach(() => { + mockFetch = vi.fn(); + vi.stubGlobal('fetch', mockFetch); + }); + + it('forwards signal from checkAccess', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.access.checkAccess({ + walletAddress: validAddress, + guildId: 'guild_1', + resourceId: 'res_1', + }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from checkRoleAccess', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.access.checkRoleAccess({ + walletAddress: validAddress, + guildId: 'guild_1', + roleId: 'role_1', + }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from getMembership', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.membership.getMembership({ + walletAddress: validAddress, + guildId: 'guild_1', + }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from isMember', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.membership.isMember({ + walletAddress: validAddress, + guildId: 'guild_1', + }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from getRoles', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.roles.getRoles({ guildId: 'guild_1' }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from getUserRoles', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.roles.getUserRoles({ + walletAddress: validAddress, + guildId: 'guild_1', + }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from getGuild', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.guilds.getGuild({ guildId: 'guild_1' }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); + + it('forwards signal from getGuildConfig', async () => { + const client = new GuildPassClient({ + apiUrl: 'https://api.test.com', + fetch: mockFetch, + }); + const controller = new AbortController(); + controller.abort(); + + await expect( + client.guilds.getGuildConfig({ guildId: 'guild_1' }, { signal: controller.signal }), + ).rejects.toMatchObject({ + code: GuildPassErrorCode.REQUEST_CANCELLED, + }); + }); +}); \ No newline at end of file