async function expectHasClassNames(selectorInitializer, classNames, options) {
  if (!(utils.isNonBlankString(classNames) || _.isArray(classNames))) {
    throw new TypeError(
      `'classNames' argument must be a non-blank string or array but it is ${typeOf(classNames)} (${classNames})`
    );
  }

  const opts = new Options(options, { defaults: { only: false } });
  const { only } = opts;

  const sel = Selector(selectorInitializer);
  await t.expect(sel.count).eql(1, "Selector must return only one DOM element but it doesn't");

  // `classNames` argument allowed to be a string but we work with array.
  classNames = _.isArray(classNames) ? classNames : [classNames];

  // ---------------------------------------------------------------------------
  // Handling case when selector must not have CSS classes at all
  // ---------------------------------------------------------------------------

  if (_.isEmpty(classNames)) {
    await t
      .expect(sel.classNames)
      .eql([''], `Selector must not have (CSS) class names but it does`);

    return;
  }

  // ---------------------------------------------------------------------------
  // Handling case when selector must have/haven't specified CSS classes
  // ---------------------------------------------------------------------------

  const classNamesMustPresent = [];

  for (const item of classNames) {
    if (!(utils.isNonBlankString(item) || _.isArray(item))) {
      throw new TypeError(
        `Item of 'classNames' array argument must be a non-blank string or array but it is` +
        ` ${typeOf(item)} (${item})`
      );
    }

    let className = item;
    let isNot = false;

    if (_.isArray(item)) {
      [className, isNot = false] = item;
    }

    if (!utils.isNonBlankString(className)) {
      throw new TypeError(
        `First element of array item of 'classNames' array argument must be a non-blank string but it is` +
        ` ${typeOf(className)} (${className})`
      );
    }

    if (!_.isBoolean(isNot)) {
      throw new TypeError(
        `Second element of array item of 'classNames' array argument must be a nil or boolean but it is` +
        ` ${typeOf(isNot)} (${isNot})`
      );
    }

    if (!isNot) {
      classNamesMustPresent.push(className);
    }

    const assertionName = utils.buildTestCafeAssertionName('ok', { isNot });
    const message =
      `Selector must ${isNot ? 'not have' : 'have'} '${className}' (CSS) class name ` +
      `but it ${isNot ? 'does' : "doesn't"}`;

    await t.expect(sel.hasClass(className))[assertionName](message);
  }

  if (only) {
    const classNamesMustPresentTxt = _.join(classNamesMustPresent, ', ');
    const selClassNames = await sel.classNames;
    const selClassNamesTxt = _.join(selClassNames, ', ');

    await t
      .expect(selClassNames.length)
      .eql(
        classNamesMustPresent.length,
        `Selector must have only '${classNamesMustPresentTxt}' (CSS) class names but it have '${selClassNamesTxt}'`
      );
  }
}
/**
 * Asserts that TestCafe selector initialized using `selectorInitializer` have
 * specified (CSS) class names. Note that TestCafe's auto wait feature used
 * to test for presence/absence of each (CSS) class name of `classNames`.
 *
 * @param {*} selectorInitializer - Initializer for TestCafe selector. See TestCafe's `Selector` for more info. Note that selector must return exactly one DOM node, otherwise error would be thrown
 * @param {array|string} classNames - (CSS) Class names which selector must have. Examples: 'className', ['className'], [['className']], [['className', false]], [['className', true]], [['className'], ['other-class-name', true]]. In case of array, passing truthy value as second element of `classNames` array item allows to assert that selector doesn't have specified (CSS) class name
 * @param {?Options} [options] - Options
 * @param {boolean} [options.only=false] - When truthy selector must have only (CSS) class names specified in `classNames` argument
 * @throws {TypeError} When arguments aren't valid.
 */
Asserts that TestCafe selector initialized using `selectorInitializer` have
specified (CSS) class names. Note that TestCafe's auto wait feature used
to test for presence/absence of each (CSS) class name of `classNames`.

@param {*} selectorInitializer - Initializer for TestCafe selector. See TestCafe's `Selector` for more info. Note that selector must return exactly one DOM node, otherwise error would be thrown
@param {array|string} classNames - (CSS) Class names which selector must have.
Asserts that TestCafe selector initialized using ` selectorInitializer ` have specified ( CSS ) class names . Note that TestCafe ' s auto wait feature used to test for presence / absence of each ( CSS ) class name of ` classNames ` . @param { * } selectorInitializer - Initializer for TestCafe selector . See TestCafe ' s ` Selector ` for more info . Note that selector must return exactly one DOM node otherwise error would be thrown @param { array|string } classNames - ( CSS ) Class names which selector must have .
async function expectHasClassNames(selectorInitializer, classNames, options) {
  if (!(utils.isNonBlankString(classNames) || _.isArray(classNames))) {
    throw new TypeError(
      `'classNames' argument must be a non-blank string or array but it is ${typeOf(classNames)} (${classNames})`
    );
  }
  const opts = new Options(options, { defaults: { only: false } });
  const { only } = opts;
  const sel = Selector(selectorInitializer);
  await t.expect(sel.count).eql(1, "Selector must return only one DOM element but it doesn't");
  classNames = _.isArray(classNames) ? classNames : [classNames];
  if (_.isEmpty(classNames)) {
    await t
      .expect(sel.classNames)
      .eql([''], `Selector must not have (CSS) class names but it does`);
    return;
  }
  const classNamesMustPresent = [];
  for (const item of classNames) {
    if (!(utils.isNonBlankString(item) || _.isArray(item))) {
      throw new TypeError(
        `Item of 'classNames' array argument must be a non-blank string or array but it is` +
        ` ${typeOf(item)} (${item})`
      );
    }
    let className = item;
    let isNot = false;
    if (_.isArray(item)) {
      [className, isNot = false] = item;
    }
    if (!utils.isNonBlankString(className)) {
      throw new TypeError(
        `First element of array item of 'classNames' array argument must be a non-blank string but it is` +
        ` ${typeOf(className)} (${className})`
      );
    }
    if (!_.isBoolean(isNot)) {
      throw new TypeError(
        `Second element of array item of 'classNames' array argument must be a nil or boolean but it is` +
        ` ${typeOf(isNot)} (${isNot})`
      );
    }
    if (!isNot) {
      classNamesMustPresent.push(className);
    }
    const assertionName = utils.buildTestCafeAssertionName('ok', { isNot });
    const message =
      `Selector must ${isNot ? 'not have' : 'have'} '${className}' (CSS) class name ` +
      `but it ${isNot ? 'does' : "doesn't"}`;
    await t.expect(sel.hasClass(className))[assertionName](message);
  }
  if (only) {
    const classNamesMustPresentTxt = _.join(classNamesMustPresent, ', ');
    const selClassNames = await sel.classNames;
    const selClassNamesTxt = _.join(selClassNames, ', ');
    await t
      .expect(selClassNames.length)
      .eql(
        classNamesMustPresent.length,
        `Selector must have only '${classNamesMustPresentTxt}' (CSS) class names but it have '${selClassNamesTxt}'`
      );
  }
}
async function expectHasClassNames ( selectorInitializer , classNames , options ) { if ( ! ( utils . isNonBlankString ( classNames ) || _ . isArray ( classNames ) ) ) { throw new TypeError ( ` ${ typeOf ( classNames ) } ${ classNames } ` ) ; } const opts = new Options ( options , { defaults : { only : false } } ) ; const { only } = opts ; const sel = Selector ( selectorInitializer ) ; await t . expect ( sel . count ) . eql ( 1 , "Selector must return only one DOM element but it doesn't" ) ; classNames = _ . isArray ( classNames ) ? classNames : [ classNames ] ; if ( _ . isEmpty ( classNames ) ) { await t . expect ( sel . classNames ) . eql ( [ '' ] , ` ` ) ; return ; } const classNamesMustPresent = [ ] ; for ( const item of classNames ) { if ( ! ( utils . isNonBlankString ( item ) || _ . isArray ( item ) ) ) { throw new TypeError ( ` ` + ` ${ typeOf ( item ) } ${ item } ` ) ; } let className = item ; let isNot = false ; if ( _ . isArray ( item ) ) { [ className , isNot = false ] = item ; } if ( ! utils . isNonBlankString ( className ) ) { throw new TypeError ( ` ` + ` ${ typeOf ( className ) } ${ className } ` ) ; } if ( ! _ . isBoolean ( isNot ) ) { throw new TypeError ( ` ` + ` ${ typeOf ( isNot ) } ${ isNot } ` ) ; } if ( ! isNot ) { classNamesMustPresent . push ( className ) ; } const assertionName = utils . buildTestCafeAssertionName ( 'ok' , { isNot } ) ; const message = ` ${ isNot ? 'not have' : 'have' } ${ className } ` + ` ${ isNot ? 'does' : "doesn't" } ` ; await t . expect ( sel . hasClass ( className ) ) [ assertionName ] ( message ) ; } if ( only ) { const classNamesMustPresentTxt = _ . join ( classNamesMustPresent , ', ' ) ; const selClassNames = await sel . classNames ; const selClassNamesTxt = _ . join ( selClassNames , ', ' ) ; await t . expect ( selClassNames . length ) . eql ( classNamesMustPresent . length , ` ${ classNamesMustPresentTxt } ${ selClassNamesTxt } ` ) ; } }
Asserts that TestCafe selector initialized using `selectorInitializer` have
 specified (CSS) class names.
Asserts that TestCafe selector initialized using ` selectorInitializer ` have specified ( CSS ) class names .
// `classNames` argument allowed to be a string but we work with array. // --------------------------------------------------------------------------- // Handling case when selector must not have CSS classes at all // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Handling case when selector must have/haven't specified CSS classes // ---------------------------------------------------------------------------