Skip to content

Commit 2711ae2

Browse files
authored
🤖 fix: validate workspace name input in real-time (#1021)
Show validation error as user types in the workspace name field. Uses the existing validateWorkspaceName() function to check that names only contain lowercase letters, digits, underscore, and hyphen. _Generated with `mux`_
1 parent 9c3d0a1 commit 2711ae2

File tree

5 files changed

+16
-9
lines changed

5 files changed

+16
-9
lines changed

src/browser/hooks/useWorkspaceName.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState, useRef, useCallback, useEffect, useMemo } from "react";
22
import { useAPI } from "@/browser/contexts/API";
3+
import { validateWorkspaceName } from "@/common/utils/validation/workspaceValidation";
34

45
export interface UseWorkspaceNameOptions {
56
/** The user's message to generate a name for */
@@ -206,7 +207,13 @@ export function useWorkspaceName(options: UseWorkspaceNameOptions): UseWorkspace
206207

207208
const setName = useCallback((name: string) => {
208209
setManualName(name);
209-
setError(null);
210+
// Validate manual input and show errors in real-time
211+
if (name.trim()) {
212+
const validation = validateWorkspaceName(name);
213+
setError(validation.error ?? null);
214+
} else {
215+
setError(null);
216+
}
210217
}, []);
211218

212219
const waitForGeneration = useCallback(async (): Promise<string> => {

src/common/utils/validation/workspaceValidation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe("validateWorkspaceName", () => {
5757
test("rejects uppercase letters", () => {
5858
const result = validateWorkspaceName("MyBranch");
5959
expect(result.valid).toBe(false);
60-
expect(result.error).toContain("lowercase");
60+
expect(result.error).toContain("a-z");
6161
});
6262

6363
test("rejects spaces", () => {

src/common/utils/validation/workspaceValidation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function validateWorkspaceName(name: string): { valid: boolean; error?: s
1717
if (!validPattern.test(name)) {
1818
return {
1919
valid: false,
20-
error: "Workspace name can only contain lowercase letters, digits, underscore, and hyphen",
20+
error: "Use only: a-z, 0-9, _, -",
2121
};
2222
}
2323

tests/ipc/createWorkspace.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -798,9 +798,9 @@ exit 1
798798
try {
799799
const invalidCases = [
800800
{ name: "", expectedErrorFragment: "empty" },
801-
{ name: "My-Branch", expectedErrorFragment: "lowercase" },
802-
{ name: "branch name", expectedErrorFragment: "lowercase" },
803-
{ name: "branch@123", expectedErrorFragment: "lowercase" },
801+
{ name: "My-Branch", expectedErrorFragment: "a-z" },
802+
{ name: "branch name", expectedErrorFragment: "a-z" },
803+
{ name: "branch@123", expectedErrorFragment: "a-z" },
804804
{ name: "a".repeat(65), expectedErrorFragment: "64 characters" },
805805
];
806806

tests/ipc/forkWorkspace.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ describeIntegration("Workspace fork", () => {
4949
// Test various invalid names
5050
const invalidNames = [
5151
{ name: "", expectedError: "empty" },
52-
{ name: "Invalid-Name", expectedError: "lowercase" },
53-
{ name: "name with spaces", expectedError: "lowercase" },
54-
{ name: "name@special", expectedError: "lowercase" },
52+
{ name: "Invalid-Name", expectedError: "a-z" },
53+
{ name: "name with spaces", expectedError: "a-z" },
54+
{ name: "name@special", expectedError: "a-z" },
5555
{ name: "a".repeat(65), expectedError: "64 characters" },
5656
];
5757

0 commit comments

Comments
 (0)