"use strict";
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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const http_1 = __importDefault(require("http"));
const service_twirp_1 = require("../__mocks__/service.twirp");
const service_1 = require("../__mocks__/service");
const gateway_twirp_1 = require("../__mocks__/gateway.twirp");
const supertest_1 = __importDefault(require("supertest"));
const http_terminator_1 = require("http-terminator");
describe("Gateway", () => {
    let server;
    let twirpServer;
    let gateway;
    beforeEach(() => {
        twirpServer = service_twirp_1.createHaberdasherServer({
            MakeHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return service_1.Hat.create({
                        id: "1",
                        name: "cap",
                        color: "blue",
                        inches: request.inches,
                    });
                });
            },
            FindHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return request;
                });
            },
            ListHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return request;
                });
            }
        });
        gateway = gateway_twirp_1.createGateway();
        const twirpRewrite = gateway.twirpRewrite();
        server = http_1.default.createServer((req, resp) => {
            twirpRewrite(req, resp, () => {
                twirpServer.httpHandler()(req, resp);
            });
        });
    });
    it("call custom POST http endpoint that maps to MakeHat", () => __awaiter(void 0, void 0, void 0, function* () {
        const response = yield supertest_1.default(server)
            .post('/hat')
            .send({
            inches: 30,
        })
            .expect('Content-Type', "application/json")
            .expect(200);
        expect(response.body).toEqual({
            id: "1",
            name: "cap",
            color: "blue",
            inches: 30,
        });
    }));
    it("will map url parameter to request message", () => __awaiter(void 0, void 0, void 0, function* () {
        const response = yield supertest_1.default(server)
            .get('/hat/12345')
            .expect('Content-Type', "application/json")
            .expect(200);
        expect(response.body).toEqual({
            hat_id: "12345",
        });
    }));
    it("will map query string parameters to request message", () => __awaiter(void 0, void 0, void 0, function* () {
        const response = yield supertest_1.default(server)
            .get('/hat')
            .query({
            'filters[0].order_by': "desc",
            'filters[0].pagination.limit': 10,
            'filters[0].pagination.offset': 2,
            'filters[1].order_by': "asc",
            'filters[1].pagination.limit': 5,
            'filters[1].pagination.offset': 6,
        })
            .expect('Content-Type', "application/json")
            .expect(200);
        expect(response.body).toEqual({
            filters: [
                {
                    order_by: "desc",
                    pagination: {
                        limit: 10,
                        offset: 2,
                    },
                },
                {
                    order_by: "asc",
                    pagination: {
                        limit: 5,
                        offset: 6,
                    },
                }
            ]
        });
    }));
    it("will do a reverse proxy request to the handler", (done) => {
        const server = service_twirp_1.createHaberdasherServer({
            MakeHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return service_1.Hat.create({
                        id: "1",
                        name: "cap",
                        color: "blue",
                        inches: 100,
                        variants: [],
                    });
                });
            },
            FindHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return request;
                });
            },
            ListHat(ctx, request) {
                return __awaiter(this, void 0, void 0, function* () {
                    return request;
                });
            }
        });
        const gateway = gateway_twirp_1.createGateway();
        const twirpServerPort = 9999;
        const twirpServer = http_1.default.createServer(server.httpHandler());
        const httpTerminator1 = http_terminator_1.createHttpTerminator({
            server: twirpServer,
        });
        const gatewayServerPort = 9998;
        const gatewayServer = http_1.default.createServer(gateway.reverseProxy({
            baseUrl: "http://localhost:9999/twirp",
        }));
        const httpTerminator2 = http_terminator_1.createHttpTerminator({
            server: gatewayServer,
        });
        // twirp server
        twirpServer.listen(twirpServerPort, () => __awaiter(void 0, void 0, void 0, function* () {
            // reverse proxy server
            gatewayServer.listen(gatewayServerPort, () => __awaiter(void 0, void 0, void 0, function* () {
                const response = yield supertest_1.default(gatewayServer)
                    .post('/hat')
                    .send({
                    inches: 30,
                })
                    .expect('Content-Type', "application/json")
                    .expect(200);
                expect(response.body).toEqual({
                    id: "1",
                    name: "cap",
                    color: "blue",
                    inches: 100,
                });
                yield Promise.all([
                    httpTerminator1.terminate(),
                    httpTerminator2.terminate(),
                ]);
                done();
            }));
        }));
    });
});
