"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 });
require("../../../src/api/BookingAPI");
const dayjs_1 = __importDefault(require("dayjs"));
const BasketRow_1 = __importDefault(require("../../../src/models/BasketRow"));
const Room_1 = require("../../../src/models/Room/Room");
const RoomRate_1 = require("../../../src/models/Room/RoomRate");
const RoomstaySession_1 = require("../../../src/models/RoomstaySession");
const SessionProvider_1 = __importDefault(require("../../../src/providers/storage/SessionProvider"));
const StorageProvider_1 = require("../../../src/providers/storage/StorageProvider");
describe('Session Provider Tests', () => {
    let session;
    beforeEach(() => {
        localStorage.clear();
        sessionStorage.clear();
        session = new SessionProvider_1.default();
    });
    describe('Session Provider Initialization', () => {
        it('creates a new session id if none are passed through', () => {
            expect.assertions(1);
            const session = new SessionProvider_1.default();
            return session.setSessionID().then(() => expect(session.getCurrentSessionID()).toBeTruthy());
        });
        it('re-uses a session if an ID is passed through', () => __awaiter(void 0, void 0, void 0, function* () {
            const sessionId = new Date().getTime();
            const sessionStorageProvider = new StorageProvider_1.StorageProvider(sessionStorage);
            yield sessionStorageProvider.write('currentSession', sessionId);
            const localStorageProvider = new StorageProvider_1.StorageProvider();
            yield localStorageProvider.write(`session-${sessionId}`, { id: sessionId });
            const session = new SessionProvider_1.default();
            yield session.initialize(sessionId);
            expect(session.getCurrentSessionID()).toBe(sessionId);
        }));
        it('saves session to storage when created', () => __awaiter(void 0, void 0, void 0, function* () {
            const session = new SessionProvider_1.default();
            yield session.initialize();
            const sessionId = session.getCurrentSessionID();
            expect(sessionId).toBeTruthy();
            expect(localStorage.getItem(`roomstay-session-${sessionId}`)).toBeTruthy();
        }));
        it('sets the current session id in sessionStorage', () => __awaiter(void 0, void 0, void 0, function* () {
            const session = new SessionProvider_1.default();
            yield session.initialize();
            const sessionId = session.getCurrentSessionID();
            expect(JSON.parse(sessionStorage.getItem('roomstay-currentSession')).value).toBe(sessionId);
        }));
    });
    describe('Loading a Session Object', () => {
        it('by default returns a blank session record', () => __awaiter(void 0, void 0, void 0, function* () {
            const state = yield session.getSession();
            expect(state).toBeTruthy();
            expect(state.id).toBeGreaterThan(1000000);
        }));
        it('loads and serializes an object from storage', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = new Date().getTime();
            const storage = new StorageProvider_1.StorageProvider();
            const serializedSession = {
                id,
                startDate: '2020-12-24',
                endDate: '2020-12-25',
                source: '',
                hotelID: '',
                step: 'StepRoom',
                basketRows: [],
            };
            storage.write(`session-${id}`, serializedSession);
            session = new SessionProvider_1.default();
            yield session.initialize(id);
            const state = yield session.getSession();
            expect(state.id).toBe(id);
        }));
        it('loads basket rows correctly mapped', () => __awaiter(void 0, void 0, void 0, function* () {
            var _a, _b;
            const id = new Date().getTime();
            const basketRow = new BasketRow_1.default();
            const room = new Room_1.Room();
            room.code = 'TESTCODE';
            room.name = 'Test Room Code';
            const rate = new RoomRate_1.RoomRate();
            rate.code = 'TEST';
            rate.name = 'Test Rate';
            rate.setRoom(room);
            basketRow.setRate(rate);
            const startDate = (0, dayjs_1.default)().add(1, 'day');
            const endDate = (0, dayjs_1.default)().add(3, 'day');
            yield session.saveSession({
                startDate,
                endDate,
                id: session.getCurrentSessionID(),
                source: '',
                hotelID: '',
                step: 'StepConfirmation',
                basketRows: [basketRow],
            });
            const loadedState = yield session.getSession();
            expect((_a = loadedState.startDate) === null || _a === void 0 ? void 0 : _a.isSame(startDate, 'date')).toBeTruthy();
            expect((_b = loadedState.endDate) === null || _b === void 0 ? void 0 : _b.isSame(endDate, 'date')).toBeTruthy();
            expect(loadedState.basketRows.length).toBeGreaterThan(0);
        }));
    });
    describe('Session Find and Retrieve', () => {
        it('finds all stored sessions in the storage', () => __awaiter(void 0, void 0, void 0, function* () {
            const startDate = (0, dayjs_1.default)().add(1, 'day');
            const endDate = (0, dayjs_1.default)().add(3, 'day');
            const room = new Room_1.Room();
            const rate = new RoomRate_1.RoomRate();
            rate.setRoom(room);
            const basketRow = new BasketRow_1.default();
            basketRow.setAdults(2);
            basketRow.setStartDate(startDate);
            basketRow.setEndDate(endDate);
            basketRow.setRate(rate);
            const partialState = {
                id: session.getCurrentSessionID(),
                startDate,
                endDate,
                source: '',
                hotelID: '',
                step: 'StepRoom',
                basketRows: [basketRow, basketRow],
            };
            //First write the session, with the auto-generated ID
            yield session.saveSession(partialState);
            //Then change over the sessionID
            yield session.setSessionID(new Date().getTime());
            //And write another session down
            yield session.saveSession(Object.assign(Object.assign({}, partialState), { id: session.getCurrentSessionID() }));
            const allSessions = yield session.getAllSessions();
            expect(allSessions.length).toBe(2);
        }));
    });
    describe('Saving session to local storage', () => {
        it('breaks out of save if no save parameter is passed', () => __awaiter(void 0, void 0, void 0, function* () {
            const session = new SessionProvider_1.default();
            const serializeCall = jest.spyOn(session, 'serializeSession');
            yield session.saveSession(null);
            expect(serializeCall).not.toHaveBeenCalled();
        }));
        it('saves current state in a serialized format', () => __awaiter(void 0, void 0, void 0, function* () {
            const partialState = {
                id: session.getCurrentSessionID(),
                startDate: (0, dayjs_1.default)().add(1, 'day'),
                endDate: (0, dayjs_1.default)().add(3, 'day'),
                source: '',
                hotelID: '',
                step: 'StepRoom',
                basketRows: [],
            };
            yield session.saveSession(partialState);
            const storage = new StorageProvider_1.StorageProvider();
            const rawStore = yield storage.read(`session-${session.getCurrentSessionID()}`);
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.startDate).toBe((0, dayjs_1.default)().add(1, 'day').format(RoomstaySession_1.SERIALIZED_DATE_FORMAT));
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.endDate).toBe((0, dayjs_1.default)().add(3, 'day').format(RoomstaySession_1.SERIALIZED_DATE_FORMAT));
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.step).toBe('StepRoom');
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.basketRows.length).toBe(0);
        }));
        it('saves current state of all basket rows correctly', () => __awaiter(void 0, void 0, void 0, function* () {
            const startDate = (0, dayjs_1.default)().add(1, 'day');
            const endDate = (0, dayjs_1.default)().add(3, 'day');
            const room = new Room_1.Room();
            const rate = new RoomRate_1.RoomRate();
            rate.setRoom(room);
            const basketRow = new BasketRow_1.default();
            basketRow.setAdults(2);
            basketRow.setStartDate(startDate);
            basketRow.setEndDate(endDate);
            basketRow.setRate(rate);
            const partialState = {
                id: session.getCurrentSessionID(),
                startDate,
                endDate,
                step: 'StepRoom',
                source: '',
                hotelID: '123',
                basketRows: [basketRow, basketRow],
            };
            yield session.saveSession(partialState);
            const storage = new StorageProvider_1.StorageProvider();
            const rawStore = yield storage.read(`session-${session.getCurrentSessionID()}`);
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.basketRows.length).toBe(2);
            expect(rawStore === null || rawStore === void 0 ? void 0 : rawStore.basketRows[0].startDate).toBe(startDate.format(RoomstaySession_1.SERIALIZED_DATE_FORMAT));
        }));
    });
    describe('Updating individual values of the state', () => {
        it('updates only the changed values of the state', () => __awaiter(void 0, void 0, void 0, function* () {
            var _a, _b;
            yield session.initialize();
            const startDate = (0, dayjs_1.default)();
            yield session.updateSession({ startDate });
            // Hacky way to get around the debounce timeout
            yield (() => new Promise((resolve) => {
                setTimeout(resolve, 350);
            }))();
            let state = yield session.getSession();
            expect((_a = state.startDate) === null || _a === void 0 ? void 0 : _a.isSame(startDate, 'day')).toBeTruthy();
            const endDate = (0, dayjs_1.default)();
            const room = new Room_1.Room();
            const rate = new RoomRate_1.RoomRate();
            rate.setRoom(room);
            const basketRow = new BasketRow_1.default();
            basketRow.setAdults(2);
            basketRow.setStartDate(startDate);
            basketRow.setEndDate(endDate);
            basketRow.setRate(rate);
            const basketRows = [basketRow];
            expect(state.basketRows.length).toBe(0);
            yield session.updateSession({ endDate, basketRows });
            // Hacky way to get around the debounce timeout
            yield (() => new Promise((resolve) => {
                setTimeout(resolve, 350);
            }))();
            state = yield session.getSession();
            expect((_b = state.endDate) === null || _b === void 0 ? void 0 : _b.isSame(endDate, 'day')).toBeTruthy();
            expect(state.basketRows.length).toBe(1);
        }));
    });
});
//# sourceMappingURL=SessionProvider.test.js.map