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

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

@ -60,7 +60,8 @@ describe("RebootOTADialog", () => {
it("renders dialog with default input value", () => {
render(<RebootOTADialog open onOpenChange={() => {}} />);
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();
});
@ -72,7 +73,7 @@ describe("RebootOTADialog", () => {
target: { value: "3" },
});
fireEvent.click(screen.getByText(/schedule reboot/i));
fireEvent.click(screen.getByTestId("scheduleRebootBtn"));
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 () => {
const onOpenChangeMock = vi.fn();
// simulate no connection
mockConnection = undefined;
render(<RebootOTADialog open onOpenChange={onOpenChangeMock} />);
fireEvent.click(screen.getByText(/schedule reboot/i));
fireEvent.click(screen.getByTestId("scheduleRebootBtn"));
vi.advanceTimersByTime(5000);
await waitFor(() => {
@ -112,7 +112,6 @@ describe("RebootOTADialog", () => {
expect(onOpenChangeMock).not.toHaveBeenCalled();
});
// reset connection for other tests
mockConnection = { rebootOta: rebootOtaMock };
});
});

2
src/components/Dialog/RebootOTADialog.tsx

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

2
src/components/LanguageSwitcher.tsx

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

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

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

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

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

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

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

1
src/pages/Dashboard/index.tsx

@ -14,7 +14,6 @@ import {
} from "lucide-react";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import LanguageSwitcher from "@components/LanguageSwitcher.tsx";
export const 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 i18n from "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();
@ -24,22 +33,56 @@ globalThis.ResizeObserver = class {
disconnect() {}
};
const appNamespaces = [
"channels",
"commandPalette",
"common",
"deviceConfig",
"moduleConfig",
"dashboard",
"dialog",
"messages",
"nodes",
"ui",
];
const appFallbackNS = ["common", "ui", "dialog"];
const appDefaultNS = "common";
i18n
.use(initReactI18next)
.init({
lng: "en",
fallbackLng: "en",
debug: false,
ns: appNamespaces,
defaultNS: appDefaultNS,
fallbackNS: appFallbackNS,
supportedLngs: ["en"],
resources: {
en: {
translation: enTranslations,
channels: channelsEN,
commandPalette: commandPaletteEN,
common: commonEN,
deviceConfig: deviceConfigEN,
moduleConfig: moduleConfigEN,
dashboard: dashboardEN,
dialog: dialogEN,
messages: messagesEN,
nodes: nodesEN,
ui: uiEN,
},
},
interpolation: {
escapeValue: false,
},
defaultNS: "translation",
initImmediate: true,
react: {
useSuspense: false,
},
debug: false,
});
afterEach(() => {

Loading…
Cancel
Save