From a87ac2db18d0eaf2d1cd3f58d75ca1c65c55087b Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Fri, 10 Jul 2026 16:34:05 +0700 Subject: [PATCH] test(api-tokens): cover the token-name length cap Export tokenNameSchema and pin the 100-character boundary (100 accepted, 101 rejected) plus its trim/default behavior. Co-Authored-By: Claude Opus 4.8 --- .../settings/settings-api-tokens.test.tsx | 24 +++++++++++++++++++ .../pages/settings/settings-api-tokens.tsx | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 frontend/src/pages/settings/settings-api-tokens.test.tsx diff --git a/frontend/src/pages/settings/settings-api-tokens.test.tsx b/frontend/src/pages/settings/settings-api-tokens.test.tsx new file mode 100644 index 00000000..52cd9ded --- /dev/null +++ b/frontend/src/pages/settings/settings-api-tokens.test.tsx @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest'; + +import { tokenNameSchema } from './settings-api-tokens'; + +describe('tokenNameSchema', () => { + it('accepts a name at the 100-character boundary', () => { + expect(tokenNameSchema.safeParse('a'.repeat(100)).success).toBe(true); + }); + + it('rejects a name one character over the 100-character cap', () => { + expect(tokenNameSchema.safeParse('a'.repeat(101)).success).toBe(false); + }); + + it('trims surrounding whitespace before length-checking', () => { + expect(tokenNameSchema.safeParse(` ${'a'.repeat(100)} `)).toMatchObject({ + data: 'a'.repeat(100), + success: true, + }); + }); + + it('defaults an omitted name to an empty string', () => { + expect(tokenNameSchema.safeParse(undefined)).toMatchObject({ data: '', success: true }); + }); +}); diff --git a/frontend/src/pages/settings/settings-api-tokens.tsx b/frontend/src/pages/settings/settings-api-tokens.tsx index e9b0055f..b3e97242 100644 --- a/frontend/src/pages/settings/settings-api-tokens.tsx +++ b/frontend/src/pages/settings/settings-api-tokens.tsx @@ -63,7 +63,7 @@ import { baseUrl } from '@/models/api'; type APIToken = ApiTokenFragmentFragment; // 100 mirrors the backend cap (server/models/api_tokens.go + the createAPIToken/updateAPIToken resolvers). -const tokenNameSchema = z.string().trim().max(100, 'Token name must be 100 characters or less').default(''); +export const tokenNameSchema = z.string().trim().max(100, 'Token name must be 100 characters or less').default(''); const createTokenFormSchema = z.object({ // Nullable in form input (the date picker starts empty); the refine gates