"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const CdmHttpClient_1 = require("../../Utilities/Network/CdmHttpClient");
const CdmHttpRequest_1 = require("../../Utilities/Network/CdmHttpRequest");
const CdmHttpResponse_1 = require("../../Utilities/Network/CdmHttpResponse");
let requestsExecutionCounter = 0;
describe('Network/MockCdmHttpClientTest', () => {
    /**
     * Testing for an immediate success.
     */
    it('Mock Cdm Http client testing for an immediate success.', () => __awaiter(void 0, void 0, void 0, function* () {
        const client = new CdmHttpClient_1.CdmHttpClient('http://www.example.com', completeResponseMethod);
        const httpRequest = new CdmHttpRequest_1.CdmHttpRequest('/folder1', 0);
        httpRequest.timeout = 1000;
        httpRequest.maximumTimeout = 10000;
        const response = yield client.SendAsync(httpRequest, callback);
        expect(response.statusCode)
            .toBe(200);
    }));
    /**
     * Testing for a failure then success with the callback.
     */
    it('Mock Cdm Http client testing for a failure then success with the callback.', () => __awaiter(void 0, void 0, void 0, function* () {
        requestsExecutionCounter = 0;
        const client = new CdmHttpClient_1.CdmHttpClient('http://www.example.com', delayedResponseMethod);
        const httpRequest = new CdmHttpRequest_1.CdmHttpRequest('/folder1', 1, 'GET');
        httpRequest.timeout = 2000;
        httpRequest.maximumTimeout = 10000;
        httpRequest.numberOfRetries = 2;
        const headers = new Map();
        headers.set('User-Agent', 'CDM');
        httpRequest.headers = headers;
        const response = yield client.SendAsync(httpRequest, callback);
        expect(response.statusCode)
            .toBe(200);
    }));
    /**
     * Testing for a failure - number of exceeded retries.
     */
    it('Mock Cdm Http client testing for a failure - number of exceeded retries.', () => __awaiter(void 0, void 0, void 0, function* () {
        requestsExecutionCounter = 0;
        const client = new CdmHttpClient_1.CdmHttpClient('http://www.example.com', delayedResponseMethod);
        const httpRequest = new CdmHttpRequest_1.CdmHttpRequest('/folder1');
        httpRequest.timeout = 100;
        httpRequest.maximumTimeout = 10000;
        httpRequest.numberOfRetries = 2;
        httpRequest.method = 'GET';
        const headers = new Map();
        headers.set('User-Agent', 'CDM');
        httpRequest.headers = headers;
        try {
            yield client.SendAsync(httpRequest, callback);
            fail('This test case should\'ve failed and throw an exception due too many retries.');
        }
        catch (err) {
            expect(err)
                .toBe('The number of retries has exceeded the maximum number allowed by the client.');
        }
    }));
    /**
     * Testing for a timeout.
     */
    it('Mock Cdm Http client testing for a timeout.', () => __awaiter(void 0, void 0, void 0, function* () {
        requestsExecutionCounter = 0;
        const client = new CdmHttpClient_1.CdmHttpClient('http://www.example.com', delayedResponseMethod);
        const httpRequest = new CdmHttpRequest_1.CdmHttpRequest('/folder1');
        httpRequest.timeout = 2000;
        httpRequest.maximumTimeout = 20000;
        httpRequest.numberOfRetries = 0;
        try {
            yield client.SendAsync(httpRequest, callback);
            fail('This test case should\'ve failed and throw an exception due timeout.');
        }
        catch (err) {
            expect(err)
                .toBe('Request timeout.');
        }
    }));
    /**
     * Testing for a maximum timeout.
     */
    it('Mock Cdm Http client testing for a maximum timeout.', () => __awaiter(void 0, void 0, void 0, function* () {
        requestsExecutionCounter = 0;
        const client = new CdmHttpClient_1.CdmHttpClient('http://www.example.com', delayedResponseMethod);
        const httpRequest = new CdmHttpRequest_1.CdmHttpRequest('/folder1');
        httpRequest.timeout = 200;
        httpRequest.maximumTimeout = 3500;
        httpRequest.numberOfRetries = 20;
        try {
            yield client.SendAsync(httpRequest, callback);
            fail('This test case should\'ve failed and throw an exception due timeout.');
        }
        catch (err) {
            expect(err)
                .toBe('Maximum timeout exceeded.');
        }
    }));
    function completeResponseMethod(fullUrl, method, requestTimeout, content, outgoingHeaders) {
        return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            yield CdmHttpClient_1.CdmHttpClient.sleep(100);
            resolve(new CdmHttpResponse_1.CdmHttpResponse(200));
        }));
    }
    function delayedResponseMethod(fullUrl, method, requestTimeout, content, outgoingHeaders) {
        return __awaiter(this, void 0, void 0, function* () {
            const waitTime = requestsExecutionCounter == 0 ? 4000 : 2000;
            requestsExecutionCounter++;
            const cancelled = requestTimeout < waitTime;
            yield CdmHttpClient_1.CdmHttpClient.sleep(Math.min(waitTime, requestTimeout));
            if (cancelled) {
                const error = {
                    code: 'ECONNRESET'
                };
                throw error;
            }
            const response = new CdmHttpResponse_1.CdmHttpResponse(200);
            response.content = 'REPLY2';
            return response;
        });
    }
});
function callback(response, hasFailed, retryNumber) {
    if (response !== undefined && response.isSuccessful && !hasFailed) {
        return undefined;
    }
    else {
        const upperBound = 1 << retryNumber;
        // Default wait time is calculated using exponential backoff with with random jitter value to avoid 'waves'.
        return Math.floor(Math.random() * upperBound) * 500;
    }
}
//# sourceMappingURL=MockCdmHttpClient.test.js.map