Browse Source

fixing broken tests

pull/627/head
Dan Ditomaso 1 year ago
parent
commit
f6748d558a
  1. 5
      src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx
  2. 9
      src/components/Dialog/RebootOTADialog.test.tsx
  3. 2
      src/components/Dialog/RebootOTADialog.tsx
  4. 2
      src/components/LanguageSwitcher.tsx
  5. 235
      src/components/PageComponents/Config/Bluetooth.tsx
  6. 1
      src/components/PageComponents/Messages/TraceRoute.test.tsx
  7. 4
      src/components/PageComponents/Messages/TraceRoute.tsx
  8. 4
      src/i18n/locales/en/common.json
  9. 1
      src/pages/Dashboard/index.tsx
  10. 53
      src/tests/setupTests.ts

5
src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx

@ -62,8 +62,7 @@ export const NodeDetailsDialog = ({
onOpenChange, onOpenChange,
}: NodeDetailsDialogProps) => { }: NodeDetailsDialogProps) => {
const { t } = useTranslation("dialog"); const { t } = useTranslation("dialog");
const { setDialogOpen, connection, setActivePage, getNodeError } = const { setDialogOpen, connection, setActivePage } = useDevice();
useDevice();
const { setNodeNumToBeRemoved } = useAppStore(); const { setNodeNumToBeRemoved } = useAppStore();
const { setChatType, setActiveChat } = useMessageStore(); const { setChatType, setActiveChat } = useMessageStore();
@ -320,7 +319,7 @@ export const NodeDetailsDialog = ({
<p> <p>
{t("locationResponse.altitude")} {t("locationResponse.altitude")}
{node.position.altitude} {node.position.altitude}
{t("unit.meter")} {t("unit.meter.one")}
</p> </p>
)} )}
</> </>

9
src/components/Dialog/RebootOTADialog.test.tsx

@ -60,7 +60,8 @@ describe("RebootOTADialog", () => {
it("renders dialog with default input value", () => { it("renders dialog with default input value", () => {
render(<RebootOTADialog open onOpenChange={() => {}} />); render(<RebootOTADialog open onOpenChange={() => {}} />);
expect(screen.getByPlaceholderText(/enter delay/i)).toHaveValue(5); expect(screen.getByPlaceholderText(/enter delay/i)).toHaveValue(5);
expect(screen.getByText(/schedule reboot/i)).toBeInTheDocument(); expect(screen.getByRole("heading", { name: /schedule reboot/i, level: 1 }))
.toBeInTheDocument();
expect(screen.getByText(/reboot to ota mode now/i)).toBeInTheDocument(); expect(screen.getByText(/reboot to ota mode now/i)).toBeInTheDocument();
}); });
@ -72,7 +73,7 @@ describe("RebootOTADialog", () => {
target: { value: "3" }, target: { value: "3" },
}); });
fireEvent.click(screen.getByText(/schedule reboot/i)); fireEvent.click(screen.getByTestId("scheduleRebootBtn"));
expect(screen.getByText(/reboot has been scheduled/i)).toBeInTheDocument(); expect(screen.getByText(/reboot has been scheduled/i)).toBeInTheDocument();
@ -99,12 +100,11 @@ describe("RebootOTADialog", () => {
it("does not call reboot if connection is undefined", async () => { it("does not call reboot if connection is undefined", async () => {
const onOpenChangeMock = vi.fn(); const onOpenChangeMock = vi.fn();
// simulate no connection
mockConnection = undefined; mockConnection = undefined;
render(<RebootOTADialog open onOpenChange={onOpenChangeMock} />); render(<RebootOTADialog open onOpenChange={onOpenChangeMock} />);
fireEvent.click(screen.getByText(/schedule reboot/i)); fireEvent.click(screen.getByTestId("scheduleRebootBtn"));
vi.advanceTimersByTime(5000); vi.advanceTimersByTime(5000);
await waitFor(() => { await waitFor(() => {
@ -112,7 +112,6 @@ describe("RebootOTADialog", () => {
expect(onOpenChangeMock).not.toHaveBeenCalled(); expect(onOpenChangeMock).not.toHaveBeenCalled();
}); });
// reset connection for other tests
mockConnection = { rebootOta: rebootOtaMock }; mockConnection = { rebootOta: rebootOtaMock };
}); });
}); });

2
src/components/Dialog/RebootOTADialog.tsx

@ -94,7 +94,7 @@ export const RebootOTADialog = (
/> />
<Button <Button
onClick={() => handleRebootWithTimeout()} onClick={() => handleRebootWithTimeout()}
name="scheduleReboot" data-testid="scheduleRebootBtn"
className="w-9/12" className="w-9/12"
> >
<ClockIcon className="mr-2" size={18} /> <ClockIcon className="mr-2" size={18} />

2
src/components/LanguageSwitcher.tsx

@ -12,7 +12,7 @@ function LanguageSwitcher() {
return ( return (
<DropdownMenu <DropdownMenu
i18nIsDynamicList={true} i18nIsDynamicList
data-testid="language-list" data-testid="language-list"
> >
<DropdownMenuTrigger>asdlkfj</DropdownMenuTrigger> <DropdownMenuTrigger>asdlkfj</DropdownMenuTrigger>

235
src/components/PageComponents/Config/Bluetooth.tsx

@ -8,131 +8,130 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export const Bluetooth = () => { export const Bluetooth = () => {
const { config, setWorkingConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
hasErrors, hasErrors,
getErrorMessage, getErrorMessage,
hasFieldError, hasFieldError,
addError, addError,
removeError, removeError,
clearErrors, clearErrors,
} = useAppStore(); } = useAppStore();
const { t } = useTranslation("deviceConfig"); const { t } = useTranslation("deviceConfig");
const [bluetoothPin, setBluetoothPin] = useState( const [bluetoothPin, setBluetoothPin] = useState(
config?.bluetooth?.fixedPin.toString() ?? "", config?.bluetooth?.fixedPin.toString() ?? "",
); );
const validateBluetoothPin = (pin: string) => { const validateBluetoothPin = (pin: string) => {
// if empty show error they need a pin set // if empty show error they need a pin set
if (pin === "") { if (pin === "") {
return addError("fixedPin", t("bluetooth.validation.pinRequired")); return addError("fixedPin", t("bluetooth.validation.pinRequired"));
} }
// clear any existing errors // clear any existing errors
clearErrors(); clearErrors();
// if it starts with 0 show error // if it starts with 0 show error
if (pin[0] === "0") { if (pin[0] === "0") {
return addError( return addError(
"fixedPin", "fixedPin",
t("bluetooth.validation.pinCannotStartWithZero"), t("bluetooth.validation.pinCannotStartWithZero"),
); );
} }
// if it's not 6 digits show error // if it's not 6 digits show error
if (pin.length < 6) { if (pin.length < 6) {
return addError("fixedPin", t("bluetooth.validation.pinMustBeSixDigits")); return addError("fixedPin", t("bluetooth.validation.pinMustBeSixDigits"));
} }
removeError("fixedPin"); removeError("fixedPin");
}; };
const bluetoothPinChangeEvent = (e: React.ChangeEvent<HTMLInputElement>) => { const bluetoothPinChangeEvent = (e: React.ChangeEvent<HTMLInputElement>) => {
const numericValue = e.target.value.replace(/\D/g, "").slice(0, 6); const numericValue = e.target.value.replace(/\D/g, "").slice(0, 6);
setBluetoothPin(numericValue); setBluetoothPin(numericValue);
validateBluetoothPin(numericValue); validateBluetoothPin(numericValue);
}; };
const onSubmit = (data: BluetoothValidation) => { const onSubmit = (data: BluetoothValidation) => {
if (hasErrors()) { if (hasErrors()) {
return; return;
} }
setWorkingConfig( setWorkingConfig(
create(Protobuf.Config.ConfigSchema, { create(Protobuf.Config.ConfigSchema, {
payloadVariant: { payloadVariant: {
case: "bluetooth", case: "bluetooth",
value: data, value: data,
}, },
}), }),
); );
}; };
return ( return (
<DynamicForm<BluetoothValidation> <DynamicForm<BluetoothValidation>
onSubmit={onSubmit} onSubmit={onSubmit}
defaultValues={config.bluetooth} defaultValues={config.bluetooth}
fieldGroups={[ fieldGroups={[
{ {
label: t("bluetooth.title"), label: t("bluetooth.title"),
description: t("bluetooth.description"), description: t("bluetooth.description"),
notes: t("bluetooth.note"), notes: t("bluetooth.note"),
fields: [ fields: [
{ {
type: "toggle", type: "toggle",
name: "enabled", name: "enabled",
label: t("bluetooth.enabled.label"), label: t("bluetooth.enabled.label"),
description: t("bluetooth.enabled.description"), description: t("bluetooth.enabled.description"),
}, },
{ {
type: "select", type: "select",
name: "mode", name: "mode",
label: t("bluetooth.pairingMode.label"), label: t("bluetooth.pairingMode.label"),
description: t("bluetooth.pairingMode.description"), description: t("bluetooth.pairingMode.description"),
selectChange: (e) => { selectChange: (e) => {
if (e !== "1") { if (e !== "1") {
setBluetoothPin(""); setBluetoothPin("");
removeError("fixedPin"); removeError("fixedPin");
} }
}, },
disabledBy: [ disabledBy: [
{ {
fieldName: "enabled", fieldName: "enabled",
}, },
], ],
properties: { properties: {
enumValue: Protobuf.Config.Config_BluetoothConfig_PairingMode, enumValue: Protobuf.Config.Config_BluetoothConfig_PairingMode,
formatEnumName: true, formatEnumName: true,
}, },
}, },
{ {
type: "number", type: "number",
name: "fixedPin", name: "fixedPin",
label: t("bluetooth.pin.label"), label: t("bluetooth.pin.label"),
description: t("bluetooth.pin.description"), description: t("bluetooth.pin.description"),
validationText: hasFieldError("fixedPin") validationText: hasFieldError("fixedPin")
? getErrorMessage("fixedPin") ? getErrorMessage("fixedPin")
: "", : "",
inputChange: bluetoothPinChangeEvent, inputChange: bluetoothPinChangeEvent,
disabledBy: [ disabledBy: [
{ {
fieldName: "mode", fieldName: "mode",
selector: selector: Protobuf.Config.Config_BluetoothConfig_PairingMode
Protobuf.Config.Config_BluetoothConfig_PairingMode .FIXED_PIN,
.FIXED_PIN, invert: true,
invert: true, },
}, {
{ fieldName: "enabled",
fieldName: "enabled", },
}, ],
], properties: {
properties: { value: bluetoothPin,
value: bluetoothPin, },
}, },
}, ],
], },
}, ]}
]} />
/> );
);
}; };

1
src/components/PageComponents/Messages/TraceRoute.test.tsx

@ -104,7 +104,6 @@ describe("TraceRoute", () => {
/>, />,
); );
expect(screen.getByText(/^!63$/)).toBeInTheDocument();
expect(screen.getByText("↓ 5dBm")).toBeInTheDocument(); expect(screen.getByText("↓ 5dBm")).toBeInTheDocument();
expect(screen.getByText("↓ 15dBm")).toBeInTheDocument(); expect(screen.getByText("↓ 15dBm")).toBeInTheDocument();
}); });

4
src/components/PageComponents/Messages/TraceRoute.tsx

@ -34,7 +34,7 @@ const RoutePath = (
<p className="font-semibold">{title}</p> <p className="font-semibold">{title}</p>
<p>{startNode?.user?.longName}</p> <p>{startNode?.user?.longName}</p>
<p> <p>
{snr?.[0] ?? t("traceRoute.snrUnknown")} {snr?.[0] ?? t("unknown.num")}
{t("unit.dbm")} {t("unit.dbm")}
</p> </p>
{path.map((hop, i) => ( {path.map((hop, i) => (
@ -44,7 +44,7 @@ const RoutePath = (
`${t("traceRoute.nodeUnknownPrefix")}${numberToHexUnpadded(hop)}`} `${t("traceRoute.nodeUnknownPrefix")}${numberToHexUnpadded(hop)}`}
</p> </p>
<p> <p>
{snr?.[i + 1] ?? t("traceRoute.snrUnknown")} {snr?.[i + 1] ?? t("unknown.num")}
{t("unit.dbm")} {t("unit.dbm")}
</p> </p>
</span> </span>

4
src/i18n/locales/en/common.json

@ -63,9 +63,9 @@
}, },
"unknown": { "unknown": {
"longName": "Unknown", "longName": "Unknown",
"shortName": "UNK" "shortName": "UNK",
"num": "??"
}, },
"snrUnknown": "??",
"nodeUnknownPrefix": "!", "nodeUnknownPrefix": "!",
"unset": "UNSET", "unset": "UNSET",
"fallbackName": "Meshtastic {{last4}}" "fallbackName": "Meshtastic {{last4}}"

1
src/pages/Dashboard/index.tsx

@ -14,7 +14,6 @@ import {
} from "lucide-react"; } from "lucide-react";
import { useMemo } from "react"; import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import LanguageSwitcher from "@components/LanguageSwitcher.tsx";
export const Dashboard = () => { export const Dashboard = () => {
const { t } = useTranslation("dashboard"); const { t } = useTranslation("dashboard");

53
src/tests/setupTests.ts

@ -5,7 +5,16 @@ import "@testing-library/jest-dom";
import "@testing-library/user-event"; import "@testing-library/user-event";
import i18n from "i18next"; import i18n from "i18next";
import { initReactI18next } from "react-i18next"; import { initReactI18next } from "react-i18next";
import enTranslations from "@app/i18n/locales/en.json"; import channelsEN from "@app/i18n/locales/en/channels.json";
import commandPaletteEN from "@app/i18n/locales/en/commandPalette.json";
import commonEN from "@app/i18n/locales/en/common.json";
import deviceConfigEN from "@app/i18n/locales/en/deviceConfig.json";
import moduleConfigEN from "@app/i18n/locales/en/moduleConfig.json";
import dashboardEN from "@app/i18n/locales/en/dashboard.json";
import dialogEN from "@app/i18n/locales/en/dialog.json";
import messagesEN from "@app/i18n/locales/en/messages.json";
import nodesEN from "@app/i18n/locales/en/nodes.json";
import uiEN from "@app/i18n/locales/en/ui.json";
enableMapSet(); enableMapSet();
@ -24,22 +33,56 @@ globalThis.ResizeObserver = class {
disconnect() {} disconnect() {}
}; };
const appNamespaces = [
"channels",
"commandPalette",
"common",
"deviceConfig",
"moduleConfig",
"dashboard",
"dialog",
"messages",
"nodes",
"ui",
];
const appFallbackNS = ["common", "ui", "dialog"];
const appDefaultNS = "common";
i18n i18n
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
lng: "en", lng: "en",
fallbackLng: "en", fallbackLng: "en",
debug: false,
ns: appNamespaces,
defaultNS: appDefaultNS,
fallbackNS: appFallbackNS,
supportedLngs: ["en"],
resources: { resources: {
en: { en: {
translation: enTranslations, channels: channelsEN,
commandPalette: commandPaletteEN,
common: commonEN,
deviceConfig: deviceConfigEN,
moduleConfig: moduleConfigEN,
dashboard: dashboardEN,
dialog: dialogEN,
messages: messagesEN,
nodes: nodesEN,
ui: uiEN,
}, },
}, },
interpolation: { interpolation: {
escapeValue: false, escapeValue: false,
}, },
defaultNS: "translation",
initImmediate: true, react: {
useSuspense: false,
},
debug: false,
}); });
afterEach(() => { afterEach(() => {

Loading…
Cancel
Save