Home Manual Reference Source

src/controllers/web/login.controller.js

import * as WebPageObjects from "../../page_objects/web/webPageObjects.js";
import BaseController from "./base.controller.js";
import fs from "fs";
import { getLoginCookies } from "../../../src/utils/getLoginCookies.js";

/**
 * Controller to perform login related actions
 * @extends BaseController
*/
class LoginController extends BaseController {
  /**
   * @param {Object} args Args from client
   */
  constructor(args) {
    super(args);
    this.loginPage = new WebPageObjects.LoginPage(args);
    this.homePage = new WebPageObjects.HomePage(args);
    this.headerPanel = new WebPageObjects.HeaderPanel(args);
    this.onboardingPage = new WebPageObjects.OnboardingPage(args);
  }

  /**
   * Bypasses normal login page then sets cookies,
   * then navigates to /auth to login.
   * @param {String} email - email of user
   * @param {String} password - password of user
   * @example loginWithCookies('test@lifesize.com', 'password123')
   */
  async loginWithCookies(email, password) {
    try {
      await this.preLogin();
      const cookies = await getLoginCookies(email, password);
      await this.browser.execute(cookies => {
        document.cookie = cookies.fullA; // eslint-disable-line
        document.cookie = cookies.fullClient; // eslint-disable-line
      }, cookies);
      await this.browser.url(BASE_URL);
      await this.waitUntilIsLoggedIn();
      await this.setSkipAlertOnClose();
    } catch (error) {
      console.log("ISSUE LOGGING IN VIA API!!!"); // eslint-disable-line

      const browserLogs = await this.browser.log("browser");
      const testName = this.testName.replace(/[^A-Z0-9]+/gi, "_");
      const fileName = `./browser_logs/${testName}.${Date.now()}.browserLogs.txt`;

      fs.writeFile(fileName, JSON.stringify(browserLogs, null, 2), err => {
        if (err) {
          console.log("Error saving browser logs"); // eslint-disable-line
          throw err;
        }
      });

      console.log("Wrote browser logs to:", fileName); // eslint-disable-line

      throw error;
    }
    await this.browser.pause(3000);
  }

  /**
   * Logs in via the normal login page
   * @param {String} email - email of user
   * @param {String} password - password of user
   * @example login('test@lifesize.com', 'password123')
   */
  async login(email, password) {
    try {
      await this.preLogin();
      await this.loginPage.visit();
      await this.loginPage.login(email, password);
      await this.browser.pause(10000);
      await this.waitUntilIsLoggedIn();
      await this.setSkipAlertOnClose();
    } catch (error) {
      console.log(this.testName + " - ISSUE LOGGING IN MANUALLY!!!"); // eslint-disable-line

      const browserLogs = await this.browser.log("browser");
      const testName = this.testName.replace(/[^A-Z0-9]+/gi, "_");
      const fileName = `./browser_logs/${testName}.${Date.now()}.browserLogs.txt`;

      fs.writeFile(fileName, JSON.stringify(browserLogs, null, 2), err => {
        if (err) {
          console.log(this.testName + " - Error saving browser logs"); // eslint-disable-line
          throw err;
        }
      });

      console.log(this.testName + " - Wrote browser logs to:", fileName); // eslint-disable-line
      throw error;
    }
    await this.browser.pause(3000);
  }

  /**
   * Pre login steps to set onboarded local storage and disable walkme
   */
  async preLogin() {
    await this.browser.url(`${BASE_URL}/missingExtension`);
    await this.setOnboarded();
    await this.disableWalkMe();
    await this.setForcedIp();
  }

  /** 
   * Logs out of the app 
   * */
  async logout() {
    await this.headerPanel.logout();
    await this.waitUntilIsLoggedOut();
  }

  /**
   * Disable walk me from showing
   */
  async disableWalkMe() {
    await this.browser.localStorage("POST", {
      key: "disableWalkMe",
      value: "true"
    });
    await this.browser.pause(1000);
  }

  /* eslint-disable complexity */
  /**
  * Waits up to 30 seconds to be considered logged in
  * @example client.loginController.waitUntilIsLoggedIn()
  */
  async waitUntilIsLoggedIn() {
    // Check if we errored out on the login form
    const error = await this.checkForLoginErrors();
    if (error) {
      throw new Error(this.testName + " - Issue on login form:" + error);
    }

    // Check if we are still on the purple loading screen
    await this.browser.waitUntil(
      async () => (await this.isLoggingIn()) === false,
      30000,
      this.testName + " - Still on the loading animation prior to login."
    );

    // Check to see if kicked back to login form
    if (await this.loginPage.emailField().isVisible()) {
      throw new Error(
        this.testName + " - Got kicked back to login form after loading screen."
      );
    }

    // Finally, confirm we are logged in.
    await this.browser.waitUntil(
      async () => {
        await this.onboardingPage.bypass();
        return await this.isLoggedIn();
      },
      30000,
      this.testName + " - Should be on homepage, but not considered logged in."
    );
  }
  /* eslint-enable complexity */

  /**
   * Wait until user is considered logged out
   */
  async waitUntilIsLoggedOut() {
    await this.browser.waitUntil(
      async () =>
        (await this.isLoggedOut()) ? true : await this.browser.pause(1000),
      30000,
      this.testName + " - Not completely logged out."
    );
  }

  /**
   * Determines if user is currently logging in
   * @returns {Boolean} True if considered logging in
   */
  async isLoggingIn() {
    return await this.loginPage.loadingCircle().isVisible();
  }

  /**
   * Determines if user is logged in
   * @returns {Boolean} True if welcome message is visible
   * @todo check more things to be considered 'logged in'?
   */
  async isLoggedIn() {
    return await this.homePage.isWelcomeMessageVisible();
  }

  /**
   * Determinse if user is considered logged out
   * @returns {Boolean} True if considered logged out
   */
  async isLoggedOut() {
    const visible = await this.headerPanel.availabilityDropdown().isVisible();
    return !visible;
  }

  /**
   * Checks for errors on the login page
   * @returns {String} Text of error message or null
   */
  async checkForLoginErrors() {
    if (await this.loginPage.errorMessage().isVisible()) {
      return await this.loginPage.errorMessage().getText();
    } else {
      return null;
    }
  }

  /**
   * When closing browser or navigating away, we are presented with an alert.
   * This run js on the page that tells the app to skip this alert.
   * Hard coded to 300,000ms (5 minutes)
   */
  async setSkipAlertOnClose() {
    // checking for lsConfig so we can skip the alert upon closing browser
    await this.browser.waitUntil(
      async () => await this.browser.execute("!!window.lsConfig"),
      10000,
      this.testName + " - lsConfig is not found"
    );

    // window.desktop = true
    await this.browser.execute(
      "window.lsConfig.skipTimeOnBeforeUnload(900000)"
    );
  }

  /**
   * Set onboarded local storage to true
   */
  async setOnboarded() {
    await this.browser.localStorage("POST", {
      key: "onboarded",
      value: "true"
    });
  }

  /**
   * Set Forced CSS IP
   */
  async setForcedIp() {
    if (process.env.FORCED_IP) {
      await this.browser.localStorage("POST", {
        key: "ipAddressOverride",
        value: process.env.FORCED_IP
      });
    }
  }
}

export default LoginController;