/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
// Mock 'os' first.
import * as osActual from 'os';
vi.mock('os', async (importOriginal) => {
    const actualOs = await importOriginal();
    return {
        ...actualOs,
        homedir: vi.fn(() => '/mock/home/user'),
        platform: vi.fn(() => 'linux'),
    };
});
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
import * as fs from 'fs';
import stripJsonComments from 'strip-json-comments';
import * as path from 'path';
import { loadTrustedFolders, USER_TRUSTED_FOLDERS_PATH, TrustLevel, isWorkspaceTrusted, } from './trustedFolders.js';
vi.mock('fs', async (importOriginal) => {
    const actualFs = await importOriginal();
    return {
        ...actualFs,
        existsSync: vi.fn(),
        readFileSync: vi.fn(),
        writeFileSync: vi.fn(),
        mkdirSync: vi.fn(),
    };
});
vi.mock('strip-json-comments', () => ({
    default: vi.fn((content) => content),
}));
describe('Trusted Folders Loading', () => {
    let mockFsExistsSync;
    let mockStripJsonComments;
    let mockFsWriteFileSync;
    beforeEach(() => {
        vi.resetAllMocks();
        mockFsExistsSync = vi.mocked(fs.existsSync);
        mockStripJsonComments = vi.mocked(stripJsonComments);
        mockFsWriteFileSync = vi.mocked(fs.writeFileSync);
        vi.mocked(osActual.homedir).mockReturnValue('/mock/home/user');
        mockStripJsonComments.mockImplementation((jsonString) => jsonString);
        mockFsExistsSync.mockReturnValue(false);
        fs.readFileSync.mockReturnValue('{}');
    });
    afterEach(() => {
        vi.restoreAllMocks();
    });
    it('should load empty rules if no files exist', () => {
        const { rules, errors } = loadTrustedFolders();
        expect(rules).toEqual([]);
        expect(errors).toEqual([]);
    });
    describe('isPathTrusted', () => {
        function setup({ config = {} } = {}) {
            mockFsExistsSync.mockImplementation((p) => p === USER_TRUSTED_FOLDERS_PATH);
            fs.readFileSync.mockImplementation((p) => {
                if (p === USER_TRUSTED_FOLDERS_PATH)
                    return JSON.stringify(config);
                return '{}';
            });
            const folders = loadTrustedFolders();
            return { folders };
        }
        it('provides a method to determine if a path is trusted', () => {
            const { folders } = setup({
                config: {
                    './myfolder': TrustLevel.TRUST_FOLDER,
                    '/trustedparent/trustme': TrustLevel.TRUST_PARENT,
                    '/user/folder': TrustLevel.TRUST_FOLDER,
                    '/secret': TrustLevel.DO_NOT_TRUST,
                    '/secret/publickeys': TrustLevel.TRUST_FOLDER,
                },
            });
            expect(folders.isPathTrusted('/secret')).toBe(false);
            expect(folders.isPathTrusted('/user/folder')).toBe(true);
            expect(folders.isPathTrusted('/secret/publickeys/public.pem')).toBe(true);
            expect(folders.isPathTrusted('/user/folder/harhar')).toBe(true);
            expect(folders.isPathTrusted('myfolder/somefile.jpg')).toBe(true);
            expect(folders.isPathTrusted('/trustedparent/someotherfolder')).toBe(true);
            expect(folders.isPathTrusted('/trustedparent/trustme')).toBe(true);
            // No explicit rule covers this file
            expect(folders.isPathTrusted('/secret/bankaccounts.json')).toBe(undefined);
            expect(folders.isPathTrusted('/secret/mine/privatekey.pem')).toBe(undefined);
            expect(folders.isPathTrusted('/user/someotherfolder')).toBe(undefined);
        });
    });
    it('should load user rules if only user file exists', () => {
        const userPath = USER_TRUSTED_FOLDERS_PATH;
        mockFsExistsSync.mockImplementation((p) => p === userPath);
        const userContent = {
            '/user/folder': TrustLevel.TRUST_FOLDER,
        };
        fs.readFileSync.mockImplementation((p) => {
            if (p === userPath)
                return JSON.stringify(userContent);
            return '{}';
        });
        const { rules, errors } = loadTrustedFolders();
        expect(rules).toEqual([
            { path: '/user/folder', trustLevel: TrustLevel.TRUST_FOLDER },
        ]);
        expect(errors).toEqual([]);
    });
    it('should handle JSON parsing errors gracefully', () => {
        const userPath = USER_TRUSTED_FOLDERS_PATH;
        mockFsExistsSync.mockImplementation((p) => p === userPath);
        fs.readFileSync.mockImplementation((p) => {
            if (p === userPath)
                return 'invalid json';
            return '{}';
        });
        const { rules, errors } = loadTrustedFolders();
        expect(rules).toEqual([]);
        expect(errors.length).toBe(1);
        expect(errors[0].path).toBe(userPath);
        expect(errors[0].message).toContain('Unexpected token');
    });
    it('setValue should update the user config and save it', () => {
        const loadedFolders = loadTrustedFolders();
        loadedFolders.setValue('/new/path', TrustLevel.TRUST_FOLDER);
        expect(loadedFolders.user.config['/new/path']).toBe(TrustLevel.TRUST_FOLDER);
        expect(mockFsWriteFileSync).toHaveBeenCalledWith(USER_TRUSTED_FOLDERS_PATH, JSON.stringify({ '/new/path': TrustLevel.TRUST_FOLDER }, null, 2), { encoding: 'utf-8', mode: 0o600 });
    });
});
describe('isWorkspaceTrusted', () => {
    let mockCwd;
    const mockRules = {};
    const mockSettings = {
        folderTrust: true,
    };
    beforeEach(() => {
        vi.spyOn(process, 'cwd').mockImplementation(() => mockCwd);
        vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
            if (p === USER_TRUSTED_FOLDERS_PATH) {
                return JSON.stringify(mockRules);
            }
            return '{}';
        });
        vi.spyOn(fs, 'existsSync').mockImplementation((p) => p === USER_TRUSTED_FOLDERS_PATH);
    });
    afterEach(() => {
        vi.restoreAllMocks();
        // Clear the object
        Object.keys(mockRules).forEach((key) => delete mockRules[key]);
    });
    it('should return true for a directly trusted folder', () => {
        mockCwd = '/home/user/projectA';
        mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should return true for a child of a trusted folder', () => {
        mockCwd = '/home/user/projectA/src';
        mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should return true for a child of a trusted parent folder', () => {
        mockCwd = '/home/user/projectB';
        mockRules['/home/user/projectB/somefile.txt'] = TrustLevel.TRUST_PARENT;
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should return false for a directly untrusted folder', () => {
        mockCwd = '/home/user/untrusted';
        mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
        expect(isWorkspaceTrusted(mockSettings)).toBe(false);
    });
    it('should return undefined for a child of an untrusted folder', () => {
        mockCwd = '/home/user/untrusted/src';
        mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
        expect(isWorkspaceTrusted(mockSettings)).toBeUndefined();
    });
    it('should return undefined when no rules match', () => {
        mockCwd = '/home/user/other';
        mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
        mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
        expect(isWorkspaceTrusted(mockSettings)).toBeUndefined();
    });
    it('should prioritize trust over distrust', () => {
        mockCwd = '/home/user/projectA/untrusted';
        mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
        mockRules['/home/user/projectA/untrusted'] = TrustLevel.DO_NOT_TRUST;
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should handle path normalization', () => {
        mockCwd = '/home/user/projectA';
        mockRules[`/home/user/../user/${path.basename('/home/user/projectA')}`] =
            TrustLevel.TRUST_FOLDER;
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
});
import { getIdeTrust } from '@vybestack/llxprt-code-core';
vi.mock('@vybestack/llxprt-code-core', async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        getIdeTrust: vi.fn(),
    };
});
describe('isWorkspaceTrusted with IDE override', () => {
    const mockSettings = {
        folderTrust: true,
    };
    it('should return true when ideTrust is true, ignoring config', () => {
        vi.mocked(getIdeTrust).mockReturnValue(true);
        // Even if config says don't trust, ideTrust should win.
        vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({ [process.cwd()]: TrustLevel.DO_NOT_TRUST }));
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should return false when ideTrust is false, ignoring config', () => {
        vi.mocked(getIdeTrust).mockReturnValue(false);
        // Even if config says trust, ideTrust should win.
        vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({ [process.cwd()]: TrustLevel.TRUST_FOLDER }));
        expect(isWorkspaceTrusted(mockSettings)).toBe(false);
    });
    it('should fall back to config when ideTrust is undefined', () => {
        vi.mocked(getIdeTrust).mockReturnValue(undefined);
        vi.spyOn(fs, 'existsSync').mockReturnValue(true);
        vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({ [process.cwd()]: TrustLevel.TRUST_FOLDER }));
        expect(isWorkspaceTrusted(mockSettings)).toBe(true);
    });
    it('should always return true if folderTrust setting is disabled', () => {
        const settings = {
            folderTrust: false,
        };
        vi.mocked(getIdeTrust).mockReturnValue(false);
        expect(isWorkspaceTrusted(settings)).toBe(true);
    });
});
//# sourceMappingURL=trustedFolders.test.js.map