Skip to content

Commit 619f3c3

Browse files
committed
refactor(settings): switch wipe dialog to confirm
Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
1 parent 6f3b6ca commit 619f3c3

3 files changed

Lines changed: 28 additions & 83 deletions

File tree

apps/settings/src/components/AuthToken.spec.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ vi.hoisted(() => {
1616

1717
import type { IToken } from '../store/authtoken.ts'
1818

19+
// Mock @nextcloud/dialogs so the wipe action's showConfirmation call resolves
20+
// synchronously in tests. Hoisted so it's installed before AuthToken.vue imports.
21+
const showConfirmationMock = vi.hoisted(() => vi.fn())
22+
vi.mock('@nextcloud/dialogs', () => ({
23+
showConfirmation: showConfirmationMock,
24+
}))
25+
1926
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
2027
import AuthToken from './AuthToken.vue'
2128
import AuthTokenDeleteDialog from './AuthTokenDeleteDialog.vue'
22-
import AuthTokenWipeDialog from './AuthTokenWipeDialog.vue'
2329
import { TokenType, useAuthTokenStore } from '../store/authtoken.ts'
2430
import { detect } from '../utils/userAgentDetect.ts'
2531

@@ -143,33 +149,27 @@ describe('AuthToken wipe flow', () => {
143149
vi.clearAllMocks()
144150
})
145151

146-
it('does not call wipeToken when the wipe action is triggered (dialog opens first)', async () => {
152+
it('does not call wipeToken when the user rejects the confirmation', async () => {
153+
showConfirmationMock.mockResolvedValueOnce(false)
147154
const token = makeToken()
148155
const wrapper = mountAuthToken(token)
149156
const store = useAuthTokenStore()
150157

151-
;(wrapper.vm as unknown as { wipe: () => void }).wipe()
152-
await wrapper.vm.$nextTick()
158+
await (wrapper.vm as unknown as { wipe: () => Promise<void> }).wipe()
153159

154-
const dialog = wrapper.findComponent(AuthTokenWipeDialog)
155-
expect(dialog.exists()).toBe(true)
156-
expect(dialog.props('open')).toBe(true)
160+
expect(showConfirmationMock).toHaveBeenCalledTimes(1)
157161
expect(store.wipeToken).not.toHaveBeenCalled()
158162
})
159163

160-
it('calls wipeToken only after the dialog emits confirm', async () => {
164+
it('calls wipeToken when the user accepts the confirmation', async () => {
165+
showConfirmationMock.mockResolvedValueOnce(true)
161166
const token = makeToken()
162167
const wrapper = mountAuthToken(token)
163168
const store = useAuthTokenStore()
164169

165-
;(wrapper.vm as unknown as { wipe: () => void }).wipe()
166-
await wrapper.vm.$nextTick()
167-
168-
const dialog = wrapper.findComponent(AuthTokenWipeDialog)
169-
dialog.vm.$emit('confirm')
170-
dialog.vm.$emit('update:open', false)
171-
await wrapper.vm.$nextTick()
170+
await (wrapper.vm as unknown as { wipe: () => Promise<void> }).wipe()
172171

172+
expect(showConfirmationMock).toHaveBeenCalledTimes(1)
173173
expect(store.wipeToken).toHaveBeenCalledTimes(1)
174174
expect(store.wipeToken).toHaveBeenCalledWith(token)
175175
})

apps/settings/src/components/AuthToken.vue

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@
7878
:token="token"
7979
:open.sync="deleteDialogOpen"
8080
@confirm="confirmDelete" />
81-
<AuthTokenWipeDialog
82-
v-if="wipeDialogOpen"
83-
:token="token"
84-
:open.sync="wipeDialogOpen"
85-
@confirm="confirmWipe" />
8681
</tr>
8782
</template>
8883

@@ -91,6 +86,7 @@ import type { PropType } from 'vue'
9186
import type { IToken } from '../store/authtoken'
9287
9388
import { mdiCheck, mdiCellphone, mdiTablet, mdiMonitor, mdiWeb, mdiKeyOutline, mdiMicrosoftEdge, mdiFirefox, mdiGoogleChrome, mdiAppleSafari, mdiAndroid, mdiAppleIos } from '@mdi/js'
89+
import { showConfirmation } from '@nextcloud/dialogs'
9490
import { translate as t } from '@nextcloud/l10n'
9591
import { defineComponent } from 'vue'
9692
import { TokenType, useAuthTokenStore } from '../store/authtoken.ts'
@@ -103,7 +99,6 @@ import NcDateTime from '@nextcloud/vue/components/NcDateTime'
10399
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
104100
import NcTextField from '@nextcloud/vue/components/NcTextField'
105101
import AuthTokenDeleteDialog from './AuthTokenDeleteDialog.vue'
106-
import AuthTokenWipeDialog from './AuthTokenWipeDialog.vue'
107102
108103
// When using capture groups the following parts are extracted the first is used as the version number, the second as the OS
109104
const userAgentMap = {
@@ -156,7 +151,6 @@ export default defineComponent({
156151
name: 'AuthToken',
157152
components: {
158153
AuthTokenDeleteDialog,
159-
AuthTokenWipeDialog,
160154
NcActions,
161155
NcActionButton,
162156
NcActionCheckbox,
@@ -182,7 +176,6 @@ export default defineComponent({
182176
newName: '',
183177
oldName: '',
184178
deleteDialogOpen: false,
185-
wipeDialogOpen: false,
186179
mdiCheck,
187180
TokenType,
188181
}
@@ -321,13 +314,19 @@ export default defineComponent({
321314
this.renaming = false
322315
this.authTokenStore.renameToken(this.token, this.newName)
323316
},
324-
wipe() {
325-
this.actionOpen = false
326-
this.wipeDialogOpen = true
327-
},
328317
329-
confirmWipe() {
330-
this.authTokenStore.wipeToken(this.token)
318+
async wipe() {
319+
this.actionOpen = false
320+
const confirmed = await showConfirmation({
321+
name: t('settings', 'Confirm wipe'),
322+
text: t('settings', 'Do you really want to wipe your data from this device?'),
323+
labelConfirm: t('settings', 'Wipe device'),
324+
labelReject: t('settings', 'Cancel'),
325+
severity: 'warning',
326+
})
327+
if (confirmed) {
328+
this.authTokenStore.wipeToken(this.token)
329+
}
331330
},
332331
},
333332
})

apps/settings/src/components/AuthTokenWipeDialog.vue

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)