belgattitude/httpx

View on GitHub
packages/plain-object/bench/comparative.bench.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { bench, describe } from 'vitest';

/**
 * Based on a hypothesis:
 */
const realLifeScenarios = [
  ...Array.from({ length: 10 }).map((_) => ({})),
  ...Array.from({ length: 10 }).map((_) => ({
    key1: {
      subkey: [],
    },
  })),
  // Others: not plain objects
  ...Array.from({ length: 10 }).fill(new Map([['key', 10]])),
  ...Array.from({ length: 10 }).fill(new Date()),
  ...Array.from({ length: 10 }).fill(null),
  // eslint-disable-next-line unicorn/no-useless-undefined
  ...Array.from({ length: 10 }).fill(undefined),
  ...Array.from({ length: 10 }).fill(1),
  ...Array.from({ length: 10 }).fill(0),
  ...Array.from({ length: 10 }).fill('str'),
  ...Array.from({ length: 10 }).fill(''),
  ...Array.from({ length: 10 }).fill(Number.NaN),
] as const;

describe(`Compare calling isPlainObject with ${realLifeScenarios.length}x mixed types values`, async () => {
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  const httpxIsPlainObject: (_v: unknown) => boolean = await import(
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore to apply benchmarks assert must be built
    // eslint-disable-next-line import-x/no-unresolved
    '@httpx/plain-object'
  )
    .then(
      (mod) =>
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
        mod.isPlainObject
    )
    .catch((_e) => {
      throw new Error(
        'Comparative benchmarks requires httpx/assert to be built (yarn build)'
      );
    });
  const is = await import('@sindresorhus/is').then((mod) => mod.default);
  const isPlainObj = await import('is-plain-obj').then((mod) => mod.default);
  const lodashIsPlainObject = await import('lodash-es').then(
    (mod) => mod.isPlainObject
  );
  const esToolkitIsPlainObject = await import('es-toolkit').then(
    (mod) => mod.isPlainObject
  );

  const reduxIsPlainObject = await import('redux').then(
    (mod) => mod.isPlainObject
  );

  // @ts-expect-error packaging of this lib is not compatible with latest ts / module
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  const jonschlinkertIsPlainObject = await import('is-plain-object').then(
    // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
    (mod) => mod.isPlainObject
  );

  bench('@httpx/plain-object: `isPlainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      httpxIsPlainObject(value);
    }
  });

  bench('(sindresorhus/)is-plain-obj: `isPlainObj(v)`', () => {
    for (const value of realLifeScenarios) {
      isPlainObj(value);
    }
  });

  bench('@sindresorhus/is: `is.plainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      is.plainObject(value);
    }
  });

  bench('estoolkit:  `isPlainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      esToolkitIsPlainObject(value);
    }
  });

  bench('redux:  `isPlainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      reduxIsPlainObject(value);
    }
  });

  bench('(jonschlinkert/)is-plain-object: `isPlainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
      jonschlinkertIsPlainObject(value);
    }
  });

  bench('lodash-es: `_.isPlainObject(v)`', () => {
    for (const value of realLifeScenarios) {
      lodashIsPlainObject(value);
    }
  });
});