"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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 aws4_1 = require("aws4");
const axios_1 = __importStar(require("axios"));
const _1 = require(".");
jest.mock("aws4");
jest.mock("./credentials/assumeRoleCredentialsProvider", () => ({
    AssumeRoleCredentialsProvider: jest.fn(() => ({
        getCredentials: jest.fn().mockResolvedValue({
            accessKeyId: "assumed-access-key-id",
            secretAccessKey: "assumed-secret-access-key",
            sessionToken: "assumed-session-token",
        }),
    })),
}));
const mockCustomProvider = {
    getCredentials: () => __awaiter(void 0, void 0, void 0, function* () {
        return Promise.resolve({
            accessKeyId: "custom-provider-access-key-id",
            secretAccessKey: "custom-provider-secret-access-key",
            sessionToken: "custom-provider-session-token",
        });
    }),
};
const getDefaultHeaders = () => new axios_1.AxiosHeaders();
const getDefaultTransformRequest = () => axios_1.default.defaults.transformRequest;
beforeEach(() => {
    aws4_1.sign.mockReset();
});
describe("interceptor", () => {
    it("signs GET requests", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, undefined);
    }));
    it("signs url query parameters in GET requests", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar?foo=bar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar?foo=bar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, undefined);
    }));
    it("signs query parameters in GET requests", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            params: { foo: "bar" },
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar?foo=bar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, undefined);
    }));
    it("signs POST requests with an object payload", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = { foo: "bar" };
        const request = {
            method: "POST",
            url: "https://example.com/foobar",
            data,
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "POST",
            region: "local",
            host: "example.com",
            body: '{"foo":"bar"}',
            headers: { "Content-Type": "application/json" },
        }, undefined);
    }));
    it("signs POST requests with a string payload", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = "foobar";
        const request = {
            method: "POST",
            url: "https://example.com/foobar",
            data,
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            method: "POST",
            path: "/foobar",
            region: "local",
            host: "example.com",
            body: "foobar",
            headers: {},
        }, undefined);
        expect(request.headers['X-Amz-Content-Sha256']).toBeUndefined();
    }));
    it("adds X-Amz-Content-Sha256 for a string payload", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = "foobar";
        const request = {
            method: "POST",
            url: "https://example.com/foobar",
            data,
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
                addContentSha: true
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(request.headers['X-Amz-Content-Sha256']).toEqual('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2');
    }));
    it("passes Content-Type header to be signed", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = "foobar";
        const request = {
            method: "POST",
            url: "https://example.com/foobar",
            data,
            headers: new axios_1.AxiosHeaders(Object.assign(Object.assign({}, getDefaultHeaders()), { "Content-Type": "application/xml" })),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            instance: axios_1.default,
            options: {
                region: "local",
                service: "execute-api",
            },
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            method: "POST",
            path: "/foobar",
            region: "local",
            host: "example.com",
            body: "foobar",
            headers: { "Content-Type": "application/xml" },
        }, undefined);
    }));
    it("works with baseURL config", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = "foobar";
        const request = {
            method: "POST",
            baseURL: "https://example.com/foo",
            url: "bar",
            data,
            headers: new axios_1.AxiosHeaders(Object.assign(Object.assign({}, getDefaultHeaders()), { "Content-Type": "application/xml" })),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            method: "POST",
            path: "/foo/bar",
            region: "local",
            host: "example.com",
            body: "foobar",
            headers: { "Content-Type": "application/xml" },
        }, undefined);
    }));
    it("passes option to sign the query instead of adding header", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            instance: axios_1.default,
            options: {
                region: "local",
                service: "execute-api",
                signQuery: true,
            },
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            method: "GET",
            path: "/foobar",
            region: "local",
            host: "example.com",
            headers: {},
            signQuery: true,
        }, undefined);
    }));
    it("passes option to add a content SHA", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            instance: axios_1.default,
            options: {
                region: "local",
                service: "execute-api",
                addContentSha: true,
            },
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(request.headers['X-Amz-Content-Sha256']).toEqual('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
    }));
});
describe("credentials", () => {
    it("passes provided credentials", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            instance: axios_1.default,
            options: {
                region: "local",
                service: "execute-api",
            },
            credentials: {
                accessKeyId: "access-key-id",
                secretAccessKey: "secret-access-key",
                sessionToken: "session-token",
            },
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, {
            accessKeyId: "access-key-id",
            secretAccessKey: "secret-access-key",
            sessionToken: "session-token",
        });
    }));
    it("gets credentials for given role", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            instance: axios_1.default,
            options: {
                region: "local",
                service: "execute-api",
                assumeRoleArn: "arn:aws:iam::111111111111:role/MockRole",
            },
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, {
            accessKeyId: "assumed-access-key-id",
            secretAccessKey: "assumed-secret-access-key",
            sessionToken: "assumed-session-token",
        });
    }));
    it("prioritizes provided credentials provider over the role", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
                assumeRoleArn: "arn:aws:iam::111111111111:role/MockRole",
            },
            credentials: mockCustomProvider,
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, {
            accessKeyId: "custom-provider-access-key-id",
            secretAccessKey: "custom-provider-secret-access-key",
            sessionToken: "custom-provider-session-token",
        });
    }));
    it("prioritizes provided credentials over the role", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "https://example.com/foobar",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
                assumeRoleArn: "arn:aws:iam::111111111111:role/MockRole",
            },
            credentials: {
                accessKeyId: "access-key-id",
                secretAccessKey: "secret-access-key",
                sessionToken: "session-token",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        // Assert
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/foobar",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
        }, {
            accessKeyId: "access-key-id",
            secretAccessKey: "secret-access-key",
            sessionToken: "session-token",
        });
    }));
    it("allows empty URL when baseURL is set", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const request = {
            method: "GET",
            url: "",
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        const client = axios_1.default.create({
            baseURL: "https://example.com",
        });
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
                assumeRoleArn: "arn:aws:iam::111111111111:role/MockRole",
            },
            credentials: {
                accessKeyId: "access-key-id",
                secretAccessKey: "secret-access-key",
                sessionToken: "session-token",
            },
            instance: client,
        });
        // Act
        yield expect(interceptor(request)).resolves.toBeDefined();
        expect(aws4_1.sign).toBeCalledWith({
            service: "execute-api",
            path: "/",
            method: "GET",
            region: "local",
            host: "example.com",
            headers: {},
            signQuery: undefined,
        }, {
            accessKeyId: "access-key-id",
            secretAccessKey: "secret-access-key",
            sessionToken: "session-token",
        });
    }));
    it("supports retries", () => __awaiter(void 0, void 0, void 0, function* () {
        // Arrange
        const data = { foo: "bar" };
        const request = {
            method: "POST",
            url: "https://example.com/foobar",
            data,
            headers: getDefaultHeaders(),
            transformRequest: getDefaultTransformRequest(),
        };
        aws4_1.sign.mockImplementation((request) => {
            // neither call should contain the previous Authorization header
            expect(request).toEqual({
                service: "execute-api",
                path: "/foobar",
                method: "POST",
                region: "local",
                host: "example.com",
                body: '{"foo":"bar"}',
                headers: { "Content-Type": "application/json" },
                signQuery: undefined
            });
            request.headers['Authorization'] = 'signed';
            return request;
        });
        const interceptor = (0, _1.aws4Interceptor)({
            options: {
                region: "local",
                service: "execute-api",
            },
            instance: axios_1.default,
        });
        // Act
        yield interceptor(request);
        yield interceptor(request);
        yield interceptor(request);
        expect(aws4_1.sign).toBeCalledTimes(3);
    }));
});
