import type { FilePermissionView } from './filePermissionContext';
|
|
import { mount } from '@vue/test-utils';
|
import { defineComponent, h, provide, reactive } from 'vue';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { fieldFileAccess, filePermissionFormKey, useFilePermissionAccess } from './filePermissionContext';
|
|
const view = (): FilePermissionView => ({
|
enabled: true,
|
taskId: 'task',
|
formId: 'form',
|
status: 'ready',
|
revision: 'state',
|
fields: {
|
files: { status: 'ready', actions: { ADD: true, DOWNLOAD: true, EDIT: true, REMOVE: true, REPLACE: true, VIEW: true } },
|
'rows-files': { status: 'ready', actions: { DOWNLOAD: false, VIEW: true } },
|
},
|
});
|
describe('runtime file permission context', () => {
|
it('isolates the same field name in main and child forms', () => {
|
expect(fieldFileAccess(view(), 'form', 'files')?.actions?.DOWNLOAD).toBe(true);
|
expect(fieldFileAccess(view(), 'form', 'files', 'rows')?.actions?.DOWNLOAD).toBe(false);
|
expect(fieldFileAccess(view(), 'form', 'missing')?.status).toBe('error');
|
});
|
it('retains legacy behavior only for a valid legacy response or a non-workflow form', () => {
|
expect(fieldFileAccess(undefined, 'form', 'files')).toBeUndefined();
|
expect(fieldFileAccess({ ...view(), enabled: false }, 'form', 'files')).toBeUndefined();
|
expect(fieldFileAccess({ ...view(), enabled: false, status: 'error' }, 'form', 'files')?.status).toBe('error');
|
});
|
it('closes actions for incomplete or foreign responses', () => {
|
expect(fieldFileAccess(view(), 'other-form', 'files')?.status).toBe('error');
|
expect(fieldFileAccess({ ...view(), taskId: '' }, 'form', 'files')?.status).toBe('error');
|
expect(fieldFileAccess({ ...view(), revision: undefined }, 'form', 'files')?.status).toBe('error');
|
expect(fieldFileAccess({ ...view(), status: 'loading' }, 'form', 'files')?.status).toBe('loading');
|
});
|
it('cannot elevate runtime permission through component props and reacts to revocation', () => {
|
const state = reactive({ view: view() });
|
let access!: ReturnType<typeof useFilePermissionAccess>;
|
const child = defineComponent({
|
setup() {
|
access = useFilePermissionAccess({
|
editField: 'files',
|
editParentField: 'rows',
|
fileAccess: { status: 'ready', actions: { DOWNLOAD: true, VIEW: true } },
|
});
|
return () => h('div');
|
},
|
});
|
const wrapper = mount(
|
defineComponent({
|
setup() {
|
provide(filePermissionFormKey, () => ({ modelId: 'form', view: state.view }));
|
return () => h(child);
|
},
|
}),
|
);
|
expect(access.value?.actions?.DOWNLOAD).toBe(false);
|
expect(access.value?.actions?.VIEW).toBe(true);
|
state.view = { ...view(), status: 'error' };
|
expect(access.value?.status).toBe('error');
|
wrapper.unmount();
|
});
|
it('keeps configured download but closes mutation actions in list details', () => {
|
const state = reactive({ readOnly: true, view: view() });
|
let access!: ReturnType<typeof useFilePermissionAccess>;
|
const child = defineComponent({
|
setup() {
|
access = useFilePermissionAccess({ editField: 'files' });
|
return () => h('div');
|
},
|
});
|
const wrapper = mount(
|
defineComponent({
|
setup() {
|
provide(filePermissionFormKey, () => ({ modelId: 'form', readOnly: state.readOnly, view: state.view }));
|
return () => h(child);
|
},
|
}),
|
);
|
expect(access.value?.actions).toMatchObject({ ADD: false, DOWNLOAD: true, EDIT: false, REMOVE: false, REPLACE: false, VIEW: true });
|
state.view.fields!.files!.actions!.DOWNLOAD = false;
|
expect(access.value?.actions?.DOWNLOAD).toBe(false);
|
state.readOnly = false;
|
expect(access.value?.actions?.EDIT).toBe(true);
|
wrapper.unmount();
|
});
|
});
|