"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const file_api_1 = require("./file-api");
const Setting_1 = require("./models/Setting");
const SyncTargetRegistry_1 = require("./SyncTargetRegistry");
const defaultPaginatedList = () => {
    return {
        items: [],
        hasMore: false,
        context: null,
    };
};
const defaultItem = () => {
    return {
        id: '',
    };
};
const validNoteId = '1b175bb38bba47baac22b0b47f778113';
const basePath = '/';
const baseTimestamp = new Date().getTime();
const setupWebDavSync = (isLocal) => {
    let url = 'http://www.example.com';
    if (isLocal)
        url = 'http://localhost';
    Setting_1.default.setValue('sync.target', SyncTargetRegistry_1.default.nameToId('webdav'));
    Setting_1.default.setValue('sync.6.path', url);
};
const remotePath = (noteId) => {
    return `${noteId}.md`;
};
const statItem = (noteId, remoteUpdatedTime) => {
    const stat = {
        path: remotePath(noteId),
        updated_time: remoteUpdatedTime,
        isDir: false,
    };
    return stat;
};
const dirStatFunc = (statItem) => {
    return () => {
        if (statItem) {
            return [statItem];
        }
        else {
            return [];
        }
    };
};
const syncOptions = (noteId, localUpdatedTime, contextTimestamp = undefined, includeFilesAtTimestamp = true) => {
    const syncContextTimestamp = contextTimestamp ? contextTimestamp : localUpdatedTime;
    const metadataMap = new Map();
    let itemIds = [];
    let filesAtTimestamp = [];
    const metadata = {
        item_id: noteId,
        updated_time: localUpdatedTime,
    };
    if (noteId) {
        metadataMap.set(noteId, metadata);
        itemIds = [noteId];
    }
    if (includeFilesAtTimestamp) {
        filesAtTimestamp = [remotePath(noteId)];
    }
    const allItemIdsHandler = async () => {
        return itemIds;
    };
    const allItemMetadataHandler = async () => {
        return metadataMap;
    };
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
    const syncContext = {
        timestamp: syncContextTimestamp,
        filesAtTimestamp: filesAtTimestamp,
        statsCache: null,
        statIdsCache: null,
        deletedItemsProcessed: false,
    };
    return {
        allItemIdsHandler: allItemIdsHandler,
        allItemMetadataHandler: allItemMetadataHandler,
        wipeOutFailSafe: false,
        context: syncContext,
    };
};
describe('file-api', () => {
    test.each([
        [
            Object.assign(Object.assign({}, defaultPaginatedList()), { items: [] }),
            false,
        ],
        [
            Object.assign(Object.assign({}, defaultPaginatedList()), { items: [
                    Object.assign(Object.assign({}, defaultItem()), { path: 'test' }),
                ] }),
            false,
        ],
        [
            Object.assign(Object.assign({}, defaultPaginatedList()), { items: [
                    Object.assign(Object.assign({}, defaultItem()), { path: 'test', jopItem: null }),
                ] }),
            true,
        ],
        [
            Object.assign(Object.assign({}, defaultPaginatedList()), { items: [
                    Object.assign(Object.assign({}, defaultItem()), { path: 'test', jopItem: { something: 'abcd' } }),
                ] }),
            true,
        ],
    ])('should tell if the sync target supports delta with items', async (deltaResponse, expected) => {
        const actual = (0, file_api_1.getSupportsDeltaWithItems)(deltaResponse);
        expect(actual).toBe(expected);
    });
    it.each([
        'http://localhost',
        'http://localhost/',
        'https://localhost:8080',
        'http://127.0.0.1',
        'https://127.100.50.25:3000/test',
        'http://[::1]',
        'http://localhost/api/v1',
    ])('should detect a local server url', (url) => {
        const result = (0, file_api_1.isLocalServer)(url);
        expect(result).toBe(true);
    });
    it.each([
        'http://localhostXYZ',
        'http://127.0.0.1foobar',
        'http://192.168.1.1',
        'http://example.com',
        'https://my-localhost.com',
    ])('should detect a non local server url', (url) => {
        const result = (0, file_api_1.isLocalServer)(url);
        expect(result).toBe(false);
    });
    it('should use enhanced basic delta algorithm when using file system sync', () => {
        Setting_1.default.setValue('sync.target', SyncTargetRegistry_1.default.nameToId('filesystem'));
        const result = (0, file_api_1.enableEnhancedBasicDeltaAlgorithm)();
        expect(result).toBe(true);
    });
    it.each([
        'http://localhost',
        'http://localhost/',
        'https://localhost:8080',
        'http://127.0.0.1',
        'https://127.100.50.25:3000/test',
        'http://[::1]',
        'http://localhost/api/v1',
    ])('should use enhanced basic delta algorithm when using WebDAV for a local server url', (url) => {
        Setting_1.default.setValue('sync.target', SyncTargetRegistry_1.default.nameToId('webdav'));
        Setting_1.default.setValue('sync.6.path', url);
        const result = (0, file_api_1.enableEnhancedBasicDeltaAlgorithm)();
        expect(result).toBe(true);
    });
    it.each([
        'http://localhostXYZ',
        'http://127.0.0.1foobar',
        'http://192.168.1.1',
        'http://example.com',
        'https://my-localhost.com',
    ])('should not use enhanced basic delta algorithm when using WebDAV for a non local server url', (url) => {
        Setting_1.default.setValue('sync.target', SyncTargetRegistry_1.default.nameToId('webdav'));
        Setting_1.default.setValue('sync.6.path', url);
        const result = (0, file_api_1.enableEnhancedBasicDeltaAlgorithm)();
        expect(result).toBe(false);
    });
    it('should not use enhanced basic delta algorithm when not using file system sync or WebDAV', () => {
        Setting_1.default.setValue('sync.target', SyncTargetRegistry_1.default.nameToId('joplinServer'));
        const result = (0, file_api_1.enableEnhancedBasicDeltaAlgorithm)();
        expect(result).toBe(false);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should not return item, where remote item is a directory', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const stat = {
            path: remotePath(validNoteId),
            updated_time: baseTimestamp + 1,
            isDir: true,
        };
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(undefined, baseTimestamp));
        expect(context.items.length).toBe(0);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should not return item, where remote item is not a system path', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const noteId = '1b175bb38bba47baac22b0b47f77811'; // 1 char too short
        const stat = statItem(noteId, baseTimestamp + 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(undefined, baseTimestamp));
        expect(context.items.length).toBe(0);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should return item with isDeleted true, where remote item not longer exists', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(undefined), syncOptions(validNoteId, baseTimestamp));
        expect(context.items.length).toBe(1);
        expect(context.items[0].isDeleted).toBe(true);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should return item, where local item does not exist', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const stat = statItem(validNoteId, baseTimestamp);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(undefined, baseTimestamp));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should return item, where local item exists and remote item has a newer timestamp', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const stat = statItem(validNoteId, baseTimestamp + 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
    test.each([false, true])('basicDelta (enhancedAlgorithm: %s) should not return item, where local item exists and remote item has an equal timestamp', async (enhancedAlgorithm) => {
        setupWebDavSync(enhancedAlgorithm);
        const stat = statItem(validNoteId, baseTimestamp);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp));
        expect(context.items.length).toBe(0);
    });
    test('basicDelta (enhancedAlgorithm: false) should return item, where local item exists and remote item has an equal timestamp, but it is not present in fileAtTimestamp', async () => {
        setupWebDavSync(false);
        const stat = statItem(validNoteId, baseTimestamp);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp, baseTimestamp, false));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
    test('basicDelta (enhancedAlgorithm: false) should not return item, where local item exists and remote item has an older timestamp', async () => {
        setupWebDavSync(false);
        const stat = statItem(validNoteId, baseTimestamp - 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp));
        expect(context.items.length).toBe(0);
    });
    test('basicDelta (enhancedAlgorithm: false) should use context timestamp for timestamp comparisons, ignoring items with earlier timestamps', async () => {
        setupWebDavSync(false);
        const stat = statItem(validNoteId, baseTimestamp + 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp, baseTimestamp + 2));
        expect(context.items.length).toBe(0);
    });
    test('basicDelta (enhancedAlgorithm: true) should return item, where local item exists and remote item has an older timestamp', async () => {
        setupWebDavSync(true);
        const stat = statItem(validNoteId, baseTimestamp - 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
    test('basicDelta (enhancedAlgorithm: true) should ignore context timestamp for timestamp comparisons, and return item based on metadata timestamp', async () => {
        setupWebDavSync(true);
        const stat = statItem(validNoteId, baseTimestamp + 1);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, baseTimestamp, baseTimestamp + 2));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
    test('basicDelta (enhancedAlgorithm: true) should always return item if there is no metadata timestamp set', async () => {
        setupWebDavSync(true);
        const stat = statItem(validNoteId, baseTimestamp);
        const context = await (0, file_api_1.basicDelta)(basePath, dirStatFunc(stat), syncOptions(validNoteId, undefined, baseTimestamp + 1));
        expect(context.items.length).toBe(1);
        expect(context.items[0]).toBe(stat);
    });
});
//# sourceMappingURL=file-api.test.js.map