Fix timezone mismatch modal posting to the removed Jetstream route

Use useUpdateUserMutation, matching UpdateProfileInformationForm.
This commit is contained in:
Andrew Herron
2026-08-29 16:44:56 +10:00
committed by Gregor Vostrak
parent 602a8daa1f
commit 7831bc697e
2 changed files with 91 additions and 25 deletions

View File

@@ -0,0 +1,72 @@
import { flushPromises, shallowMount } from '@vue/test-utils';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { createPinia } from 'pinia';
import { VueQueryPlugin } from '@tanstack/vue-query';
import UserTimezoneMismatchModal from './UserTimezoneMismatchModal.vue';
import TimezoneMismatchModal from '@/packages/ui/src/TimezoneMismatchModal.vue';
import { api } from '@/packages/api/src';
vi.mock('@/packages/api/src', async (importOriginal) => ({
...(await importOriginal<typeof import('@/packages/api/src')>()),
api: {
updateUser: vi.fn(),
},
}));
vi.mock('@inertiajs/vue3', async (importOriginal) => ({
...(await importOriginal<typeof import('@inertiajs/vue3')>()),
usePage: () => ({
props: {
auth: {
user: { id: 'user-1' },
},
},
}),
}));
function mountModal() {
return shallowMount(UserTimezoneMismatchModal, {
props: { show: true },
global: {
plugins: [createPinia(), VueQueryPlugin],
},
});
}
describe('UserTimezoneMismatchModal', () => {
beforeEach(() => {
vi.mocked(api.updateUser).mockReset();
Object.defineProperty(window.location, 'reload', {
configurable: true,
value: vi.fn(),
});
});
it('saves the new timezone through the users API', async () => {
vi.mocked(api.updateUser).mockResolvedValue({
data: { id: 'user-1', timezone: 'Australia/Sydney' },
} as never);
const wrapper = mountModal();
wrapper.findComponent(TimezoneMismatchModal).vm.$emit('update', 'Australia/Sydney');
await flushPromises();
expect(api.updateUser).toHaveBeenCalledWith(
{ timezone: 'Australia/Sydney' },
{ params: { user: 'user-1' } }
);
expect(wrapper.findComponent(TimezoneMismatchModal).props('show')).toBe(false);
expect(window.location.reload).toHaveBeenCalled();
});
it('leaves the modal open when the update fails', async () => {
vi.mocked(api.updateUser).mockRejectedValue(new Error('nope'));
const wrapper = mountModal();
wrapper.findComponent(TimezoneMismatchModal).vm.$emit('update', 'Australia/Sydney');
await flushPromises();
expect(wrapper.findComponent(TimezoneMismatchModal).props('show')).toBe(true);
expect(window.location.reload).not.toHaveBeenCalled();
});
});

View File

@@ -1,11 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useForm, usePage } from '@inertiajs/vue3';
import { usePage } from '@inertiajs/vue3';
import type { User } from '@/types/models';
import TimezoneMismatchModal from '@/packages/ui/src/TimezoneMismatchModal.vue';
import { useUpdateUserMutation } from '@/utils/useUserQuery';
const show = defineModel('show', { default: false });
const saving = ref(false);
const page = usePage<{
auth: {
@@ -13,33 +12,28 @@ const page = usePage<{
};
}>();
function handleUpdate(timezone: string) {
saving.value = true;
const form = useForm({
_method: 'PUT',
timezone: timezone,
name: page.props.auth.user.name,
email: page.props.auth.user.email,
week_start: page.props.auth.user.week_start,
});
const updateUser = useUpdateUserMutation();
form.post(route('user-profile-information.update'), {
errorBag: 'updateProfileInformation',
preserveScroll: true,
onSuccess: () => {
saving.value = false;
show.value = false;
location.reload();
},
onError: () => {
saving.value = false;
},
});
async function handleUpdate(timezone: string) {
try {
await updateUser.mutateAsync({
userId: page.props.auth.user.id,
body: { timezone },
});
show.value = false;
// reload the whole page to re-read the timezone update
location.reload();
} catch {
// notification handled by mutation
}
}
</script>
<template>
<TimezoneMismatchModal v-model:show="show" :saving="saving" @update="handleUpdate" />
<TimezoneMismatchModal
v-model:show="show"
:saving="updateUser.isPending.value"
@update="handleUpdate" />
</template>
<style scoped></style>