Skip to content

Commit e18a8db

Browse files
odzhychkobackportbot[bot]
authored andcommitted
fix(settings): display birthday correctly regardless of browsers timezone
fix(settings): display birthday correctly regardless of browsers timezone This also avoid shifting dates after user input. Resolves #49828 Signed-off-by: Oleksandr Dzhychko <hey@oleks.dev> [skip ci]
1 parent a14f248 commit e18a8db

2 files changed

Lines changed: 63 additions & 7 deletions

File tree

apps/settings/src/components/PersonalInfo/BirthdaySection.spec.js

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,17 @@ vi.mock('../../service/PersonalInfo/PersonalInfoService.js', () => ({
2626
savePrimaryAccountProperty,
2727
}))
2828

29+
async function mountBirthdaySection() {
30+
const BirthdaySection = await import('./BirthdaySection.vue')
31+
return mount(BirthdaySection.default, {
32+
mocks: {
33+
t: (_app, text) => text,
34+
},
35+
})
36+
}
37+
2938
afterEach(() => {
39+
vi.unstubAllEnvs()
3040
personalInfoParameters = undefined
3141
vi.resetModules()
3242
})
@@ -42,12 +52,45 @@ describe('BirthdaySection', () => {
4252
savePrimaryAccountProperty.mockReturnValue(Promise.resolve({
4353
ocs: { meta: { status: 'ok' } },
4454
}))
45-
const BirthdaySection = await import('./BirthdaySection.vue')
46-
const wrapper = mount(BirthdaySection.default, {
47-
mocks: {
48-
t: (_app, text) => text,
55+
const wrapper = await mountBirthdaySection()
56+
57+
const input = wrapper.find('input')
58+
await input.setValue('1987-12-01')
59+
60+
await expect.poll(() => savePrimaryAccountProperty.mock.calls.length).toBe(1)
61+
expect(savePrimaryAccountProperty).toHaveBeenCalledWith(
62+
'birthdate',
63+
'1987-12-01T00:00:00.000Z',
64+
)
65+
expect(input.element.value).toBe('1987-12-01')
66+
})
67+
68+
it('displays value when browser timezone is set', async () => {
69+
vi.stubEnv('TZ', 'US/Pacific')
70+
personalInfoParameters = {
71+
birthdate: {
72+
name: 'birthdate',
73+
value: '1987-12-15T00:00:00.000Z',
4974
},
50-
})
75+
}
76+
77+
const wrapper = await mountBirthdaySection()
78+
79+
expect(wrapper.find('input').element.value).toBe('1987-12-15')
80+
})
81+
82+
it('saves value when browser timezone is set', async () => {
83+
vi.stubEnv('TZ', 'US/Pacific')
84+
personalInfoParameters = {
85+
birthdate: {
86+
name: 'birthdate',
87+
value: null,
88+
},
89+
}
90+
savePrimaryAccountProperty.mockReturnValue(Promise.resolve({
91+
ocs: { meta: { status: 'ok' } },
92+
}))
93+
const wrapper = await mountBirthdaySection()
5194

5295
const input = wrapper.find('input')
5396
await input.setValue('1987-12-01')

apps/settings/src/components/PersonalInfo/BirthdaySection.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ import HeaderBar from './shared/HeaderBar.vue'
3333
3434
const { birthdate } = loadState('settings', 'personalInfoParameters', {})
3535
36+
/**
37+
* Convert a birthdate string value into a Date.
38+
*
39+
* @param {string } birthdateValue - e.g. "1987-12-01" or "1987-12-01T00:00:00.000Z"
40+
* @return {Date}
41+
*/
42+
function birthdateValueToDate(birthdateValue) {
43+
return new Date(birthdateValue)
44+
}
45+
3646
export default {
3747
name: 'BirthdaySection',
3848
@@ -44,7 +54,7 @@ export default {
4454
data() {
4555
let initialValue = null
4656
if (birthdate.value) {
47-
initialValue = new Date(birthdate.value)
57+
initialValue = birthdateValueToDate(birthdate.value)
4858
}
4959
5060
return {
@@ -76,7 +86,10 @@ export default {
7686
7787
methods: {
7888
onInput(e) {
79-
this.value = e
89+
const day = e.getDate().toString().padStart(2, '0')
90+
const month = (e.getMonth() + 1).toString().padStart(2, '0')
91+
const year = e.getFullYear()
92+
this.birthdate.value = `${year}-${month}-${day}`
8093
this.debouncePropertyChange(this.value)
8194
},
8295

0 commit comments

Comments
 (0)