var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import { act } from 'react-dom/test-utils';
import { nanoid } from 'nanoid';
import { getWorkerURL, resetHtml, getFilesWithArrayBuffer, setUpRequestInterceptor, setUpResponseInterceptor, isValidCustomScript, getRequestFakeUrl, getResponseFakeUrl, getProcessedTask } from './customScript';
import { CustomAction, CustomScriptPlatform, RequestAction } from '@reltio/mdm-sdk';
jest.mock('nanoid', function () {
    var nanoid = jest.requireActual('nanoid');
    return __assign(__assign({}, nanoid), { nanoid: jest.fn() });
});
describe('customScript helpers tests', function () {
    beforeAll(function () {
        nanoid.mockReturnValue('nanoid');
    });
    beforeEach(function () {
        jest.clearAllMocks();
    });
    var uiPath = 'http://localhost:3000/nui/tenant/';
    var apiPath = '/nui/reltioAPI';
    var reltioPath = 'https://tst-01.reltio.com/reltio';
    var tenant = 'tenant';
    describe('getWorkerURL tests', function () {
        it('should return correct worker url', function () {
            expect(getWorkerURL(uiPath, tenant)).toBe('http://localhost:3000/nui/worker_api.js');
        });
    });
    describe('getRequestFakeUrl tests', function () {
        it('should return correct fake url if not starts with apiPath', function () {
            var url = '/entities';
            expect(getRequestFakeUrl(url, apiPath, reltioPath, tenant)).toBe('https://tst-01.reltio.com/reltio/api/tenant/entities');
        });
        it('should return correct fake url if starts with apiPath', function () {
            var url = '/nui/reltioAPI/entities';
            expect(getRequestFakeUrl(url, apiPath, reltioPath, tenant)).toBe('https://tst-01.reltio.com/reltio/entities');
        });
    });
    describe('getResponseFakeUrl tests', function () {
        it('should return correct fake url', function () {
            var url = '/nui/reltioAPI/entities';
            expect(getResponseFakeUrl(url, apiPath, reltioPath)).toBe('https://tst-01.reltio.com/reltio/entities');
        });
    });
    describe('getProcessedTask tests', function () {
        it('should return same task if no url', function () {
            var task = { action: CustomAction.REQUEST, params: {} };
            expect(getProcessedTask(task, apiPath, reltioPath, tenant)).toBe(task);
        });
        it('should return task with correct params if api action and not global url', function () {
            var task = {
                action: CustomAction.REQUEST,
                params: {
                    url: 'https://tst-01.reltio.com/reltio/entities',
                    name: RequestAction.API
                }
            };
            expect(getProcessedTask(task, apiPath, reltioPath, tenant)).toEqual(__assign(__assign({}, task), { params: __assign(__assign({}, task.params), { url: '/nui/reltioAPI/entities', validationUrl: task.params.url }) }));
        });
        it('should return task with correct params if global url and not api action', function () {
            var task = {
                action: CustomAction.REQUEST,
                params: {
                    url: 'https://tst-01.reltio.com/reltio/entities'
                }
            };
            expect(getProcessedTask(task, apiPath, reltioPath, tenant)).toEqual(__assign(__assign({}, task), { params: __assign(__assign({}, task.params), { url: '/nui/reltioAPI/entities', validationUrl: task.params.url }) }));
        });
        it('should return task with correct params if api action and global url', function () {
            var task = {
                action: CustomAction.REQUEST,
                params: {
                    url: '/entities',
                    name: RequestAction.API
                }
            };
            expect(getProcessedTask(task, apiPath, reltioPath, tenant)).toEqual(__assign(__assign({}, task), { params: __assign(__assign({}, task.params), { url: '/nui/reltioAPI/api/tenant/entities', validationUrl: task.params.url }) }));
        });
    });
    describe('getFilesWithArrayBuffer tests', function () {
        var fileTxt = new File(['testTxt'], 'foo.txt', { type: 'text/plain' });
        var filePng = new File(['testPng'], 'test.png', { type: 'png/image' });
        var getResult = function (file) { return ({
            content: new ArrayBuffer(file.size),
            lastModified: file.lastModified,
            name: file.name,
            size: file.size,
            type: file.type
        }); };
        var getFileList = function (files) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('name', 'file-upload');
            input.multiple = true;
            var fileList = Object.create(input.files);
            files.forEach(function (file, i) {
                fileList[i] = file;
            });
            Object.defineProperty(fileList, 'length', { value: files.length });
            return fileList;
        };
        it('should work correctly for one file', function () { return __awaiter(void 0, void 0, void 0, function () {
            var files, result, fileList, _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        files = [fileTxt];
                        result = files.map(getResult);
                        fileList = getFileList(files);
                        _a = expect;
                        return [4 /*yield*/, getFilesWithArrayBuffer(fileList)];
                    case 1:
                        _a.apply(void 0, [_b.sent()]).toEqual(result);
                        return [2 /*return*/];
                }
            });
        }); });
        it('should work correctly for multiple files', function () { return __awaiter(void 0, void 0, void 0, function () {
            var files, result, fileList, _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        files = [fileTxt, filePng];
                        result = files.map(getResult);
                        fileList = getFileList(files);
                        _a = expect;
                        return [4 /*yield*/, getFilesWithArrayBuffer(fileList)];
                    case 1:
                        _a.apply(void 0, [_b.sent()]).toEqual(result);
                        return [2 /*return*/];
                }
            });
        }); });
    });
    describe('isValidCustomScript tests', function () {
        it('should return true if valid custom script', function () {
            expect(isValidCustomScript({
                files: ['https://retlio.com/file.js'],
                platform: CustomScriptPlatform.NEW
            })).toBe(true);
            expect(isValidCustomScript({
                files: ['https://retlio.com/file.js']
            })).toBe(true);
        });
        it('should return false if invalid custom script', function () {
            expect(isValidCustomScript()).toBe(false);
            expect(isValidCustomScript({})).toBe(false);
            expect(isValidCustomScript({ files: [] })).toBe(false);
            expect(isValidCustomScript({ permissions: ['test123'] })).toBe(false);
            expect(isValidCustomScript({
                files: ['https://retlio.com/file.js'],
                platform: CustomScriptPlatform.CLASSIC
            })).toBe(false);
        });
    });
    describe('resetHtml tests', function () {
        var worker = {};
        var html = '<div>html</div>';
        var innerText = 'test';
        var setTooltip = jest.fn();
        var setHtml = jest.fn();
        var setListenersToReset = jest.fn();
        it('should work correctly with html prop', function () {
            var docBlock = document.createElement('div');
            docBlock.innerHTML = html;
            resetHtml({ worker: worker, setTooltip: setTooltip, innerText: innerText, html: html, setListenersToReset: setListenersToReset, setHtml: setHtml });
            expect(setListenersToReset).toHaveBeenCalledWith([]);
            expect(setHtml).toHaveBeenCalledWith(docBlock);
        });
        it('should work correctly without html prop', function () {
            var docBlock = document.createElement('div');
            docBlock.innerHTML = innerText;
            resetHtml({ worker: worker, setTooltip: setTooltip, innerText: innerText, setListenersToReset: setListenersToReset, setHtml: setHtml });
            expect(setListenersToReset).toHaveBeenCalledWith([]);
            expect(setHtml).toHaveBeenCalledWith(docBlock);
        });
    });
    describe('interceptors tests', function () {
        var postMessageSpy = jest.fn();
        var workerRef = {
            current: {
                postMessage: postMessageSpy
            }
        };
        var setRequestListeners = jest.fn();
        var setResponseListeners = jest.fn();
        var url = 'url';
        var next = jest.fn();
        var resolve = jest.fn();
        var abort = jest.fn();
        describe('setUpRequestInterceptor tests', function () {
            it('should correctly intercept if processable url', function () {
                var requestInterceptor = setUpRequestInterceptor({
                    apiPath: apiPath,
                    reltioPath: reltioPath,
                    tenant: tenant,
                    processApiRequest: ['https://tst-01.reltio.com/reltio/api/tenant/testRequest'],
                    workerRef: workerRef,
                    setRequestListeners: setRequestListeners
                });
                var options = {
                    method: 'POST',
                    body: 'string',
                    headers: { test: 'some' }
                };
                requestInterceptor({ options: options, next: next, url: '/testRequest', resolve: resolve, abort: abort });
                expect(setRequestListeners).toHaveBeenCalledWith(options, next, 'nanoid', resolve);
                expect(postMessageSpy).toHaveBeenCalledWith({
                    action: 'apiRequest',
                    id: 'nanoid',
                    url: 'https://tst-01.reltio.com/reltio/api/tenant/testRequest',
                    method: options.method,
                    headers: options.headers,
                    data: options.body
                });
                expect(next).not.toHaveBeenCalled();
            });
            it('should run next if not processable url', function () {
                var requestInterceptor = setUpRequestInterceptor({
                    apiPath: apiPath,
                    reltioPath: reltioPath,
                    tenant: tenant,
                    processApiRequest: [],
                    workerRef: workerRef,
                    setRequestListeners: setRequestListeners
                });
                var options = {
                    method: 'POST',
                    body: 'string',
                    headers: {}
                };
                requestInterceptor({ options: options, next: next, url: url, resolve: resolve, abort: abort });
                expect(postMessageSpy).not.toHaveBeenCalled();
                expect(next).toHaveBeenCalledWith(url, options);
            });
        });
        describe('setUpResponseInterceptor tests', function () {
            var resolveResponse;
            var rejectResponse;
            var createResponse = function (status) {
                return ({
                    json: function () {
                        return new Promise(function (resolve, reject) {
                            resolveResponse = function () { return resolve('data'); };
                            rejectResponse = function () { return reject('error'); };
                        });
                    },
                    status: status
                });
            };
            it('should correctly intercept response', function () { return __awaiter(void 0, void 0, void 0, function () {
                var response, responseInterceptor, options;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            response = createResponse(200);
                            responseInterceptor = setUpResponseInterceptor({
                                apiPath: apiPath,
                                reltioPath: reltioPath,
                                processApiResponse: ['https://tst-01.reltio.com/reltio/testRequest'],
                                workerRef: workerRef,
                                setResponseListeners: setResponseListeners
                            });
                            options = {
                                method: 'GET'
                            };
                            responseInterceptor({ url: '/testRequest', options: options, response: response, next: next, abort: abort });
                            return [4 /*yield*/, act(function () { return __awaiter(void 0, void 0, void 0, function () {
                                    return __generator(this, function (_a) {
                                        resolveResponse();
                                        return [2 /*return*/];
                                    });
                                }); })];
                        case 1:
                            _a.sent();
                            expect(setResponseListeners).toHaveBeenCalledWith(next, 'nanoid');
                            expect(postMessageSpy).toHaveBeenCalledWith({
                                action: 'apiResponse',
                                id: 'nanoid',
                                url: 'https://tst-01.reltio.com/reltio/testRequest',
                                method: options.method,
                                data: 'data'
                            });
                            expect(next).not.toHaveBeenCalled();
                            return [2 /*return*/];
                    }
                });
            }); });
            it('should handle error', function () { return __awaiter(void 0, void 0, void 0, function () {
                var response, responseInterceptor, options;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            response = createResponse(200);
                            responseInterceptor = setUpResponseInterceptor({
                                apiPath: apiPath,
                                reltioPath: reltioPath,
                                processApiResponse: ['https://tst-01.reltio.com/reltio/testRequest'],
                                workerRef: workerRef,
                                setResponseListeners: setResponseListeners
                            });
                            options = {
                                method: 'GET'
                            };
                            responseInterceptor({ url: '/testRequest', options: options, response: response, next: next, abort: abort });
                            return [4 /*yield*/, act(function () { return __awaiter(void 0, void 0, void 0, function () {
                                    return __generator(this, function (_a) {
                                        rejectResponse();
                                        return [2 /*return*/];
                                    });
                                }); })];
                        case 1:
                            _a.sent();
                            expect(setResponseListeners).not.toHaveBeenCalled();
                            expect(postMessageSpy).not.toHaveBeenCalled();
                            expect(next).not.toHaveBeenCalled();
                            expect(abort).toHaveBeenCalledWith('error');
                            return [2 /*return*/];
                    }
                });
            }); });
            it('should run next if not processable url', function () {
                var response = createResponse(200);
                var responseInterceptor = setUpResponseInterceptor({
                    apiPath: apiPath,
                    reltioPath: reltioPath,
                    processApiResponse: [],
                    workerRef: workerRef,
                    setResponseListeners: setResponseListeners
                });
                responseInterceptor({ url: url, options: {}, response: response, next: next, abort: abort });
                expect(setResponseListeners).not.toHaveBeenCalled();
                expect(postMessageSpy).not.toHaveBeenCalled();
                expect(next).toHaveBeenCalledWith(response);
            });
        });
    });
});
