<commit_before>import path from 'path';

import {assert} from 'chai';

import {moveMouse} from '../';
import {clearEventLog, getEventLog} from '../../events';
import {constructHydraId} from '../../hydra';

import {elements as mainElements} from './main';

const uploadDir = path.join(__dirname, '../assets');

export const elements = {
  deleteMessageButton: 'button[aria-label="Delete this message"]',
  flagButton: 'button[aria-label="Flag this message"]',
  highlighted: '.isHighlighted',
  pendingAction: '.flagActionPending',
  pendingActivity: '.activity-item-pending',
  inputFile: '.ciscospark-file-input',
  modalWindow: '.ciscospark-dialogue-modal',
  modalDeleteButton: 'button[title="Delete"].dialogue-modal-action-btn',
  downloadButtonContainer: '(//div[starts-with(@class,"ciscospark-activity-content")])[last()]',
  downloadFileButton: '(//div[@title="Download this file"]/parent::button)[last()]',
  shareButton: 'button[aria-label="Share"]',
  systemMessage: '.ciscospark-system-message',
  lastActivity: '.ciscospark-activity-item-container:last-child',
  lastActivityText: '.ciscospark-activity-item-container:last-child .ciscospark-activity-text'
};

export const messages = {
  youDeleted: 'You deleted your message.'
};

/**
 * @typedef {object} TestObject
 * @param {object} browser - browser for test
 * @param {object} user - user object for test
 * @param {object} displayName - name used to identify test object
 */

/**
 * Sends message to user from specified browser
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} message
 * @returns {void}
 */
export function sendMessage(sender, receiver, message) {
  sender.browser.waitForVisible(`[placeholder="Send a message to ${receiver.displayName}"]`);
  sender.browser.waitForVisible(elements.systemMessage);
  sender.browser.setValue(`[placeholder="Send a message to ${receiver.displayName}"]`, message);
  sender.browser.keys(['Enter', 'NULL']);
}

/**
 * Verifies message received from user in specified browser
 * @param {TestObject} receiver
 * @param {TestObject} sender
 * @param {string} message
 * @returns {void}
 */
export function verifyMessageReceipt(receiver, sender, message) {
  receiver.browser.waitForVisible(`[placeholder="Send a message to ${sender.displayName}"]`);
  receiver.browser.waitForExist(elements.pendingActivity, 15000, true);
  receiver.browser.waitForExist(elements.lastActivityText, 15000);
  receiver.browser.waitUntil(() => receiver.browser.element(elements.lastActivityText).getText() === message);
}

/**
 * Verifies file is displayed in files tab
 * @param {object} aBrowser
 * @param {string} fileName
 * @param {boolean} hasThumbnail
 * @returns {void}
 */
export function verifyFilesActivityTab(aBrowser, fileName, hasThumbnail) {
  const fileTitle = `//div[text()="${fileName}"]`;
  const fileThumbnail = `[alt="Uploaded File ${fileName}"]`;
  if (!aBrowser.isVisible(mainElements.activityMenu)) {
    aBrowser.click(mainElements.menuButton);
    aBrowser.waitForVisible(mainElements.activityMenu);
  }
  aBrowser.waitForVisible(mainElements.filesButton);
  aBrowser.click(mainElements.filesButton);
  aBrowser.waitForVisible(mainElements.filesWidget);
  aBrowser.element(`${mainElements.filesWidget}${fileTitle}`).waitForExist();
  if (hasThumbnail) {
    aBrowser.waitForVisible(fileThumbnail);
  }
  aBrowser.waitForVisible(mainElements.closeButton);
  aBrowser.click(mainElements.closeButton);
}

/**
 * Flags the last message received
 * @param {TestObject} testObject
 * @param {string} messageToFlag Verifies the last message is this string
 * @returns {void}
 */
export function flagMessage(testObject, messageToFlag) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    testObject.browser.element(elements.lastActivityText).getText() === messageToFlag);
  moveMouse(testObject.browser, elements.lastActivityText);
  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(`${elements.lastActivity} ${elements.flagButton}`)
      .isVisible(),
  'flag button is not visible');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.flagButton}`)
    .click();

  // Flag has a pending class while it waits for server upload
  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}${elements.pendingAction} ${elements.flagButton}`)
    .isVisible(), 1500, 'flag button did not highlight with pending state');

  // Verify it is highlighted, showing it was flagged
  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted} ${elements.flagButton}`)
    .isVisible(), 1500, 'flag button did not highlight');

  // Remove pending flag
  testObject.browser.waitUntil(() => !testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}${elements.pendingAction} ${elements.flagButton}`)
    .isVisible(), 7500, 'flag button did not remove pending state');
}

/**
 * Unflags the last message received. Expected message should already be flagged
 * @param {TestObject} testObject
 * @param {string} messageToUnflag
 * @returns {void}
 */
export function removeFlagMessage(testObject, messageToUnflag) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    testObject.browser.element(elements.lastActivityText).getText() === messageToUnflag, 'message was not found');

  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted} ${elements.flagButton}`)
    .isVisible(), 'message was not flagged');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.flagButton}`)
    .click();

  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}`)
    .isVisible() === false, 'message was still flagged');
}

/**
 * Looks to see if the last message can be deleted
 * @param {TestObject} testObject
 * @param {string} messageToDelete
 * @returns {boolean}
 */
export function canDeleteMessage(testObject, messageToDelete) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    // Text matches message to delete
    testObject.browser.element(elements.lastActivityText).getText() === messageToDelete);

  return testObject.browser
    .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
    // Delete button is hidden but still exists
    .isExisting();
}

/**
 * Deletes the last message sent
 * @param {TestObject} testObject
 * @param {string} messageToDelete
 */
export function deleteMessage(testObject, messageToDelete) {
  assert.isTrue(canDeleteMessage(testObject, messageToDelete));

  moveMouse(testObject.browser, elements.lastActivityText);

  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
      .isVisible(),
  'delete button is not visible');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
    .click();

  // Click modal confirm
  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(elements.modalWindow)
      .isVisible(),
  'modal window is not visible');
  assert.isTrue(testObject.browser.element(elements.modalDeleteButton).isVisible(), 'modal delete button is not visible');
  testObject.browser.element(elements.modalDeleteButton).click();

  testObject.browser.waitForVisible(`${elements.lastActivity} ${elements.systemMessage}`);

  testObject.browser.waitUntil(() => {
    const text = testObject.browser.element(`${elements.lastActivity} ${elements.systemMessage}`).getText();
    return text.includes(messages.youDeleted);
  }, 'message was not deleted');
}


/* eslint no-sync: "off" */
/**
 * Sends a file and verifies receipt
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} fileName
 * @param {boolean} [fileSizeVerify=true] Some files are embedded and don't display file sizes
 * @returns {void}
 */
const sendFileTest = (sender, receiver, fileName, fileSizeVerify = true) => {
  const filePath = path.join(uploadDir, fileName);
  const fileTitle = `//div[text()="${fileName}"]`;
  sender.browser.chooseFile(elements.inputFile, filePath);
  sender.browser.click(elements.shareButton);
  receiver.browser.waitForExist(fileTitle, 30000);
  receiver.browser.scroll(fileTitle);
  const localSize = sender.browser.element(elements.lastActivity).element('.ciscospark-share-file-size').getText();
  const remoteSize = receiver.browser.element(elements.lastActivity).element('.ciscospark-share-file-size').getText();
  // Some files are embedded and don't display file sizes
  if (fileSizeVerify) {
    assert.equal(localSize, remoteSize);
  }
  // Send receipt acknowledgement and verify before moving on
  sendMessage(receiver, sender, `Received: ${fileName}`);
  verifyMessageReceipt(sender, receiver, `Received: ${fileName}`);
};

/**
 * Test that sends a file and verifies that it is present in the files activity tab
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} fileName
 * @param {boolean} [hasThumbnail = true] Some files don't have a thumbnail
 * @returns {void}
 */<commit_msg>chore(journeys): add better error messaging<commit_after>import path from 'path';

import {assert} from 'chai';

import {moveMouse} from '../';
import {clearEventLog, getEventLog} from '../../events';
import {constructHydraId} from '../../hydra';

import {elements as mainElements} from './main';

const uploadDir = path.join(__dirname, '../assets');

export const elements = {
  deleteMessageButton: 'button[aria-label="Delete this message"]',
  flagButton: 'button[aria-label="Flag this message"]',
  highlighted: '.isHighlighted',
  pendingAction: '.flagActionPending',
  pendingActivity: '.activity-item-pending',
  inputFile: '.ciscospark-file-input',
  modalWindow: '.ciscospark-dialogue-modal',
  modalDeleteButton: 'button[title="Delete"].dialogue-modal-action-btn',
  downloadButtonContainer: '(//div[starts-with(@class,"ciscospark-activity-content")])[last()]',
  downloadFileButton: '(//div[@title="Download this file"]/parent::button)[last()]',
  shareButton: 'button[aria-label="Share"]',
  systemMessage: '.ciscospark-system-message',
  lastActivity: '.ciscospark-activity-item-container:last-child',
  lastActivityText: '.ciscospark-activity-item-container:last-child .ciscospark-activity-text'
};

export const messages = {
  youDeleted: 'You deleted your message.'
};

/**
 * @typedef {object} TestObject
 * @param {object} browser - browser for test
 * @param {object} user - user object for test
 * @param {object} displayName - name used to identify test object
 */

/**
 * Sends message to user from specified browser
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} message
 * @returns {void}
 */
export function sendMessage(sender, receiver, message) {
  sender.browser.waitForVisible(`[placeholder="Send a message to ${receiver.displayName}"]`);
  sender.browser.waitForVisible(elements.systemMessage);
  sender.browser.setValue(`[placeholder="Send a message to ${receiver.displayName}"]`, message);
  sender.browser.keys(['Enter', 'NULL']);
}

/**
 * Verifies message received from user in specified browser
 * @param {TestObject} receiver
 * @param {TestObject} sender
 * @param {string} message
 * @returns {void}
 */
export function verifyMessageReceipt(receiver, sender, message) {
  receiver.browser.waitForVisible(`[placeholder="Send a message to ${sender.displayName}"]`);
  receiver.browser.waitForExist(elements.pendingActivity, 15000, true);
  receiver.browser.waitForExist(elements.lastActivityText, 15000);
  receiver.browser.waitUntil(() => receiver.browser.element(elements.lastActivityText).getText() === message);
}

/**
 * Verifies file is displayed in files tab
 * @param {object} aBrowser
 * @param {string} fileName
 * @param {boolean} hasThumbnail
 * @returns {void}
 */
export function verifyFilesActivityTab(aBrowser, fileName, hasThumbnail) {
  const fileTitle = `//div[text()="${fileName}"]`;
  const fileThumbnail = `[alt="Uploaded File ${fileName}"]`;
  if (!aBrowser.isVisible(mainElements.activityMenu)) {
    aBrowser.click(mainElements.menuButton);
    aBrowser.waitForVisible(mainElements.activityMenu);
  }
  aBrowser.waitForVisible(mainElements.filesButton);
  aBrowser.click(mainElements.filesButton);
  aBrowser.waitForVisible(mainElements.filesWidget);
  aBrowser.element(`${mainElements.filesWidget}${fileTitle}`).waitForExist();
  if (hasThumbnail) {
    aBrowser.waitForVisible(fileThumbnail);
  }
  aBrowser.waitForVisible(mainElements.closeButton);
  aBrowser.click(mainElements.closeButton);
}

/**
 * Flags the last message received
 * @param {TestObject} testObject
 * @param {string} messageToFlag Verifies the last message is this string
 * @returns {void}
 */
export function flagMessage(testObject, messageToFlag) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    testObject.browser.element(elements.lastActivityText).getText() === messageToFlag);
  moveMouse(testObject.browser, elements.lastActivityText);
  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(`${elements.lastActivity} ${elements.flagButton}`)
      .isVisible(),
  1500, 'flag button is not visible when hovering');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.flagButton}`)
    .click();

  // Flag has a pending class while it waits for server upload
  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}${elements.pendingAction} ${elements.flagButton}`)
    .isVisible(), 1500, 'flag button did not highlight with pending state');

  // Verify it is highlighted, showing it was flagged
  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted} ${elements.flagButton}`)
    .isVisible(), 1500, 'flag button did not highlight');

  // Remove pending flag
  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}${elements.pendingAction} ${elements.flagButton}`)
    .isVisible() === false, 7500, 'flag button did not remove pending state');
}

/**
 * Unflags the last message received. Expected message should already be flagged
 * @param {TestObject} testObject
 * @param {string} messageToUnflag
 * @returns {void}
 */
export function removeFlagMessage(testObject, messageToUnflag) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    testObject.browser.element(elements.lastActivityText).getText() === messageToUnflag, 1500, 'message was not found');

  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted} ${elements.flagButton}`)
    .isVisible(), 1500, 'message was not flagged');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.flagButton}`)
    .click();

  testObject.browser.waitUntil(() => testObject.browser
    .element(`${elements.lastActivity} ${elements.highlighted}`)
    .isVisible() === false, 3500, 'message was still flagged');
}

/**
 * Looks to see if the last message can be deleted
 * @param {TestObject} testObject
 * @param {string} messageToDelete
 * @returns {boolean}
 */
export function canDeleteMessage(testObject, messageToDelete) {
  testObject.browser.waitForExist(elements.pendingActivity, 15000, true);
  testObject.browser.waitUntil(() =>
    // Text matches message to delete
    testObject.browser.element(elements.lastActivityText).getText() === messageToDelete);

  return testObject.browser
    .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
    // Delete button is hidden but still exists
    .isExisting();
}

/**
 * Deletes the last message sent
 * @param {TestObject} testObject
 * @param {string} messageToDelete
 */
export function deleteMessage(testObject, messageToDelete) {
  assert.isTrue(canDeleteMessage(testObject, messageToDelete));

  moveMouse(testObject.browser, elements.lastActivityText);

  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
      .isVisible(),
  1500, 'delete button is not visible when hovering');

  testObject.browser
    .element(`${elements.lastActivity} ${elements.deleteMessageButton}`)
    .click();

  // Click modal confirm
  testObject.browser.waitUntil(() =>
    testObject.browser
      .element(elements.modalWindow)
      .isVisible(),
  3500, 'delete modal window is not visible after clicking delete button');
  assert.isTrue(testObject.browser.element(elements.modalDeleteButton).isVisible(), 'modal delete button is not visible');
  testObject.browser.element(elements.modalDeleteButton).click();

  testObject.browser.waitForVisible(`${elements.lastActivity} ${elements.systemMessage}`);

  testObject.browser.waitUntil(() => {
    const text = testObject.browser.element(`${elements.lastActivity} ${elements.systemMessage}`).getText();
    return text.includes(messages.youDeleted);
  }, 3500, 'message was not deleted');
}


/* eslint no-sync: "off" */
/**
 * Sends a file and verifies receipt
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} fileName
 * @param {boolean} [fileSizeVerify=true] Some files are embedded and don't display file sizes
 * @returns {void}
 */
const sendFileTest = (sender, receiver, fileName, fileSizeVerify = true) => {
  const filePath = path.join(uploadDir, fileName);
  const fileTitle = `//div[text()="${fileName}"]`;
  sender.browser.chooseFile(elements.inputFile, filePath);
  sender.browser.click(elements.shareButton);
  receiver.browser.waitForExist(fileTitle, 30000);
  receiver.browser.scroll(fileTitle);
  const localSize = sender.browser.element(`${elements.lastActivity} .ciscospark-share-file-size`).getText();
  const remoteSize = receiver.browser.element(`${elements.lastActivity} .ciscospark-share-file-size`).getText();
  // Some files are embedded and don't display file sizes
  if (fileSizeVerify) {
    assert.equal(localSize, remoteSize);
  }
  // Send receipt acknowledgement and verify before moving on
  sendMessage(receiver, sender, `Received: ${fileName}`);
  verifyMessageReceipt(sender, receiver, `Received: ${fileName}`);
};

/**
 * Test that sends a file and verifies that it is present in the files activity tab
 * @param {TestObject} sender
 * @param {TestObject} receiver
 * @param {string} fileName
 * @param {boolean} [hasThumbnail = true] Some files don't have a thumbnail
 * @returns {void}
 */
{'fraction_non_alphanumeric': 0.14177803602556652, 'fraction_numerical': 0.005916222069621256, 'mean_word_length': 5.27927031509121, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6342740', 'n_tokens_mistral': 5489, 'n_tokens_neox': 5398, 'n_words': 1263}