cibernox/ember-power-select

View on GitHub
ember-power-select/src/test-support.ts

Summary

Maintainability
D
2 days
Test Coverage
import { click, fillIn, settled } from '@ember/test-helpers';

async function openIfClosedAndGetContentId(trigger: HTMLElement) {
  const contentId = `ember-basic-dropdown-content-${trigger
    .getAttribute('data-ebd-id')
    ?.replace('-trigger', '')}`;
  const content = contentId
    ? document.querySelector(`#${contentId}`)
    : undefined;
  // If the dropdown is closed, open it
  if (
    !content ||
    content.classList.contains('ember-basic-dropdown-content-placeholder')
  ) {
    await click(trigger);
  }
  return contentId;
}

export async function selectChoose(
  cssPathOrTrigger: string | HTMLElement,
  valueOrSelector: string,
  optionIndex?: number,
) {
  let trigger: HTMLElement | null = null;
  let target: HTMLElement | undefined;
  if (cssPathOrTrigger instanceof HTMLElement) {
    if (cssPathOrTrigger.classList.contains('ember-power-select-trigger')) {
      trigger = cssPathOrTrigger;
    } else {
      trigger = cssPathOrTrigger.querySelector('.ember-power-select-trigger');
    }
  } else {
    trigger = document.querySelector(
      `${cssPathOrTrigger} .ember-power-select-trigger`,
    );

    if (!trigger) {
      trigger = document.querySelector(cssPathOrTrigger);
    }
  }

  if (!trigger) {
    throw new Error(
      `You called "selectChoose('${cssPathOrTrigger}', '${valueOrSelector}')" but no select was found using selector "${cssPathOrTrigger}"`,
    );
  }

  trigger.scrollIntoView();

  const contentId = await openIfClosedAndGetContentId(trigger);
  // Select the option with the given text
  const options = document.querySelectorAll<HTMLElement>(
    `#${contentId} .ember-power-select-option`,
  );
  let potentialTargets = Array.from(options).filter(
    (opt) => (opt.textContent ?? '').indexOf(valueOrSelector) > -1,
  );
  if (potentialTargets.length === 0) {
    potentialTargets = Array.from(
      document.querySelectorAll(`#${contentId} ${valueOrSelector}`),
    );
  }
  if (potentialTargets.length > 1) {
    const filteredTargets = potentialTargets.filter(
      (t) => t.textContent?.trim() === valueOrSelector,
    );
    if (optionIndex === undefined) {
      target = filteredTargets[0] ?? potentialTargets[0];
    } else {
      target = filteredTargets[optionIndex] ?? potentialTargets[optionIndex];
    }
  } else {
    target = potentialTargets[0];
  }
  if (!target) {
    throw new Error(
      `You called "selectChoose('${cssPathOrTrigger}', '${valueOrSelector}')" but "${valueOrSelector}" didn't match any option`,
    );
  }
  await click(target);
  return settled();
}

export async function selectSearch(
  cssPathOrTrigger: string | HTMLElement,
  value: string,
) {
  let trigger: HTMLElement | null;
  if (cssPathOrTrigger instanceof HTMLElement) {
    trigger = cssPathOrTrigger;
  } else {
    let triggerPath = `${cssPathOrTrigger} .ember-power-select-trigger`;
    trigger = document.querySelector(triggerPath);
    if (!trigger) {
      triggerPath = cssPathOrTrigger;
      trigger = document.querySelector(triggerPath);
    }

    if (!trigger) {
      throw new Error(
        `You called "selectSearch('${cssPathOrTrigger}', '${value}')" but no select was found using selector "${cssPathOrTrigger}"`,
      );
    }
  }

  trigger.scrollIntoView();

  const isMultipleSelect = !!trigger.querySelector(
    '.ember-power-select-trigger-multiple-input',
  );

  const contentId = await openIfClosedAndGetContentId(trigger);
  const isDefaultSingleSelect = !!document.querySelector(
    '.ember-power-select-search-input',
  );

  if (isMultipleSelect) {
    const multiSelectTrigger = trigger.querySelector(
      '.ember-power-select-trigger-multiple-input',
    );
    if (multiSelectTrigger) {
      await fillIn(multiSelectTrigger, value);
    }
  } else if (isDefaultSingleSelect) {
    await fillIn('.ember-power-select-search-input', value);
  } else {
    // It's probably a customized version
    const triggerInput = trigger.querySelector(
      '.ember-power-select-trigger input[type=search]',
    );
    if (triggerInput) {
      await fillIn(triggerInput, value);
    } else {
      await fillIn(
        `#${contentId} .ember-power-select-search-input[type=search]`,
        'input',
      );
    }
  }
  return settled();
}

export async function removeMultipleOption(cssPath: string, value: string) {
  let elem: HTMLElement | null = null;
  const items = document.querySelectorAll(
    `${cssPath} .ember-power-select-multiple-options > li`,
  );
  const item = Array.from(items).find(
    (el) => (el.textContent ?? '').indexOf(value) > -1,
  );
  if (item) {
    elem = item.querySelector('.ember-power-select-multiple-remove-btn');
  }

  if (!elem) {
    throw new Error(
      `You called "removeMultipleOption('${cssPath}', '${value}')" but no remove button was found using selector "${cssPath}" for value "${value}"`,
    );
  }

  await click(elem);
  return settled();
}

export async function clearSelected(cssPath: string) {
  const elem = document.querySelector(
    `${cssPath} .ember-power-select-clear-btn`,
  );

  if (!elem) {
    throw new Error(
      `You called "clearSelected('${cssPath}')" but no clear button was found using selector "${cssPath}"`,
    );
  }

  await click(elem);
  return settled();
}

/* *
 * @param {String} selector CSS3 selector of the elements to check the content
 * @returns {Array} returns all the elements present in the dropdown
 * */
export async function getDropdownItems(cssPathOrTrigger: string | HTMLElement) {
  let trigger: HTMLElement | null = null;

  if (cssPathOrTrigger instanceof HTMLElement) {
    if (cssPathOrTrigger.classList.contains('ember-power-select-trigger')) {
      trigger = cssPathOrTrigger;
    } else {
      trigger = cssPathOrTrigger.querySelector('.ember-power-select-trigger');
    }
  } else {
    trigger = document.querySelector(
      `${cssPathOrTrigger} .ember-power-select-trigger`,
    );

    if (!trigger) {
      trigger = document.querySelector(cssPathOrTrigger);
    }
  }

  if (!trigger) {
    throw new Error(
      `You called "getDropdownItems('${cssPathOrTrigger}'" but no select was found using selector "${cssPathOrTrigger}"`,
    );
  }

  trigger.scrollIntoView();

  const contentId = await openIfClosedAndGetContentId(trigger);
  // Select the option with the given selector
  const rawOptions = document.querySelectorAll(
    `#${contentId} .ember-power-select-option`,
  );
  return Array.from(rawOptions).map((opt) => opt.textContent?.trim());
}