import { vi, describe, expect, it, beforeAll, afterAll } from 'vitest';
import { axios, flushPromises } from 'app/test/vitest/helper';
import { useAcl } from 'src/composables/useAcl';

describe('useAcl', () => {
    const acl = useAcl();
    const mockAcls = [
        {
            model: 'Address',
            property: '*',
            accessType: '*',
            permission: 'ALLOW',
            principalType: 'ROLE',
            principalId: 'employee',
        },
        {
            model: 'Worker',
            property: 'holidays',
            accessType: 'READ',
            permission: 'ALLOW',
            principalType: 'ROLE',
            principalId: 'employee',
        },
        {
            model: 'Url',
            property: 'getByUser',
            accessType: 'READ',
            permission: 'ALLOW',
            principalType: 'ROLE',
            principalId: '$everyone',
        },
        {
            model: 'TpvTransaction',
            property: 'start',
            accessType: 'WRITE',
            permission: 'ALLOW',
            principalType: 'ROLE',
            principalId: '$authenticated',
        },
    ];

    beforeAll(async () => {
        vi.spyOn(axios, 'get').mockResolvedValue({ data: mockAcls });
        await acl.fetch();
    });

    afterAll(async () => await flushPromises());

    describe('hasAny', () => {
        it('should return false if no roles matched', async () => {
            expect(
                acl.hasAny([
                    { model: 'Worker', props: 'updateAttributes', accessType: 'WRITE' },
                ])
            ).toBeFalsy();
        });

        it('should return false if no roles matched', async () => {
            expect(
                acl.hasAny([{ model: 'Worker', props: 'holidays', accessType: 'READ' }])
            ).toBeTruthy();
        });

        describe('*', () => {
            it('should return true if an acl matched', async () => {
                expect(
                    acl.hasAny([{ model: 'Address', props: '*', accessType: 'WRITE' }])
                ).toBeTruthy();
            });

            it('should return false if no acls matched', async () => {
                expect(
                    acl.hasAny([{ model: 'Worker', props: '*', accessType: 'READ' }])
                ).toBeFalsy();
            });
        });

        describe('$authenticated', () => {
            it('should return false if no acls matched', async () => {
                expect(
                    acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: '*' }])
                ).toBeFalsy();
            });

            it('should return true if an acl matched', async () => {
                expect(
                    acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: 'READ' }])
                ).toBeTruthy();
            });
        });

        describe('$everyone', () => {
            it('should return false if no acls matched', async () => {
                expect(
                    acl.hasAny([
                        { model: 'TpvTransaction', props: 'start', accessType: 'READ' },
                    ])
                ).toBeFalsy();
            });

            it('should return false if an acl matched', async () => {
                expect(
                    acl.hasAny([
                        { model: 'TpvTransaction', props: 'start', accessType: 'WRITE' },
                    ])
                ).toBeTruthy();
            });
        });
    });
});