mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { getAnimateMock } from '$lib/__mocks__/animate.mock';
|
||||
import { getIntersectionObserverMock } from '$lib/__mocks__/intersection-observer.mock';
|
||||
import { getVisualViewportMock } from '$lib/__mocks__/visual-viewport.mock';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';
|
||||
import { DateTime } from 'luxon';
|
||||
import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import AssetChangeDateModal from './AssetChangeDateModal.svelte';
|
||||
|
||||
describe('AssetChangeDateModal component', () => {
|
||||
const initialDate = DateTime.fromISO('2026-03-19T23:31:30.112');
|
||||
const initialTimeZone = 'Europe/Lisbon';
|
||||
const onClose = vi.fn();
|
||||
|
||||
const getDateInput = async () => (await screen.findByDisplayValue('2026-03-19T23:31:30.112')) as HTMLInputElement;
|
||||
const getTimeZoneInput = () => screen.getByRole('combobox', { name: /timezone/i }) as HTMLInputElement;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('IntersectionObserver', getIntersectionObserverMock());
|
||||
vi.stubGlobal('visualViewport', getVisualViewportMock());
|
||||
vi.resetAllMocks();
|
||||
Element.prototype.animate = getAnimateMock();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await waitFor(() => {
|
||||
expect(document.body.style.pointerEvents).not.toBe('none');
|
||||
});
|
||||
});
|
||||
|
||||
test('preserves the selected timezone when changing the datetime', async () => {
|
||||
render(AssetChangeDateModal, {
|
||||
props: {
|
||||
initialDate,
|
||||
initialTimeZone,
|
||||
timezoneInput: true,
|
||||
asset: { id: 'asset-id' } as never,
|
||||
onClose,
|
||||
},
|
||||
});
|
||||
|
||||
const timezoneInput = getTimeZoneInput();
|
||||
const datetimeInput = await getDateInput();
|
||||
|
||||
const initialTimezoneValue = timezoneInput.value;
|
||||
|
||||
await fireEvent.focus(timezoneInput);
|
||||
await fireEvent.input(timezoneInput, { target: { value: 'Pacific/Pitcairn' } });
|
||||
|
||||
const option = await screen.findByText(/Pacific\/Pitcairn/i);
|
||||
await fireEvent.click(option);
|
||||
|
||||
expect(timezoneInput.value).toBe('Pacific/Pitcairn (-08:00)');
|
||||
expect(timezoneInput.value).not.toBe(initialTimezoneValue);
|
||||
|
||||
const beforeDatetime = datetimeInput.value;
|
||||
|
||||
await fireEvent.input(datetimeInput, {
|
||||
target: { value: '2026-03-19T23:31:31.113' },
|
||||
});
|
||||
await fireEvent.change(datetimeInput, {
|
||||
target: { value: '2026-03-19T23:31:31.113' },
|
||||
});
|
||||
|
||||
expect(datetimeInput.value).not.toBe(beforeDatetime);
|
||||
expect(timezoneInput.value).toBe('Pacific/Pitcairn (-08:00)');
|
||||
});
|
||||
});
|
||||
@@ -23,10 +23,7 @@
|
||||
let selectedDate = $state(initialDate.toFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"));
|
||||
const timezones = $derived(getTimezones(selectedDate));
|
||||
|
||||
// svelte-ignore state_referenced_locally
|
||||
let lastSelectedTimezone = $state(getPreferredTimeZone(initialDate, initialTimeZone, timezones));
|
||||
// the offsets (and validity) for time zones may change if the date is changed, which is why we recompute the list
|
||||
let selectedOption = $derived(getPreferredTimeZone(initialDate, initialTimeZone, timezones, lastSelectedTimezone));
|
||||
let selectedOption = $state(getPreferredTimeZone(initialDate, initialTimeZone, getTimezones(selectedDate)));
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (!date.isValid || !selectedOption) {
|
||||
@@ -45,6 +42,12 @@
|
||||
}
|
||||
};
|
||||
|
||||
const updateSelectedDate = (value: string) => {
|
||||
selectedDate = value;
|
||||
|
||||
selectedOption = getPreferredTimeZone(initialDate, initialTimeZone, getTimezones(value), selectedOption);
|
||||
};
|
||||
|
||||
// when changing the time zone, assume the configured date/time is meant for that time zone (instead of updating it)
|
||||
const date = $derived(DateTime.fromISO(selectedDate, { zone: selectedOption?.value, setZone: true }));
|
||||
</script>
|
||||
@@ -59,7 +62,12 @@
|
||||
size="small"
|
||||
>
|
||||
<Label for="datetime" class="block mb-1">{$t('date_and_time')}</Label>
|
||||
<DateInput class="immich-form-input w-full mb-2" id="datetime" type="datetime-local" bind:value={selectedDate} />
|
||||
<DateInput
|
||||
class="immich-form-input w-full mb-2"
|
||||
id="datetime"
|
||||
type="datetime-local"
|
||||
bind:value={() => selectedDate, updateSelectedDate}
|
||||
/>
|
||||
{#if timezoneInput}
|
||||
<div class="w-full">
|
||||
<Combobox bind:selectedOption label={$t('timezone')} options={timezones} placeholder={$t('search_timezone')} />
|
||||
|
||||
Reference in New Issue
Block a user