-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Expand file tree
/
Copy pathEditUserDialog.spec.ts
More file actions
126 lines (103 loc) · 3.89 KB
/
Copy pathEditUserDialog.spec.ts
File metadata and controls
126 lines (103 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { mount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
const confirmPassword = vi.hoisted(() => vi.fn())
vi.mock('@nextcloud/password-confirmation', () => ({ confirmPassword }))
vi.mock('@nextcloud/dialogs', () => ({ showError: vi.fn(), showSuccess: vi.fn() }))
// Decouple the dialog test from form-data diffing internals: always report a
// non-empty change set so save() proceeds past its early return. Other exports
// (used transitively by the form sub-components) are kept real.
vi.mock('./userFormUtils.ts', async (importActual) => ({
...(await importActual()),
userToFormData: () => ({
username: 'bob',
displayName: 'Bob',
password: '',
email: '',
groups: [],
subadminGroups: [],
quota: { id: 'default' },
language: { code: 'en' },
manager: { id: '' },
}),
diffPayload: () => ({ displayName: 'Bobby' }),
}))
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import EditUserDialog from './EditUserDialog.vue'
import { flushPromises, NcButtonStub, NcDialogStub, UserFormFieldsStub } from './dialogTestHelpers.ts'
function mountDialog({ dispatch = vi.fn() } = {}) {
return mount(EditUserDialog, {
propsData: {
user: { id: 'bob', backendCapabilities: { setPassword: true } },
quotaOptions: [],
},
mocks: {
t: (_app: string, text: string) => text,
$store: {
dispatch,
getters: {
getGroups: [],
getServerData: { languages: [], canChangePassword: true },
getPasswordPolicyMinLength: 8,
},
},
},
stubs: {
NcDialog: NcDialogStub,
NcButton: NcButtonStub,
UserFormFields: UserFormFieldsStub,
},
})
}
describe('EditUserDialog loading feedback', () => {
beforeEach(() => {
vi.clearAllMocks()
confirmPassword.mockResolvedValue(undefined)
})
it('does not dispatch a second save request while one is in flight', async () => {
const dispatch = vi.fn().mockReturnValue(new Promise(() => {}))
const wrapper = mountDialog({ dispatch })
await wrapper.find('form').trigger('submit')
await flushPromises()
await wrapper.find('form').trigger('submit')
await flushPromises()
const saveCalls = dispatch.mock.calls.filter(([action]) => action === 'editUserMultiField')
expect(saveCalls).toHaveLength(1)
})
it('marks the form as busy and inert while saving', async () => {
confirmPassword.mockReturnValue(new Promise(() => {}))
const wrapper = mountDialog()
await wrapper.find('form').trigger('submit')
const form = wrapper.find('form')
expect(form.attributes('aria-busy')).toBe('true')
expect(form.attributes('inert')).toBeDefined()
})
it('shows a spinner and busy label on the submit button while saving', async () => {
confirmPassword.mockReturnValue(new Promise(() => {}))
const wrapper = mountDialog()
await wrapper.find('form').trigger('submit')
expect(wrapper.findComponent(NcLoadingIcon).exists()).toBe(true)
expect(wrapper.find('[data-test="submit"]').text()).toContain('Saving')
})
it('sets aria-disabled (not disabled) on the submit button while saving', async () => {
confirmPassword.mockReturnValue(new Promise(() => {}))
const wrapper = mountDialog()
const submit = wrapper.find('[data-test="submit"]')
expect(submit.attributes('aria-disabled')).toBe('false')
expect(submit.attributes('disabled')).toBeUndefined()
await wrapper.find('form').trigger('submit')
expect(submit.attributes('aria-disabled')).toBe('true')
expect(submit.attributes('disabled')).toBeUndefined()
})
it('prevents closing the dialog while saving', async () => {
confirmPassword.mockReturnValue(new Promise(() => {}))
const wrapper = mountDialog()
const dialog = wrapper.findComponent(NcDialogStub)
expect(dialog.props('noClose')).toBe(false)
await wrapper.find('form').trigger('submit')
expect(dialog.props('noClose')).toBe(true)
})
})