All files / src/vitest concrete.ts

100% Statements 51/51
100% Branches 8/8
100% Functions 4/4
100% Lines 51/51

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113            1x 1x                       1x 29x 29x 29x 29x 29x 29x 29x 29x                 1x 1x 1x 1x 1x   1x       1x       1x 1x 1x 1x 1x 1x 1x 1x                 1x 1x 8x 8x 8x   8x       20x       20x 20x 20x 20x 20x 20x 20x 20x                   1x 1x 5x 5x 5x           5x 5x 5x 5x 5x  
import {Monoid as MO, Semigroup as SE} from '@effect/typeclass'
import {Equivalence as EQ} from 'effect'
import type {TypeLambda} from 'effect/HKT'
import fc from 'fast-check'
import type {ParameterOverrides} from '../law.js'
import type {Concrete, ConcreteGiven} from '../laws.js'
import {buildConcreteTypeclassLaws} from '../laws.js'
import {testLawSets} from './testLaws.js'
/**
 * Test [concrete type](https://github.com/Effect-TS/effect/blob/main/packages/typeclass/README.md#concrete-types)
 * typeclass laws for the given instances of some datatype.
 * @param instances - Instances to test. Key is typeclass name and value is the
 * instance under test. For example, `{ Equivalence: Number.Equivalence }` will run
 * the instance through the `Equivalence` typeclass laws.
 * @param given - The common concrete options: equivalence and an arbitrary
 * for the underlying type of the test.
 * @param parameters - Optional runtime `fast-check` parameters.
 * @category vitest
 */
export const testConcreteTypeclassLaws = <A>(
  instances: Partial<Concrete<A>>,
  given: Omit<ConcreteGiven<TypeLambda, A>, 'F'>,
  parameters?: ParameterOverrides,
) => {
  testLawSets({verbose: true, ...parameters})(
    ...buildConcreteTypeclassLaws(instances, given),
  )
}
 
/**
 * Run the given Semigroup instance through the Semigroup typeclass laws tests.
 * @param a - An arbitrary for the underlying type `A`.
 * @param equalsA - Equivalence for the underlying type `A`.
 * @param parameters - Optional runtime `fast-check` parameters.
 * @category vitest
 */
export const testSemigroup =
  <A>(
    a: fc.Arbitrary<A>,
    equalsA: EQ.Equivalence<A>,
    parameters?: ParameterOverrides,
  ) =>
  (
    /**
     * The semigroup under test.
     */
    Semigroup: SE.Semigroup<A>,
    /**
     * Optional suffix will be added to `description()` block label.
     */
    suffix = '',
  ) => {
    testConcreteTypeclassLaws(
      {Semigroup},
      {suffix, a, equalsA},
      {verbose: true, ...parameters},
    )
  }
 
/**
 * Run the given monoid instance through the Monoid typeclass laws tests.
 * @param a - An arbitrary for the underlying type `A`.
 * @param equalsA - Equivalence for the underlying type `A`.
 * @param parameters - Optional runtime `fast-check` parameters.
 * @category vitest
 */
export const testMonoid =
  <A>(
    a: fc.Arbitrary<A>,
    equalsA: EQ.Equivalence<A>,
    parameters?: ParameterOverrides,
  ) =>
  (
    /**
     * The monoid under test.
     */
    Monoid: MO.Monoid<A>,
    /**
     * Optional suffix will be added to `description()` block label.
     */
    suffix = '',
  ) => {
    testConcreteTypeclassLaws(
      {Monoid},
      {suffix, a, equalsA},
      {verbose: true, ...parameters},
    )
  }
 
/**
 * Run the given monoid/semigroup instances through their respective typeclass
 * law tests.
 * @param a - An arbitrary for the underlying type `A`.
 * @param equalsA - Equivalence for the underlying type `A`.
 * @param parameters - Optional runtime `fast-check` parameters.
 * @category vitest
 */
export const testMonoids =
  <A>(
    a: fc.Arbitrary<A>,
    equalsA: EQ.Equivalence<A>,
    parameters?: ParameterOverrides,
  ) =>
  /**
   * Named list of `Monoid` instances to test in the form of an object where
   * the keys are the instances names and the values the instances themselves.
   */
  (namedInstances: Record<string, MO.Monoid<A>>) => {
    const test = testMonoid(a, equalsA, parameters)
    for (const [suffix, Monoid] of Object.entries(namedInstances))
      test(Monoid, suffix)
  }