function assertMost(n, msg) {
  if (msg) flag(this, 'message', msg);
  let obj = flag(this, 'object'),
    doLength = flag(this, 'doLength'),
    flagMsg = flag(this, 'message'),
    msgPrefix = flagMsg ? flagMsg + ': ' : '',
    ssfi = flag(this, 'ssfi'),
    objType = _.type(obj).toLowerCase(),
    nType = _.type(n).toLowerCase(),
    errorMessage,
    shouldThrow = true;

  if (doLength && objType !== 'map' && objType !== 'set') {
    new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
  }

  if (!doLength && objType === 'date' && nType !== 'date') {
    errorMessage = msgPrefix + 'the argument to most must be a date';
  } else if (!_.isNumeric(n) && (doLength || _.isNumeric(obj))) {
    errorMessage = msgPrefix + 'the argument to most must be a number';
  } else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
    let printObj = objType === 'string' ? "'" + obj + "'" : obj;
    errorMessage =
      msgPrefix + 'expected ' + printObj + ' to be a number or a date';
  } else {
    shouldThrow = false;
  }

  if (shouldThrow) {
    throw new AssertionError(errorMessage, undefined, ssfi);
  }

  if (doLength) {
    let descriptor = 'length',
      itemsCount;
    if (objType === 'map' || objType === 'set') {
      descriptor = 'size';
      itemsCount = obj.size;
    } else {
      itemsCount = obj.length;
    }
    this.assert(
      itemsCount <= n,
      'expected #{this} to have a ' +
        descriptor +
        ' at most #{exp} but got #{act}',
      'expected #{this} to have a ' + descriptor + ' above #{exp}',
      n,
      itemsCount
    );
  } else {
    this.assert(
      obj <= n,
      'expected #{this} to be at most #{exp}',
      'expected #{this} to be above #{exp}',
      n
    );
  }
}
### .most(n[, msg])

Asserts that the target is a number or a date less than or equal to the given number
or date `n` respectively. However, it's often best to assert that the target is equal to its
expected value.

    expect(1).to.equal(1); // Recommended
    expect(1).to.be.at.most(2); // Not recommended
    expect(1).to.be.at.most(1); // Not recommended

Add `.lengthOf` earlier in the chain to assert that the target's `length`
or `size` is less than or equal to the given number `n`.

    expect('foo').to.have.lengthOf(3); // Recommended
    expect('foo').to.have.lengthOf.at.most(4); // Not recommended

    expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
    expect([1, 2, 3]).to.have.lengthOf.at.most(4); // Not recommended

Add `.not` earlier in the chain to negate `.most`.

    expect(2).to.equal(2); // Recommended
    expect(2).to.not.be.at.most(1); // Not recommended

`.most` accepts an optional `msg` argument which is a custom error message
to show when the assertion fails. The message can also be given as the
second argument to `expect`.

    expect(2).to.be.at.most(1, 'nooo why fail??');
    expect(2, 'nooo why fail??').to.be.at.most(1);

The aliases `.lte` and `.lessThanOrEqual` can be used interchangeably with
`.most`.

@name most
@alias lte
@alias lessThanOrEqual
@param {unknown} n
@param {string} msg _optional_
@namespace BDD
@public