"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const scopes_1 = require("./scopes");
describe('scope dependency graph helpers', () => {
    describe('getScopeAncestors', () => {
        it('returns direct and transitive dependencies for a scope', () => {
            expect((0, scopes_1.getScopeAncestors)('manage:Dashboard')).toEqual([
                'view:Project',
                'view:SavedChart',
                'view:Space',
            ]);
        });
        it('ignores unknown scopes', () => {
            expect((0, scopes_1.getScopeAncestors)('not:aScope')).toEqual([]);
            expect((0, scopes_1.getScopeAncestors)('not-a-scope')).toEqual([]);
        });
        it('normalizes scope names before traversing dependencies', () => {
            expect((0, scopes_1.getScopeAncestors)('manage:dashboard')).toEqual([
                'view:Project',
                'view:SavedChart',
                'view:Space',
            ]);
        });
        it('does not return the input scope when the graph cycles back to it', () => {
            const ancestors = (0, scopes_1.getScopeAncestors)('manage:CompileProject');
            expect(ancestors).toContain('create:Job');
            expect(ancestors).not.toContain('manage:CompileProject');
        });
    });
    describe('getScopeDescendants', () => {
        it('returns direct and transitive dependents for a scope', () => {
            const descendants = (0, scopes_1.getScopeDescendants)('view:SavedChart');
            expect(descendants).toEqual(expect.arrayContaining([
                'view:Dashboard',
                'manage:Dashboard',
                'manage:Dashboard@space',
                'manage:Dashboard@self',
            ]));
            expect(descendants).not.toContain('view:SavedChart');
        });
        it('ignores unknown scopes', () => {
            expect((0, scopes_1.getScopeDescendants)('not:aScope')).toEqual([]);
            expect((0, scopes_1.getScopeDescendants)('not-a-scope')).toEqual([]);
        });
        it('does not return the input scope when the graph cycles back to it', () => {
            const descendants = (0, scopes_1.getScopeDescendants)('create:Job');
            expect(descendants).toContain('manage:CompileProject');
            expect(descendants).not.toContain('create:Job');
        });
    });
    it('can traverse ancestors for every scope without looping forever', () => {
        (0, scopes_1.getScopes)({ isEnterprise: true }).forEach((scope) => {
            expect((0, scopes_1.getScopeAncestors)(scope.name, { isEnterprise: true })).not.toContain(scope.name);
        });
    });
    describe('getScopeSubstitutes', () => {
        it('returns stronger scope variations that can replace a view requirement', () => {
            expect((0, scopes_1.getScopeSubstitutes)('view:Dashboard')).toEqual([
                'manage:Dashboard',
                'manage:Dashboard@space',
                'manage:Dashboard@self',
            ]);
        });
        it('does not treat promote as a substitute for view or manage', () => {
            expect((0, scopes_1.getScopeSubstitutes)('view:Dashboard')).not.toContain('promote:Dashboard');
            expect((0, scopes_1.getScopeSubstitutes)('manage:Dashboard@space')).not.toContain('promote:Dashboard@space');
        });
        it('returns broader same-action variants that can replace a scoped requirement', () => {
            expect((0, scopes_1.getScopeSubstitutes)('manage:Dashboard@space')).toContain('manage:Dashboard');
            expect((0, scopes_1.getScopeSubstitutes)('view:DataApp@self', {
                isEnterprise: true,
            })).toContain('view:DataApp');
        });
        it('does not return weaker or narrower scopes as substitutes', () => {
            expect((0, scopes_1.getScopeSubstitutes)('manage:Dashboard')).not.toContain('view:Dashboard');
            expect((0, scopes_1.getScopeSubstitutes)('manage:Dashboard')).not.toContain('manage:Dashboard@space');
        });
        it('returns manage as a substitute for granular create and delete scopes', () => {
            expect((0, scopes_1.getScopeSubstitutes)('create:VirtualView')).toEqual([
                'manage:VirtualView',
            ]);
            expect((0, scopes_1.getScopeSubstitutes)('delete:VirtualView')).toEqual([
                'manage:VirtualView',
            ]);
        });
        it('returns stronger scoped variants for a scoped view requirement', () => {
            expect((0, scopes_1.getScopeSubstitutes)('view:DataApp@self', {
                isEnterprise: true,
            })).toContain('manage:DataApp@self');
        });
        it('ignores unknown scopes', () => {
            expect((0, scopes_1.getScopeSubstitutes)('not:aScope')).toEqual([]);
            expect((0, scopes_1.getScopeSubstitutes)('not-a-scope')).toEqual([]);
        });
        it('normalizes scope names before finding substitutes', () => {
            expect((0, scopes_1.getScopeSubstitutes)('view:dashboard')).toEqual([
                'manage:Dashboard',
                'manage:Dashboard@space',
                'manage:Dashboard@self',
            ]);
        });
    });
    describe('getUnsatisfiedScopeDependencies', () => {
        it('returns missing dependencies for a new scope', () => {
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['view:Project', 'view:SavedChart'], 'manage:Dashboard')).toEqual(['view:Space']);
        });
        it('treats substitute scopes as satisfying dependencies', () => {
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['view:Project', 'manage:SavedChart', 'view:Space'], 'manage:Dashboard')).toEqual([]);
        });
        it('includes transitive dependencies', () => {
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['view:Project', 'manage:SavedChart@space'], 'manage:CustomFields')).toEqual(['view:Space', 'manage:Explore']);
        });
        it('ignores unknown existing scopes and unknown new scopes', () => {
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['not:aScope', 'view:Project'], 'view:SavedChart')).toEqual([]);
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['view:Project'], 'not:aScope')).toEqual([]);
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['not-a-scope', 'view:Project'], 'not-a-scope')).toEqual([]);
        });
        it('normalizes existing and new scope names before checking dependencies', () => {
            expect((0, scopes_1.getUnsatisfiedScopeDependencies)(['view:project', 'manage:saved_chart', 'view:space'], 'manage:dashboard')).toEqual([]);
        });
    });
});
//# sourceMappingURL=scopes.test.js.map