UI: Add date format preference in user interface settings (#29321)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
parent
28bb5ba859
commit
37d8aecbb2
9 changed files with 195 additions and 18 deletions
|
|
@ -59,6 +59,19 @@
|
||||||
equal-width
|
equal-width
|
||||||
/>
|
/>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
|
<FormRow id="settingsDateFormat" :label="$t('settings.dateFormat.label')">
|
||||||
|
<select
|
||||||
|
id="settingsDateFormat"
|
||||||
|
v-model="dateFormat"
|
||||||
|
class="form-select form-select-sm w-75"
|
||||||
|
>
|
||||||
|
<option value="">{{ $t("settings.dateFormat.auto") }}</option>
|
||||||
|
<option value="dmy">{{ $t("settings.dateFormat.dmy") }}</option>
|
||||||
|
<option value="mdy">{{ $t("settings.dateFormat.mdy") }}</option>
|
||||||
|
<option value="ymd">{{ $t("settings.dateFormat.ymd") }}</option>
|
||||||
|
</select>
|
||||||
|
<div class="form-text evcc-gray">{{ dateFormatExample }}</div>
|
||||||
|
</FormRow>
|
||||||
<FormRow v-if="loadpoints.length" :label="$t('settings.loadpoints.label')">
|
<FormRow v-if="loadpoints.length" :label="$t('settings.loadpoints.label')">
|
||||||
<LoadpointOrderSettings :loadpoints="loadpoints" />
|
<LoadpointOrderSettings :loadpoints="loadpoints" />
|
||||||
</FormRow>
|
</FormRow>
|
||||||
|
|
@ -91,14 +104,24 @@ import {
|
||||||
removeLocalePreference,
|
removeLocalePreference,
|
||||||
} from "@/i18n.ts";
|
} from "@/i18n.ts";
|
||||||
import { getThemePreference, setThemePreference } from "@/theme.ts";
|
import { getThemePreference, setThemePreference } from "@/theme.ts";
|
||||||
import { getUnits, setUnits, is12hFormat, set12hFormat } from "@/units";
|
import {
|
||||||
|
getUnits,
|
||||||
|
setUnits,
|
||||||
|
is12hFormat,
|
||||||
|
set12hFormat,
|
||||||
|
getDateFormat,
|
||||||
|
setDateFormat,
|
||||||
|
} from "@/units";
|
||||||
import { isApp } from "@/utils/native";
|
import { isApp } from "@/utils/native";
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import { LENGTH_UNIT, THEME, TIME_FORMAT, type UiLoadpoint } from "@/types/evcc";
|
import { LENGTH_UNIT, THEME, TIME_FORMAT, type UiLoadpoint } from "@/types/evcc";
|
||||||
|
import formatter from "@/mixins/formatter";
|
||||||
|
import type { DateFormat } from "@/settings";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UserInterfaceSettings",
|
name: "UserInterfaceSettings",
|
||||||
components: { FormRow, SelectGroup, LoadpointOrderSettings },
|
components: { FormRow, SelectGroup, LoadpointOrderSettings },
|
||||||
|
mixins: [formatter],
|
||||||
props: {
|
props: {
|
||||||
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
||||||
},
|
},
|
||||||
|
|
@ -115,6 +138,17 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
dateFormat: {
|
||||||
|
get(): DateFormat {
|
||||||
|
return getDateFormat();
|
||||||
|
},
|
||||||
|
set(value: DateFormat) {
|
||||||
|
setDateFormat(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dateFormatExample(): string {
|
||||||
|
return this.fmtFullDateTime(new Date(2015, 9, 21, 16, 29));
|
||||||
|
},
|
||||||
languageOptions: () => {
|
languageOptions: () => {
|
||||||
const locales = Object.entries(LOCALES).map(([key, value]) => {
|
const locales = Object.entries(LOCALES).map(([key, value]) => {
|
||||||
return { value: key, name: value[1] };
|
return { value: key, name: value[1] };
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,11 @@
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<template v-if="session.created">
|
<template v-if="session.created">
|
||||||
{{ fmtFullDateTime(new Date(session.created), false) }}
|
{{ fmtFullDateTime(new Date(session.created)) }}
|
||||||
</template>
|
</template>
|
||||||
<br />
|
<br />
|
||||||
<template v-if="session.finished">
|
<template v-if="session.finished">
|
||||||
{{ fmtFullDateTime(new Date(session.finished), false) }}
|
{{ fmtFullDateTime(new Date(session.finished)) }}
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@
|
||||||
@click="showDetails(session.id)"
|
@click="showDetails(session.id)"
|
||||||
>
|
>
|
||||||
<td class="ps-0 tabular">
|
<td class="ps-0 tabular">
|
||||||
{{ fmtFullDateTime(new Date(session.created), true) }}
|
{{ fmtWeekdayDayTime(new Date(session.created)) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="d-none d-md-table-cell">
|
<td class="d-none d-md-table-cell">
|
||||||
{{ session.loadpoint }}
|
{{ session.loadpoint }}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { mount, config } from "@vue/test-utils";
|
||||||
import { describe, expect, test, vi } from "vite-plus/test";
|
import { describe, expect, test, vi } from "vite-plus/test";
|
||||||
import formatter, { POWER_UNIT } from "./formatter";
|
import formatter, { POWER_UNIT } from "./formatter";
|
||||||
import * as units from "../units";
|
import * as units from "../units";
|
||||||
|
import settings from "../settings";
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { CURRENCY } from "@/types/evcc";
|
import { CURRENCY } from "@/types/evcc";
|
||||||
|
|
||||||
|
|
@ -275,7 +276,7 @@ describe("12h/24h time format", () => {
|
||||||
test("12h format", () => {
|
test("12h format", () => {
|
||||||
is12hSpy.mockReturnValue(true);
|
is12hSpy.mockReturnValue(true);
|
||||||
expect(fmt.fmtHourMinute(testDate)).toBe("3:30 PM");
|
expect(fmt.fmtHourMinute(testDate)).toBe("3:30 PM");
|
||||||
expect(fmt.fmtFullDateTime(testDate, false)).toBe("So., 15. Jan., 3:30 PM");
|
expect(fmt.fmtFullDateTime(testDate)).toBe("So., 15. Jan. 2023, 3:30 PM");
|
||||||
expect(fmt.fmtWeekdayTime(testDate)).toBe("So. 3:30 PM");
|
expect(fmt.fmtWeekdayTime(testDate)).toBe("So. 3:30 PM");
|
||||||
expect(fmt.fmtAbsoluteDate(testDate)).toBe("So 3:30 PM");
|
expect(fmt.fmtAbsoluteDate(testDate)).toBe("So 3:30 PM");
|
||||||
});
|
});
|
||||||
|
|
@ -283,12 +284,29 @@ describe("12h/24h time format", () => {
|
||||||
test("24h format", () => {
|
test("24h format", () => {
|
||||||
is12hSpy.mockReturnValue(false);
|
is12hSpy.mockReturnValue(false);
|
||||||
expect(fmt.fmtHourMinute(testDate)).toBe("15:30");
|
expect(fmt.fmtHourMinute(testDate)).toBe("15:30");
|
||||||
expect(fmt.fmtFullDateTime(testDate, false)).toBe("So., 15. Jan., 15:30");
|
expect(fmt.fmtFullDateTime(testDate)).toBe("So., 15. Jan. 2023, 15:30");
|
||||||
expect(fmt.fmtWeekdayTime(testDate)).toBe("So., 15:30");
|
expect(fmt.fmtWeekdayTime(testDate)).toBe("So., 15:30");
|
||||||
expect(fmt.fmtAbsoluteDate(testDate)).toBe("So 15:30");
|
expect(fmt.fmtAbsoluteDate(testDate)).toBe("So 15:30");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("date format", () => {
|
||||||
|
test("should order day and month by preference", () => {
|
||||||
|
is12hSpy.mockReturnValue(false);
|
||||||
|
settings.dateFormat = "dmy";
|
||||||
|
expect(fmt.fmtFullDateTime(testDate)).toBe("So. 15 Jan. 2023 15:30");
|
||||||
|
settings.dateFormat = "mdy";
|
||||||
|
expect(fmt.fmtFullDateTime(testDate)).toBe("So. Jan. 15, 2023 15:30");
|
||||||
|
settings.dateFormat = "ymd";
|
||||||
|
expect(fmt.fmtFullDateTime(testDate)).toBe("So. 2023-01-15 15:30");
|
||||||
|
settings.dateFormat = "";
|
||||||
|
});
|
||||||
|
test("should format day and time", () => {
|
||||||
|
is12hSpy.mockReturnValue(false);
|
||||||
|
expect(fmt.fmtWeekdayDayTime(testDate)).toBe("So. 15, 15:30");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("fmtTimeRange", () => {
|
describe("fmtTimeRange", () => {
|
||||||
test("should format time ranges in 24h format", () => {
|
test("should format time ranges in 24h format", () => {
|
||||||
is12hSpy.mockReturnValue(false);
|
is12hSpy.mockReturnValue(false);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,55 @@
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { is12hFormat } from "@/units";
|
import { is12hFormat } from "@/units";
|
||||||
import { CURRENCY } from "../types/evcc";
|
import { CURRENCY } from "../types/evcc";
|
||||||
|
import settings from "@/settings";
|
||||||
|
import type { DateFormat } from "@/settings";
|
||||||
|
|
||||||
|
// Extract a single part in date context, where names can differ from their
|
||||||
|
// standalone forms (German "So.", "Jan." vs "So", "Jan").
|
||||||
|
function datePart(
|
||||||
|
date: Date,
|
||||||
|
locale: string | undefined,
|
||||||
|
type: Intl.DateTimeFormatPartTypes
|
||||||
|
): string {
|
||||||
|
return (
|
||||||
|
new Intl.DateTimeFormat(locale, { weekday: "short", day: "numeric", month: "short" })
|
||||||
|
.formatToParts(date)
|
||||||
|
.find((part) => part.type === type)?.value ?? ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Day+month(+year) in the user's date order, e.g. "17 Mai" or "Mai 17, 2025".
|
||||||
|
// Ordering and punctuation come from a reference locale (en-GB day-first,
|
||||||
|
// en-US month-first), month names stay translated. ymd is the full ISO date.
|
||||||
|
function formatDayMonth(
|
||||||
|
date: Date,
|
||||||
|
locale: string | undefined,
|
||||||
|
fmt: DateFormat,
|
||||||
|
year = false
|
||||||
|
): string {
|
||||||
|
if (fmt === "ymd") return isoDate(date);
|
||||||
|
const orderLocale = fmt === "mdy" ? "en-US" : "en-GB";
|
||||||
|
const month = datePart(date, locale, "month");
|
||||||
|
// some locales (e.g. Czech) use numeric months in date context
|
||||||
|
const name = /\p{L}/u.test(month)
|
||||||
|
? month
|
||||||
|
: new Intl.DateTimeFormat(locale, { month: "short" }).format(date);
|
||||||
|
return new Intl.DateTimeFormat(orderLocale, {
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
year: year ? "numeric" : undefined,
|
||||||
|
})
|
||||||
|
.formatToParts(date)
|
||||||
|
.map((part) => (part.type === "month" ? name : part.value))
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// local-time ISO date, Intl cannot produce this reliably across locales
|
||||||
|
function isoDate(date: Date): string {
|
||||||
|
const mm = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const dd = String(date.getDate()).padStart(2, "0");
|
||||||
|
return `${date.getFullYear()}-${mm}-${dd}`;
|
||||||
|
}
|
||||||
|
|
||||||
const CURRENCY_SYMBOLS: Record<CURRENCY, string> = {
|
const CURRENCY_SYMBOLS: Record<CURRENCY, string> = {
|
||||||
AUD: "$",
|
AUD: "$",
|
||||||
|
|
@ -62,6 +111,11 @@ export default defineComponent({
|
||||||
fmtDigits: 1,
|
fmtDigits: 1,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
dateFormat(): DateFormat {
|
||||||
|
return settings.dateFormat || "";
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
energyPriceSubunit(currency: CURRENCY): string | undefined {
|
energyPriceSubunit(currency: CURRENCY): string | undefined {
|
||||||
if (currency === CURRENCY.CHF) {
|
if (currency === CURRENCY.CHF) {
|
||||||
|
|
@ -265,15 +319,33 @@ export default defineComponent({
|
||||||
hour12: is12hFormat(),
|
hour12: is12hFormat(),
|
||||||
}).format(date);
|
}).format(date);
|
||||||
},
|
},
|
||||||
fmtFullDateTime(date: Date, short: boolean) {
|
fmtFullDateTime(date: Date) {
|
||||||
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
const locale = this.$i18n?.locale;
|
||||||
weekday: short ? undefined : "short",
|
const fmt = this.dateFormat;
|
||||||
month: short ? "numeric" : "short",
|
if (!fmt) {
|
||||||
day: "numeric",
|
// auto: single Intl call preserves locale-native separators (e.g. German "So., 15. Jan.,")
|
||||||
|
return new Intl.DateTimeFormat(locale, {
|
||||||
|
weekday: "short",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
hour: "numeric",
|
||||||
|
minute: "numeric",
|
||||||
|
hour12: is12hFormat(),
|
||||||
|
}).format(date);
|
||||||
|
}
|
||||||
|
const time = new Intl.DateTimeFormat(locale, {
|
||||||
hour: "numeric",
|
hour: "numeric",
|
||||||
minute: "numeric",
|
minute: "numeric",
|
||||||
hour12: is12hFormat(),
|
hour12: is12hFormat(),
|
||||||
}).format(date);
|
}).format(date);
|
||||||
|
const weekday = datePart(date, locale, "weekday");
|
||||||
|
return `${weekday} ${formatDayMonth(date, locale, fmt, true)} ${time}`.trim();
|
||||||
|
},
|
||||||
|
// weekday + day of month + time, for lists within a known month
|
||||||
|
fmtWeekdayDayTime(date: Date) {
|
||||||
|
const weekday = datePart(date, this.$i18n?.locale, "weekday");
|
||||||
|
return `${weekday} ${date.getDate()}, ${this.fmtHourMinute(date)}`;
|
||||||
},
|
},
|
||||||
fmtWeekdayTime(date: Date) {
|
fmtWeekdayTime(date: Date) {
|
||||||
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
||||||
|
|
@ -295,11 +367,17 @@ export default defineComponent({
|
||||||
}).format(date);
|
}).format(date);
|
||||||
},
|
},
|
||||||
fmtDayMonth(date: Date) {
|
fmtDayMonth(date: Date) {
|
||||||
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
const locale = this.$i18n?.locale;
|
||||||
weekday: "short",
|
const fmt = this.dateFormat;
|
||||||
day: "numeric",
|
if (!fmt) {
|
||||||
month: "short",
|
return new Intl.DateTimeFormat(locale, {
|
||||||
}).format(date);
|
weekday: "short",
|
||||||
|
day: "numeric",
|
||||||
|
month: "short",
|
||||||
|
}).format(date);
|
||||||
|
}
|
||||||
|
const weekday = datePart(date, locale, "weekday");
|
||||||
|
return `${weekday} ${formatDayMonth(date, locale, fmt)}`.trim();
|
||||||
},
|
},
|
||||||
fmtDayMonthYear(date: Date) {
|
fmtDayMonthYear(date: Date) {
|
||||||
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ const BATTERY_UNIT = "battery_unit";
|
||||||
const SETTINGS_PRICE_ZOOM = "settings_price_zoom";
|
const SETTINGS_PRICE_ZOOM = "settings_price_zoom";
|
||||||
const SETTINGS_HIDE_FEEDIN = "settings_hide_feedin";
|
const SETTINGS_HIDE_FEEDIN = "settings_hide_feedin";
|
||||||
const LAST_BATTERY_SMART_COST_LIMIT = "last_battery_smart_cost_limit";
|
const LAST_BATTERY_SMART_COST_LIMIT = "last_battery_smart_cost_limit";
|
||||||
|
const SETTINGS_DATE_FORMAT = "settings_date_format";
|
||||||
const LAST_TARGET_TIME = "last_target_time";
|
const LAST_TARGET_TIME = "last_target_time";
|
||||||
const LAST_SOC_GOAL = "last_soc_goal";
|
const LAST_SOC_GOAL = "last_soc_goal";
|
||||||
const LAST_ENERGY_GOAL = "last_energy_goal";
|
const LAST_ENERGY_GOAL = "last_energy_goal";
|
||||||
|
|
@ -99,6 +100,8 @@ function saveJSON(key: string) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DateFormat = "" | "dmy" | "mdy" | "ymd";
|
||||||
|
|
||||||
export interface LoadpointSettings {
|
export interface LoadpointSettings {
|
||||||
order?: number;
|
order?: number;
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
|
|
@ -112,6 +115,7 @@ export interface Settings {
|
||||||
theme: THEME | null;
|
theme: THEME | null;
|
||||||
unit: string;
|
unit: string;
|
||||||
is12hFormat: boolean;
|
is12hFormat: boolean;
|
||||||
|
dateFormat: DateFormat;
|
||||||
energyflowDetails: boolean;
|
energyflowDetails: boolean;
|
||||||
energyflowCo2: boolean;
|
energyflowCo2: boolean;
|
||||||
energyflowPv: boolean;
|
energyflowPv: boolean;
|
||||||
|
|
@ -141,6 +145,7 @@ const settings: Settings = reactive({
|
||||||
theme: read(SETTINGS_THEME),
|
theme: read(SETTINGS_THEME),
|
||||||
unit: read(SETTINGS_UNIT),
|
unit: read(SETTINGS_UNIT),
|
||||||
is12hFormat: readBool(SETTINGS_12H_FORMAT),
|
is12hFormat: readBool(SETTINGS_12H_FORMAT),
|
||||||
|
dateFormat: read(SETTINGS_DATE_FORMAT) || "",
|
||||||
energyflowDetails: readBool(SETTINGS_ENERGYFLOW_DETAILS),
|
energyflowDetails: readBool(SETTINGS_ENERGYFLOW_DETAILS),
|
||||||
energyflowCo2: readBool(SETTINGS_ENERGYFLOW_CO2),
|
energyflowCo2: readBool(SETTINGS_ENERGYFLOW_CO2),
|
||||||
energyflowPv: readBool(SETTINGS_ENERGYFLOW_PV),
|
energyflowPv: readBool(SETTINGS_ENERGYFLOW_PV),
|
||||||
|
|
@ -169,6 +174,7 @@ watch(() => settings.locale, save(SETTINGS_LOCALE));
|
||||||
watch(() => settings.theme, save(SETTINGS_THEME));
|
watch(() => settings.theme, save(SETTINGS_THEME));
|
||||||
watch(() => settings.unit, save(SETTINGS_UNIT));
|
watch(() => settings.unit, save(SETTINGS_UNIT));
|
||||||
watch(() => settings.is12hFormat, saveBool(SETTINGS_12H_FORMAT));
|
watch(() => settings.is12hFormat, saveBool(SETTINGS_12H_FORMAT));
|
||||||
|
watch(() => settings.dateFormat, save(SETTINGS_DATE_FORMAT));
|
||||||
watch(() => settings.energyflowDetails, saveBool(SETTINGS_ENERGYFLOW_DETAILS));
|
watch(() => settings.energyflowDetails, saveBool(SETTINGS_ENERGYFLOW_DETAILS));
|
||||||
watch(() => settings.energyflowCo2, saveBool(SETTINGS_ENERGYFLOW_CO2));
|
watch(() => settings.energyflowCo2, saveBool(SETTINGS_ENERGYFLOW_CO2));
|
||||||
watch(() => settings.energyflowPv, saveBool(SETTINGS_ENERGYFLOW_PV));
|
watch(() => settings.energyflowPv, saveBool(SETTINGS_ENERGYFLOW_PV));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import settings from "./settings";
|
import settings from "./settings";
|
||||||
|
import type { DateFormat } from "./settings";
|
||||||
import { LENGTH_UNIT } from "./types/evcc";
|
import { LENGTH_UNIT } from "./types/evcc";
|
||||||
|
|
||||||
const MILES_FACTOR = 0.6213711922;
|
const MILES_FACTOR = 0.6213711922;
|
||||||
|
|
@ -34,3 +35,11 @@ export function is12hFormat() {
|
||||||
export function set12hFormat(value: boolean) {
|
export function set12hFormat(value: boolean) {
|
||||||
settings.is12hFormat = value;
|
settings.is12hFormat = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDateFormat(): DateFormat {
|
||||||
|
return settings.dateFormat || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDateFormat(value: DateFormat) {
|
||||||
|
settings.dateFormat = value;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1718,6 +1718,13 @@
|
||||||
"vehicle": "Vehicle"
|
"vehicle": "Vehicle"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"dateFormat": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"dmy": "DD/MM/YYYY",
|
||||||
|
"label": "Date format",
|
||||||
|
"mdy": "MM/DD/YYYY",
|
||||||
|
"ymd": "YYYY-MM-DD"
|
||||||
|
},
|
||||||
"deviceInfo": "Settings you make in this dialog only affect this device.",
|
"deviceInfo": "Settings you make in this dialog only affect this device.",
|
||||||
"fullscreen": {
|
"fullscreen": {
|
||||||
"enter": "Enter fullscreen",
|
"enter": "Enter fullscreen",
|
||||||
|
|
|
||||||
|
|
@ -388,7 +388,7 @@ test.describe("session details", async () => {
|
||||||
await expect(modal.getByLabel("Charging point")).toHaveValue("Garage");
|
await expect(modal.getByLabel("Charging point")).toHaveValue("Garage");
|
||||||
await expect(modal.getByLabel("Vehicle")).toHaveValue("weißes Model 3");
|
await expect(modal.getByLabel("Vehicle")).toHaveValue("weißes Model 3");
|
||||||
await expect(modal.getByTestId("session-details-date")).toContainText(
|
await expect(modal.getByTestId("session-details-date")).toContainText(
|
||||||
["Thu, May 4, 22:00", "Fri, May 5, 06:00"].join("")
|
["Thu, May 4, 2023, 22:00", "Fri, May 5, 2023, 06:00"].join("")
|
||||||
);
|
);
|
||||||
await expect(modal.getByTestId("session-details-energy")).toContainText("5.0 kWh");
|
await expect(modal.getByTestId("session-details-energy")).toContainText("5.0 kWh");
|
||||||
await expect(modal.getByTestId("session-details-energy")).toContainText("1:00");
|
await expect(modal.getByTestId("session-details-energy")).toContainText("1:00");
|
||||||
|
|
@ -410,7 +410,7 @@ test.describe("session details", async () => {
|
||||||
await expect(modal.getByLabel("Charging point")).toHaveValue("Carport");
|
await expect(modal.getByLabel("Charging point")).toHaveValue("Carport");
|
||||||
await expect(modal.getByLabel("Vehicle")).toHaveValue("blauer e-Golf");
|
await expect(modal.getByLabel("Vehicle")).toHaveValue("blauer e-Golf");
|
||||||
await expect(modal.getByTestId("session-details-date")).toContainText(
|
await expect(modal.getByTestId("session-details-date")).toContainText(
|
||||||
["Wed, Mar 1, 07:00", "Tue, May 2, 12:00"].join("")
|
["Wed, Mar 1, 2023, 07:00", "Tue, May 2, 2023, 12:00"].join("")
|
||||||
);
|
);
|
||||||
await expect(modal.getByTestId("session-details-energy")).toContainText("10.0 kWh");
|
await expect(modal.getByTestId("session-details-energy")).toContainText("10.0 kWh");
|
||||||
await expect(modal.getByTestId("session-details-energy")).toContainText("1:00");
|
await expect(modal.getByTestId("session-details-energy")).toContainText("1:00");
|
||||||
|
|
@ -422,6 +422,31 @@ test.describe("session details", async () => {
|
||||||
await expect(modal.getByTestId("session-details-odometer")).toContainText("12,345 km");
|
await expect(modal.getByTestId("session-details-odometer")).toContainText("12,345 km");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("date format setting (session 1)", async ({ page }) => {
|
||||||
|
await page.goto("/#/sessions?year=2023&month=3");
|
||||||
|
const modal = page.getByTestId("session-details");
|
||||||
|
const date = modal.getByTestId("session-details-date");
|
||||||
|
|
||||||
|
// auto format
|
||||||
|
await page.getByTestId("sessions-entry").nth(0).click();
|
||||||
|
await expectModalVisible(modal);
|
||||||
|
await expect(date).toContainText("Wed, Mar 1, 2023, 07:00");
|
||||||
|
await modal.getByRole("button", { name: "Close" }).click();
|
||||||
|
await expectModalHidden(modal);
|
||||||
|
|
||||||
|
await openMoreMenu(page);
|
||||||
|
await page.getByRole("button", { name: "User Interface", exact: true }).click();
|
||||||
|
const settings = page.getByTestId("global-settings-modal");
|
||||||
|
await expectModalVisible(settings);
|
||||||
|
await settings.getByLabel("Date format").selectOption("ymd");
|
||||||
|
await settings.getByRole("button", { name: "Close" }).click();
|
||||||
|
await expectModalHidden(settings);
|
||||||
|
|
||||||
|
await page.getByTestId("sessions-entry").nth(0).click();
|
||||||
|
await expectModalVisible(modal);
|
||||||
|
await expect(date).toContainText("Wed 2023-03-01 07:00");
|
||||||
|
});
|
||||||
|
|
||||||
test("edit session (session 5)", async ({ page }) => {
|
test("edit session (session 5)", async ({ page }) => {
|
||||||
await page.goto("/#/sessions?year=2023&month=5");
|
await page.goto("/#/sessions?year=2023&month=5");
|
||||||
await page.getByTestId("sessions-entry").nth(0).click();
|
await page.getByTestId("sessions-entry").nth(0).click();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue