mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-02 17:54:22 +10:00
fix(builder): preserve explicit HTTP URLs (#3403)
This commit is contained in:
@@ -56,6 +56,43 @@ describe("URLInput", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it.each(["http://other.example/path", "HTTP://other.example/path"])(
|
||||
"preserves an explicitly pasted HTTP URL: %s",
|
||||
(url) => {
|
||||
const onChange = vi.fn();
|
||||
renderInput({ url: "https://example.com", label: "Company" }, onChange);
|
||||
|
||||
fireEvent.change(screen.getByRole("textbox"), { target: { value: url } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({ url, label: "Company" });
|
||||
},
|
||||
);
|
||||
|
||||
it("shows an existing HTTP URL with its matching prefix", () => {
|
||||
renderInput({ url: "http://example.com/path", label: "" });
|
||||
|
||||
expect((screen.getByRole("textbox") as HTMLInputElement).value).toBe("example.com/path");
|
||||
expect(screen.getByText("http://")).toBeDefined();
|
||||
});
|
||||
|
||||
it("preserves HTTP while editing the host or path", () => {
|
||||
const onChange = vi.fn();
|
||||
renderInput({ url: "http://example.com/path", label: "Company" }, onChange);
|
||||
|
||||
fireEvent.change(screen.getByRole("textbox"), { target: { value: "example.com/new-path" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({ url: "http://example.com/new-path", label: "Company" });
|
||||
});
|
||||
|
||||
it("allows switching an existing HTTP URL to HTTPS by pasting", () => {
|
||||
const onChange = vi.fn();
|
||||
renderInput({ url: "http://example.com", label: "" }, onChange);
|
||||
|
||||
fireEvent.change(screen.getByRole("textbox"), { target: { value: "https://example.com" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({ url: "https://example.com", label: "" });
|
||||
});
|
||||
|
||||
it("emits an empty url string when cleared", () => {
|
||||
const onChange = vi.fn();
|
||||
renderInput({ url: "https://example.com", label: "" }, onChange);
|
||||
|
||||
@@ -15,15 +15,16 @@ import { Label } from "@reactive-resume/ui/components/label";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@reactive-resume/ui/components/popover";
|
||||
import { cn } from "@reactive-resume/utils/style";
|
||||
|
||||
const PREFIX = "https://";
|
||||
const DEFAULT_PREFIX = "https://";
|
||||
const HTTP_PREFIX = /^https?:\/\//i;
|
||||
|
||||
function stripPrefix(url: string) {
|
||||
return url.startsWith(PREFIX) ? url.slice(PREFIX.length) : url;
|
||||
return url.replace(HTTP_PREFIX, "");
|
||||
}
|
||||
|
||||
function ensurePrefix(url: string) {
|
||||
function ensurePrefix(url: string, prefix: string) {
|
||||
if (url === "") return "";
|
||||
return url.startsWith(PREFIX) ? url : PREFIX + url;
|
||||
return HTTP_PREFIX.test(url) ? url : prefix + url;
|
||||
}
|
||||
|
||||
type Props<TValue extends Website = Website> = Omit<React.ComponentProps<"input">, "value" | "onChange"> & {
|
||||
@@ -33,14 +34,15 @@ type Props<TValue extends Website = Website> = Omit<React.ComponentProps<"input"
|
||||
};
|
||||
|
||||
export function URLInput<TValue extends Website>({ value, onChange, hideLabelButton, ...props }: Props<TValue>) {
|
||||
const prefix = value.url.match(HTTP_PREFIX)?.[0] ?? DEFAULT_PREFIX;
|
||||
const handleUrlChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange({
|
||||
...value,
|
||||
url: ensurePrefix(e.target.value),
|
||||
url: ensurePrefix(e.target.value, prefix),
|
||||
});
|
||||
},
|
||||
[onChange, value],
|
||||
[onChange, value, prefix],
|
||||
);
|
||||
|
||||
const handleLabelChange = useCallback(
|
||||
@@ -55,7 +57,7 @@ export function URLInput<TValue extends Website>({ value, onChange, hideLabelBut
|
||||
return (
|
||||
<InputGroup>
|
||||
<InputGroupAddon align="inline-start">
|
||||
<InputGroupText>{PREFIX}</InputGroupText>
|
||||
<InputGroupText>{prefix}</InputGroupText>
|
||||
</InputGroupAddon>
|
||||
|
||||
<InputGroupInput
|
||||
|
||||
Reference in New Issue
Block a user