Skip to content

Commit fe50d1b

Browse files
test(Sign): cover lifecycle and envelope regressions
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 494d4f4 commit fe50d1b

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

src/tests/views/SignPDF/Sign.spec.ts

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,36 @@ const createSignDocument = (overrides: Partial<SignDocument> = {}): SignDocument
106106
...overrides,
107107
})
108108

109+
const createSignMountOptions = () => ({
110+
global: {
111+
stubs: {
112+
NcButton: true,
113+
NcDialog: true,
114+
NcLoadingIcon: true,
115+
TokenManager: true,
116+
EmailManager: true,
117+
UploadCertificate: true,
118+
Documents: true,
119+
Signatures: true,
120+
Draw: true,
121+
ManagePassword: true,
122+
CreatePassword: true,
123+
NcNoteCard: true,
124+
NcPasswordField: true,
125+
NcRichText: true,
126+
},
127+
mocks: {
128+
$watch: vi.fn(),
129+
$nextTick: vi.fn(),
130+
},
131+
},
132+
})
133+
134+
const mountRealSignComponent = async () => {
135+
const SignComponent = await import('../../../views/SignPDF/_partials/Sign.vue')
136+
return mount(SignComponent.default, createSignMountOptions())
137+
}
138+
109139
// Global mock for axios - prevents unhandled rejections during component mounting
110140
vi.mock('@nextcloud/axios', () => {
111141
const axiosInstanceMock = Object.assign(vi.fn().mockResolvedValue({
@@ -468,6 +498,113 @@ describe('Sign.vue - signWithTokenCode', () => {
468498
})
469499
})
470500

501+
describe('Sign.vue - lifecycle regressions', () => {
502+
it('consumes pendingAction on mount and opens the matching signing modal', async () => {
503+
setActivePinia(createPinia())
504+
505+
const { useSignStore } = await import('../../../store/sign.js')
506+
const signStore = useSignStore()
507+
const signMethodsStore = useSignMethodsStore()
508+
509+
signStore.document = createSignDocument({
510+
status: FILE_STATUS.ABLE_TO_SIGN,
511+
signers: [{ me: true, status: SIGN_REQUEST_STATUS.ABLE_TO_SIGN, signRequestId: 501, sign_request_uuid: 'pending-action-uuid' }],
512+
})
513+
signStore.queueAction('sign')
514+
signMethodsStore.settings = {
515+
clickToSign: {},
516+
}
517+
518+
await mountRealSignComponent()
519+
await flushPromises()
520+
521+
expect(signMethodsStore.modal.clickToSign).toBe(true)
522+
expect(signStore.pendingAction).toBe(null)
523+
})
524+
525+
it('emits signing-started on mount when document is already signing in progress', async () => {
526+
setActivePinia(createPinia())
527+
528+
const { useSignStore } = await import('../../../store/sign.js')
529+
const signStore = useSignStore()
530+
531+
signStore.document = createSignDocument({
532+
status: FILE_STATUS.SIGNING_IN_PROGRESS,
533+
signers: [{ me: true, signRequestId: 501, sign_request_uuid: 'progress-uuid' }],
534+
})
535+
536+
const wrapper = await mountRealSignComponent()
537+
await flushPromises()
538+
539+
expect(wrapper.emitted('signing-started')).toEqual([
540+
[{ signRequestUuid: 'progress-uuid', async: true }],
541+
])
542+
})
543+
544+
it('resets modal and local signing state when signRequestUuid changes', async () => {
545+
setActivePinia(createPinia())
546+
547+
const { useSignStore } = await import('../../../store/sign.js')
548+
const signStore = useSignStore()
549+
const signMethodsStore = useSignMethodsStore()
550+
551+
signStore.document = createSignDocument({
552+
signers: [{ me: true, signRequestId: 501, sign_request_uuid: 'uuid-before' }],
553+
})
554+
555+
const wrapper = await mountRealSignComponent()
556+
const signVm = wrapper.vm as typeof wrapper.vm & {
557+
showManagePassword: boolean
558+
signPassword: string
559+
}
560+
signMethodsStore.showModal('password')
561+
signMethodsStore.showModal('token')
562+
signStore.setSigningErrors([{ message: 'existing error', code: 422 }])
563+
signVm.showManagePassword = true
564+
signVm.signPassword = '123456'
565+
566+
signStore.document = createSignDocument({
567+
signers: [{ me: true, signRequestId: 502, sign_request_uuid: 'uuid-after' }],
568+
})
569+
570+
await wrapper.vm.$nextTick()
571+
await flushPromises()
572+
573+
expect(signMethodsStore.modal.password).toBe(false)
574+
expect(signMethodsStore.modal.token).toBe(false)
575+
expect(signStore.errors).toEqual([])
576+
expect(signVm.showManagePassword).toBe(false)
577+
expect(signVm.signPassword).toBe('')
578+
})
579+
580+
it('cleans modal and signing errors on unmount', async () => {
581+
setActivePinia(createPinia())
582+
583+
const { useSignStore } = await import('../../../store/sign.js')
584+
const signStore = useSignStore()
585+
const signMethodsStore = useSignMethodsStore()
586+
587+
signStore.document = createSignDocument({
588+
signers: [{ me: true, signRequestId: 501, sign_request_uuid: 'cleanup-uuid' }],
589+
})
590+
591+
const wrapper = await mountRealSignComponent()
592+
signMethodsStore.showModal('password')
593+
signMethodsStore.showModal('createSignature')
594+
signMethodsStore.settings = {
595+
password: { hasSignatureFile: true },
596+
}
597+
signStore.setSigningErrors([{ message: 'existing error', code: 422 }])
598+
599+
wrapper.unmount()
600+
601+
expect(signMethodsStore.modal.password).toBe(false)
602+
expect(signMethodsStore.modal.createSignature).toBe(false)
603+
expect(signMethodsStore.settings).toEqual({})
604+
expect(signStore.errors).toEqual([])
605+
})
606+
})
607+
471608
describe('Sign.vue - API error handling', () => {
472609
it('emits signed when envelope submit has mixed results and the final result is signed', async () => {
473610
const context = {
@@ -1790,4 +1927,61 @@ describe('Sign.vue - signWithTokenCode', () => {
17901927
{ documentId: 1 },
17911928
)
17921929
})
1930+
1931+
it('submits each envelope file when current signer uuids only exist in child files', async () => {
1932+
const storeSubmitMock = vi.fn().mockResolvedValue({ status: 'signed', data: {} })
1933+
1934+
const context = {
1935+
loading: false,
1936+
elements: [
1937+
{ elementId: 100, signRequestId: 10, type: 'signature' },
1938+
{ elementId: 200, signRequestId: 20, type: 'signature' },
1939+
],
1940+
canCreateSignature: false,
1941+
signRequestUuid: 'fallback-envelope-uuid',
1942+
signatureElementsStore: { signs: {} },
1943+
actionHandler: { showModal: vi.fn(), closeModal: vi.fn() },
1944+
signMethodsStore: { certificateEngine: 'openssl' },
1945+
signStore: {
1946+
document: {
1947+
id: 1,
1948+
nodeType: 'envelope',
1949+
signers: [],
1950+
files: [
1951+
{
1952+
signers: [
1953+
{ signRequestId: 10, me: true, sign_request_uuid: 'uuid-file-1' },
1954+
],
1955+
},
1956+
{
1957+
signers: [
1958+
{ signRequestId: 20, me: true, sign_request_uuid: 'uuid-file-2' },
1959+
],
1960+
},
1961+
],
1962+
},
1963+
clearSigningErrors: vi.fn(),
1964+
setSigningErrors: vi.fn(),
1965+
submitSignature: storeSubmitMock,
1966+
},
1967+
$emit: vi.fn(),
1968+
sidebarStore: { hideSidebar: vi.fn() },
1969+
}
1970+
1971+
await submitSignatureCompatMethod.call(context, { method: 'clickToSign' })
1972+
1973+
expect(storeSubmitMock).toHaveBeenCalledTimes(2)
1974+
expect(storeSubmitMock).toHaveBeenNthCalledWith(
1975+
1,
1976+
{ method: 'clickToSign', elements: [{ documentElementId: 100 }] },
1977+
'uuid-file-1',
1978+
{ documentId: 1 },
1979+
)
1980+
expect(storeSubmitMock).toHaveBeenNthCalledWith(
1981+
2,
1982+
{ method: 'clickToSign', elements: [{ documentElementId: 200 }] },
1983+
'uuid-file-2',
1984+
{ documentId: 1 },
1985+
)
1986+
})
17931987
})

0 commit comments

Comments
 (0)