fix: restored https toggle functionality. added tests
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { describe, it, vi, expect } from "vitest";
|
||||
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
||||
import { HTTP } from "@components/PageComponents/Connect/HTTP.tsx";
|
||||
import { TransportHTTP } from "@meshtastic/transport-http";
|
||||
import { MeshDevice } from "@meshtastic/core";
|
||||
|
||||
vi.mock("@core/stores/appStore.ts", () => ({
|
||||
useAppStore: vi.fn(() => ({ setSelectedDevice: vi.fn() })),
|
||||
}));
|
||||
|
||||
vi.mock("@core/stores/deviceStore.ts", () => ({
|
||||
useDeviceStore: vi.fn(() => ({ addDevice: vi.fn(() => ({ addConnection: vi.fn() })) })),
|
||||
}));
|
||||
|
||||
vi.mock("@core/utils/randId.ts", () => ({
|
||||
randId: vi.fn(() => "mock-id"),
|
||||
}));
|
||||
|
||||
vi.mock("@meshtastic/transport-http", () => ({
|
||||
TransportHTTP: {
|
||||
create: vi.fn(() => Promise.resolve({})),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@meshtastic/core", () => ({
|
||||
MeshDevice: vi.fn(() => ({
|
||||
configure: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
|
||||
describe("HTTP Component", () => {
|
||||
it("renders correctly", () => {
|
||||
render(<HTTP closeDialog={vi.fn()} />);
|
||||
expect(screen.getByText("IP Address/Hostname")).toBeInTheDocument();
|
||||
expect(screen.getByRole("textbox")).toBeInTheDocument();
|
||||
expect(screen.getByPlaceholderText("000.000.000.000 / meshtastic.local")).toBeInTheDocument();
|
||||
expect(screen.getByText("Use HTTPS")).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Connect" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("allows input field to be updated", () => {
|
||||
render(<HTTP closeDialog={vi.fn()} />);
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "meshtastic.local" } });
|
||||
expect(input).toHaveValue("meshtastic.local");
|
||||
});
|
||||
|
||||
it("toggles HTTPS switch and updates prefix", () => {
|
||||
render(<HTTP closeDialog={vi.fn()} />);
|
||||
const switchInput = screen.getByRole("switch");
|
||||
expect(screen.getByText("http://")).toBeInTheDocument();
|
||||
fireEvent.click(switchInput);
|
||||
expect(screen.getByText("https://")).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(switchInput);
|
||||
expect(switchInput).not.toBeChecked();
|
||||
expect(screen.getByText("http://")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.skip("submits form and triggers connection process", () => {
|
||||
// This will need further work to test, as it involves a lot of other plumbing mocking
|
||||
const closeDialog = vi.fn();
|
||||
render(<HTTP closeDialog={closeDialog} />);
|
||||
|
||||
const button = screen.getByRole("button", { name: "Connect" });
|
||||
expect(button).not.toBeDisabled();
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
waitFor(() => {
|
||||
expect(button).toBeDisabled();
|
||||
expect(closeDialog).toHaveBeenCalled();
|
||||
expect(TransportHTTP.create).toHaveBeenCalled();
|
||||
expect(MeshDevice).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,37 +10,43 @@ import { randId } from "@core/utils/randId.ts";
|
||||
import { MeshDevice } from "@meshtastic/core";
|
||||
import { TransportHTTP } from "@meshtastic/transport-http";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useForm, useController } from "react-hook-form";
|
||||
import { FieldWrapper } from "@components/Form/FormWrapper.tsx";
|
||||
|
||||
interface FormData {
|
||||
ip: string;
|
||||
tls: boolean;
|
||||
}
|
||||
|
||||
export const HTTP = ({ closeDialog }: TabElementProps) => {
|
||||
const [https, setHTTPS] = useState(false);
|
||||
const { addDevice } = useDeviceStore();
|
||||
const { setSelectedDevice } = useAppStore();
|
||||
const { register, handleSubmit, control } = useForm<{
|
||||
ip: string;
|
||||
tls: boolean;
|
||||
}>({
|
||||
const { control, handleSubmit, register } = useForm<FormData>({
|
||||
defaultValues: {
|
||||
ip: ["client.meshtastic.org", "localhost"].includes(
|
||||
globalThis.location.hostname,
|
||||
)
|
||||
? "meshtastic.local"
|
||||
: globalThis.location.host,
|
||||
tls: location.protocol === "https:",
|
||||
tls: false,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
field: { value: tlsValue, onChange: setTLS },
|
||||
} = useController({ name: "tls", control });
|
||||
|
||||
const [connectionInProgress, setConnectionInProgress] = useState(false);
|
||||
|
||||
const onSubmit = handleSubmit(async (data) => {
|
||||
setConnectionInProgress(true);
|
||||
console.log(data);
|
||||
|
||||
setConnectionInProgress(true);
|
||||
const id = randId();
|
||||
const device = addDevice(id);
|
||||
const transport = await TransportHTTP.create(data.ip, data.tls);
|
||||
const connection = new MeshDevice(transport, id);
|
||||
connection.configure();
|
||||
|
||||
setSelectedDevice(id);
|
||||
device.addConnection(connection);
|
||||
subscribeAll(device, connection);
|
||||
@@ -50,32 +56,26 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
||||
return (
|
||||
<form className="flex w-full flex-col gap-2 p-4" onSubmit={onSubmit}>
|
||||
<div className="flex h-48 flex-col gap-2">
|
||||
<Label>IP Address/Hostname</Label>
|
||||
<Input
|
||||
prefix={https ? "https://" : "http://"}
|
||||
placeholder="000.000.000.000 / meshtastic.local"
|
||||
className="text-slate-900 dark:text-slate-900"
|
||||
disabled={connectionInProgress}
|
||||
{...register("ip")}
|
||||
/>
|
||||
<Controller
|
||||
name="tls"
|
||||
control={control}
|
||||
render={({ field: { ...rest } }) => (
|
||||
<>
|
||||
<Label>Use HTTPS</Label>
|
||||
<Switch
|
||||
onCheckedChange={(checked: boolean) => {
|
||||
checked ? setHTTPS(true) : setHTTPS(false);
|
||||
}}
|
||||
disabled={location.protocol === "https:" ||
|
||||
connectionInProgress}
|
||||
checked={https}
|
||||
{...rest}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<Label>IP Address/Hostname</Label>
|
||||
<Input
|
||||
prefix={tlsValue ? "https://" : "http://"}
|
||||
placeholder="000.000.000.000 / meshtastic.local"
|
||||
className="text-slate-900 dark:text-slate-900"
|
||||
disabled={connectionInProgress}
|
||||
{...register("ip")}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Switch
|
||||
onCheckedChange={setTLS}
|
||||
disabled={location.protocol === "https:" || connectionInProgress}
|
||||
checked={tlsValue}
|
||||
{...register("tls")}
|
||||
/>
|
||||
<Label>Use HTTPS</Label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="submit"
|
||||
@@ -86,4 +86,4 @@ export const HTTP = ({ closeDialog }: TabElementProps) => {
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
};
|
||||
@@ -21,8 +21,8 @@ const inputVariants = cva(
|
||||
|
||||
export interface InputProps
|
||||
extends
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
VariantProps<typeof inputVariants> {
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
VariantProps<typeof inputVariants> {
|
||||
prefix?: string;
|
||||
suffix?: string;
|
||||
action?: {
|
||||
@@ -36,9 +36,9 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
{prefix && (
|
||||
<span className="inline-flex items-center rounded-l-md bg-slate-100/80 px-3 font-mono text-sm text-slate-600">
|
||||
<label className="inline-flex items-center rounded-l-md bg-slate-100/80 px-3 font-mono text-sm text-slate-600">
|
||||
{prefix}
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
className={cn(
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
globalThis.ResizeObserver = class {
|
||||
observe() { }
|
||||
unobserve() { }
|
||||
disconnect() { }
|
||||
};
|
||||
Reference in New Issue
Block a user