UnitTest.test('foldl concat ys xs === reverse(xs) ++ ys', () => {
  fc.assert(fc.property(
    fc.array(fc.integer()),
    fc.array(fc.integer()),
    (xs, ys) => {
      const output = Arr.foldl(xs, (b, a) => [ a ].concat(b), ys);
      Assert.eq('eq', Arr.reverse(xs).concat(ys), output);
    }
  ));
})


unknown

UnitTest.test('Arr.flatten: consistent with chunking', () => {
  fc.assert(fc.property(
    fc.array(fc.integer()),
    fc.integer(1, 5),
    (arr, chunkSize) => {
      const chunks = Arr.chunk(arr, chunkSize);
      const bound = Arr.flatten(chunks);
      return Assert.eq('chunking', arr, bound);
    }
  ));
})


UnitTest.test('Arr.flatten: Wrap then flatten array is identity', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    Assert.eq('wrap then flatten', Arr.flatten(Arr.pure(arr)), arr);
  }));
})


UnitTest.test('Mapping pure then flattening array is identity', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    Assert.eq('map pure then flatten', Arr.flatten(Arr.map(arr, Arr.pure)), arr);
  }));
})


UnitTest.test('Flattening two lists === concat', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.array(fc.integer()), (xs, ys) => {
    Assert.eq('flatten/concat', Arr.flatten([ xs, ys ]), xs.concat(ys));
  }));
})


UnitTest.test('Arr.findIndex: Element found passes predicate', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    const pred = (x) => x % 3 === 0;
    return Arr.findIndex(arr, pred).forall((x) => pred(arr[x]));
  }));
})


UnitTest.test('Arr.findIndex: consistent with exists', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    const pred = (x) => x % 6 === 0;
    Assert.eq('findIndex vs find', Arr.exists(arr, pred), Arr.findIndex(arr, pred).isSome());
  }));
})


UnitTest.test('Element exists in middle of array', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.integer(), fc.array(fc.integer()), (prefix, element, suffix) => {
    const arr2 = Arr.flatten([ prefix, [ element ], suffix ]);
    Assert.eq('in array', true, Arr.exists(arr2, eqc(element)));
  }));
})


UnitTest.test('Element exists in singleton array of itself', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (i) => {
    Assert.eq('in array', true, Arr.exists([ i ], eqc(i)));
  }));
})


UnitTest.test('Element does not exist in empty array', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (i) => {
    Assert.eq('not in empty array', false, Arr.exists([], eqc(i)));
  }));
})


UnitTest.test('Element not found when predicate always returns false', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => !Arr.exists(arr, never)));
})


UnitTest.test('Element exists in non-empty array when predicate always returns true', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.integer(), (xs, x) => {
    const arr = Arr.flatten([ xs, [ x ]]);
    return Arr.exists(arr, always);
  }));
})


UnitTest.test('difference: ∀ xs ys. x ∈ xs -> x ∉ (ys - xs)', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.array(fc.integer()), (xs, ys) => {
    const diff = Arr.difference(ys, xs);
    return Arr.forall(xs, (x) => !Arr.contains(diff, x));
  }));
})


UnitTest.test('difference: ∀ xs ys. x ∈ (ys - xs) -> x ∉ ys', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.array(fc.integer()), (xs, ys) => {
    const diff = Arr.difference(ys, xs);
    return Arr.forall(diff, (d) => Arr.contains(ys, d));
  }));
})


UnitTest.test('Arr.contains: array contains element', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.integer(), fc.array(fc.integer()), (prefix, element, suffix) => {
    const arr2 = Arr.flatten([ prefix, [ element ], suffix ]);
    Assert.eq('in array', true, Arr.contains(arr2, element));
  }));
})


UnitTest.test('Check not :: not(not(f(x))) === f(x)', () => {
  fc.assert(fc.property(fc.json(), fc.func(fc.boolean()), (x, f) => {
    const g = Fun.not(Fun.not(f));
    Assert.eq('eq', f(x), g(x));
  }));
})

Summary: `Fun.not` applied twice to a function should yield the original function's result for a given input.


UnitTest.test('Arr.find: value not found', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    const result = Arr.find(arr, () => false);
    Assert.eq('Element not found in array', Optional.none(), result, tOptional(tNumber));
  }));
})

Summary: `Arr.find` should return `Optional.none()` when no element is found in the array.


UnitTest.test('Chunking should create an array of the appropriate length except for the last one', () => {
  fc.assert(fc.property(
    fc.array(fc.integer()),
    fc.nat(),
    (arr, rawChunkSize) => {
      // ensure chunkSize is at least one
      const chunkSize = rawChunkSize + 1;
      const chunks = Arr.chunk(arr, chunkSize);

      const hasRightSize = (part) => part.length === chunkSize;

      const numChunks = chunks.length;
      const firstParts = chunks.slice(0, numChunks - 1);
      Assert.eq('Incorrect chunk size', true, Arr.forall(firstParts, hasRightSize));
      if (arr.length === 0) {
        Assert.eq('empty', [], chunks, tArray(tArray(tNumber)));
      } else {
        Assert.eq('nonEmpty', true, chunks[chunks.length - 1].length <= chunkSize);
      }
    }
  ));
})


UnitTest.test('Arr.sort: idempotency', () => {
  fc.assert(fc.property(
    fc.array(fc.nat()), (arr) => {
      Assert.eq('idempotency', Arr.sort(arr), Arr.sort(Arr.sort(arr)), tArray(tNumber));
    }
  ));
})


UnitTest.test('Arr.findMap finds an element', () => {
  fc.assert(fc.property(
    fc.array(fc.integer()),
    fc.integer(),
    fc.integer(),
    fc.array(fc.integer()),
    (prefix, element, ret, suffix) => {
      const arr = [ ...prefix, element, ...suffix ];
      Assert.eq('eq', Optional.some(ret), Arr.findMap(arr, (x) => Optionals.someIf(x === element, ret)), tOptional());
    }
  ));
})

Summary: `Arr.findMap` should return an `Optional` containing a specified return value when an element in the array satisfies a given condition.


UnitTest.test('Arr.bind: binding an array of empty arrays with identity equals an empty array', () => {
  fc.assert(fc.property(fc.array(fc.constant<number[]>([])), (arr) => {
    Assert.eq('bind empty arrays', [], Arr.bind(arr, Fun.identity), tArray(tNumber));
  }));
})


UnitTest.test('Arr.bind: bind (pure .) is map', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.integer(), (arr, j) => {
    const f = (x: number) => x + j;
    Assert.eq('bind pure', Arr.map(arr, f), Arr.bind(arr, Fun.compose(Arr.pure, f)), tArray(tNumber));
  }));
})


UnitTest.test('Arr.bind: Monad Law: left identity', () => {
  fc.assert(fc.property(fc.integer(), fc.integer(), (i, j) => {
    const f = (x: number) => [ x, j, x + j ];
    Assert.eq('left id', f(i), Arr.bind(Arr.pure(i), f), tArray(tNumber));
  }));
})


UnitTest.test('Arr.bind: Monad Law: right identity', () => {
  fc.assert(fc.property(fc.array(fc.integer()), (arr) => {
    Assert.eq('right id', arr, Arr.bind(arr, Arr.pure), tArray(tNumber));
  }));
})


UnitTest.test('Arr.bind: Monad Law: associativity', () => {
  fc.assert(fc.property(fc.array(fc.integer()), fc.integer(), (arr, j) => {
    const f = (x: number) => [ x, j, x + j ];
    const g = (x: number) => [ j, x, x + j ];
    Assert.eq('assoc', Arr.bind(arr, (x) => Arr.bind(f(x), g)), Arr.bind(Arr.bind(arr, f), g), tArray(tNumber));
  }));
})


UnitTest.test('KAssert.eqResult: fail', () => {
  fc.assert(fc.property(twoDifferentNumbers, ([ a, b ]) => {
    Assert.throws('value(a) != (value(!a)) #1', () => {
      KAssert.eqResult('eq', Result.value(a), Result.value(b));
    });
    Assert.throws('value(a) != (value(!a)) #2', () => {
      KAssert.eqResult('eq', Result.value(a), Result.value(b), tNumber);
    });
    Assert.throws('value(a) != (value(!a)) #2', () => {
      KAssert.eqResult('eq', Result.value(a), Result.value(b), tNumber, tBoom());
    });
  }));

  fc.assert(fc.property(twoDifferentNumbers, ([ a, b ]) => {
    Assert.throws('error(a) != (error(!a)) #1', () => {
      KAssert.eqResult('eq', Result.error(a), Result.error(b));
    });
    Assert.throws('error(a) != (error(!a)) #2', () => {
      KAssert.eqResult('eq', Result.error(a), Result.error(b), tBoom());
    });
    Assert.throws('result(a) != (result(!a)) #2', () => {
      KAssert.eqResult('eq', Result.error(a), Result.error(b), tBoom(), tNumber);
    });
  }));

  fc.assert(fc.property(fc.integer(), fc.string(), (i, s) => {
    Assert.throws('value != error #1', () => {
      KAssert.eqResult('eq', Result.value(i), Result.error(s));
    });
    Assert.throws('value != error #2', () => {
      KAssert.eqResult('eq', Result.value(i), Result.error(s), tBoom());
    });
    Assert.throws('value != error #3', () => {
      KAssert.eqResult('eq', Result.value(i), Result.error(s), tBoom());
    });

    Assert.throws('error != value #1', () => {
      KAssert.eqResult('eq', Result.error(i), Result.value(s));
    });
    Assert.throws('error != value #2', () => {
      KAssert.eqResult('eq', Result.error(i), Result.value(s), tBoom());
    });
    Assert.throws('error != value #3', () => {
      KAssert.eqResult('eq', Result.error(i), Result.value(s), tBoom(), tBoom());
    });
  }));
})

Summary: `KAssert.eqResult` throws an exception when comparing different result types, such as different `value` results, different `error` results, and `value` vs. `error` results.


UnitTest.test('KAssert.eqSome: success (reflexivity)', () => {
  fc.assert(fc.property(fc.integer(), (i) => {
    KAssert.eqSome('eq', i, Optional.some(i));
    KAssert.eqSome('eq', i, Optional.some(i), tNumber);
  }));
})


UnitTest.test('KAssert.eqSome: failure', () => {
  fc.assert(fc.property(twoDifferentNumbers, ([ a, b ]) => {
    Assert.throws('some(i) != some(!i) #1', () => {
      KAssert.eqSome('eq', a, Optional.some(b));
    });
  }));
  fc.assert(fc.property(twoDifferentNumbers, ([ a, b ]) => {
    Assert.throws('some(i) != some(!i) #2', () => {
      KAssert.eqSome('eq', a, Optional.some(b), tNumber);
    });
  }));
})


UnitTest.test('KAssert.eqNone: failure', () => {
  fc.assert(fc.property(fc.integer(), (i) => {
    Assert.throws('some(i) != none', () => {
      KAssert.eqNone('eq', Optional.some(i));
    });
  }));
})


UnitTest.test('KAssert.eqOption: success (reflexivity)', () => {
  fc.assert(fc.property(fc.integer(), (i) => {
    KAssert.eqOptional('eq', Optional.some(i), Optional.some(i));
    KAssert.eqOptional('eq', Optional.some(i), Optional.some(i), tNumber);
  }));
  KAssert.eqOptional('eq', Optional.none(), Optional.none());
})


it('should reject non-positive and non-integer numbers', () => {
      fc.assert(
        fc.property(
          fc.oneof(
            fc.integer({ min: -1000, max: 0 }), // Non-positive integers
            fc
              .float({ min: Math.fround(0.1), max: Math.fround(1000) })
              .filter(n => !Number.isInteger(n)) // Only non-integers
          ),
          num => {
            const result = isPositiveInteger(num);
            expect(result).toBe(false);
          }
        )
      );
    })

Summary: `isPositiveInteger` should return false for non-positive and non-integer numbers.


it('should validate non-negative numbers correctly', () => {
      fc.assert(
        fc.property(
          fc.float({ min: 0, max: Math.fround(1000), noNaN: true }),
          num => {
            const result = isNonNegativeNumber(num);
            expect(result).toBe(true);
          }
        )
      );
    })

Summary: `isNonNegativeNumber` validates that a given float number is non-negative.


it('should validate regex patterns correctly', () => {
      fc.assert(
        fc.property(fc.string(), str => {
          const validator = createRegexValidator(/^[a-zA-Z]+$/);
          const result = validator(str);
          const expected = /^[a-zA-Z]+$/.test(str);
          expect(result).toBe(expected);
        })
      );
    })

Summary: `createRegexValidator` correctly validates strings against a regex pattern for alphabetical characters only.


it('should always return object with valid boolean', () => {
      fc.assert(
        fc.property(fc.string(), password => {
          const result = validatePassword(password);
          return (
            typeof result === 'object' &&
            typeof result.valid === 'boolean' &&
            (result.valid || typeof result.reason === 'string')
          );
        })
      );
    })

Summary: The function `validatePassword` should consistently return an object containing a `valid` boolean, and if `valid` is false, the object should also contain a `reason` string.


it('should consistently return boolean values', () => {
    fc.assert(
      fc.property(fc.string(), input => {
        const result = isValidEmail(input);
        expect(typeof result).toBe('boolean');
      })
    );
  })

Summary: `isValidEmail` consistently returns boolean values for any string input.


it('should always return object with isValid and errors properties', () => {
    fc.assert(
      fc.property(fc.string(), password => {
        const result = validatePasswordStrength(password);

        expect(typeof result.isValid).toBe('boolean');
        expect(Array.isArray(result.errors)).toBe(true);
        expect(result.isValid === (result.errors.length === 0)).toBe(true);
      })
    );
  })

Summary: `validatePasswordStrength` returns an object containing `isValid` as a boolean and `errors` as an array, with `isValid` being true if `errors` is empty.


it('should be monotonic (adding items never decreases total)', () => {
      fc.assert(
        fc.property(
          generators.items(),
          generators.items(),
          (items1, items2) => {
            const total1 = calculateTotal(items1);
            const total2 = calculateTotal([...items1, ...items2]);

            expect(total2).toBeGreaterThanOrEqual(total1);
          }
        )
      );
    })

Summary: Adding items to a list should not decrease the calculated total.


it('should equal sum of individual items', () => {
      fc.assert(
        fc.property(
          fc.array(
            fc.record({
              price: fc.float({ min: 0, max: Math.fround(100), noNaN: true }),
              quantity: fc.integer({ min: 0, max: 10 }),
            }),
            { maxLength: 5 }
          ),
          items => {
            const total = calculateTotal(items);
            const manual = items.reduce(
              (sum, item) => sum + item.price * item.quantity,
              0
            );
            expect(total).toBeCloseTo(manual, 10);
          }
        )
      );
    })

Summary: `calculateTotal` should equal the sum of items' prices multiplied by their quantities across an array.


it('should never return discount greater than price', () => {
      fc.assert(
        fc.property(
          fc.float({ min: 0, max: Math.fround(10000), noNaN: true }),
          fc.float({ min: 0, max: Math.fround(100), noNaN: true }),
          (price, discountPercent) => {
            const discount = calculateDiscount(price, discountPercent);
            expect(discount).toBeLessThanOrEqual(price);
            expect(discount).toBeGreaterThanOrEqual(0);
          }
        )
      );
    })

Summary: The calculated discount should always be between 0 and the original price.


it('should be monotonic (higher discount % = higher discount amount)', () => {
      fc.assert(
        fc.property(
          fc.float({ min: 1, max: Math.fround(1000), noNaN: true }),
          fc.float({ min: 0, max: Math.fround(50), noNaN: true }),
          fc.float({ min: 0, max: Math.fround(50), noNaN: true }),
          (price, discount1, discount2) => {
            const [lower, higher] =
              discount1 <= discount2
                ? [discount1, discount2]
                : [discount2, discount1];

            const discountAmount1 = calculateDiscount(price, lower);
            const discountAmount2 = calculateDiscount(price, higher);

            expect(discountAmount1).toBeLessThanOrEqual(discountAmount2);
          }
        )
      );
    })

Summary: Higher discount percentages should yield higher discount amounts.


t.notThrows(() => {
    fc.assert(equivalentToSecp256k1Node);
  })


t.notThrows(() => {
    fc.assert(reversesUncompress);
    fc.assert(equivalentToSecp256k1Node);
    fc.assert(equivalentToElliptic);
  })


t.notThrows(() => {
    fc.assert(isEquivalentToDeriveUncompressedThenCompress);
    fc.assert(equivalentToSecp256k1Node);
    fc.assert(equivalentToElliptic);
  })


t.notThrows(() => {
    fc.assert(isEquivalentToDeriveCompressedThenUncompress);
    fc.assert(equivalentToSecp256k1Node);
    fc.assert(equivalentToElliptic);
  })


t.notThrows(() => {
    fc.assert(malleationIsJustNegation);
  })


t.notThrows(() => {
    fc.assert(malleateThenNormalizeEqualsInitial);
    fc.assert(equivalentToSecp256k1Node);
  })


t.notThrows(() => {
    fc.assert(equivalentToSecp256k1Node);
    fc.assert(equivalentToElliptic);
  })


t.notThrows(() => {
    fc.assert(reversesCompress);
    fc.assert(equivalentToSecp256k1Node);
  })


t.notThrows(() => {
    fc.assert(createsValidSignatures);
  })


t.notThrows(() => {
      fc.assert(equivalentToSinglePass);
    })


t.notThrows(() => {
    fc.assert(roundTripWithPayloadLength(20));
    fc.assert(roundTripWithPayloadLength(24));
    fc.assert(roundTripWithPayloadLength(28));
    fc.assert(roundTripWithPayloadLength(32));
    fc.assert(roundTripWithPayloadLength(40));
    fc.assert(roundTripWithPayloadLength(48));
    fc.assert(roundTripWithPayloadLength(56));
    fc.assert(roundTripWithPayloadLength(64));
  })


t.notThrows(() => {
    fc.assert(correctsUpToTwoErrors(20));
    fc.assert(correctsUpToTwoErrors(24));
    fc.assert(correctsUpToTwoErrors(28));
    fc.assert(correctsUpToTwoErrors(32));
    fc.assert(correctsUpToTwoErrors(40));
    fc.assert(correctsUpToTwoErrors(48));
    fc.assert(correctsUpToTwoErrors(56));
    fc.assert(correctsUpToTwoErrors(64));
  })


it('takes the first n from a list', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: -1000, max: 1000 }),
          fc.nat(1000),
          (len, num) => {
            const a = Range(0, len).toArray();
            const v = List(a);
            expect(v.take(num).toArray()).toEqual(a.slice(0, num));
          }
        )
      );
    })

Summary: Verifies that taking the first `n` elements from a list matches the expected slice of an array with the same elements.


it('is not dependent on order', () => {
    fc.assert(
      fc.property(genHeterogeneousishArray, (vals) => {
        expect(
          is(
            Seq<string | number>(shuffle(vals.slice())).min(),
            Seq<string | number>(vals).min()
          )
        ).toEqual(true);
      })
    );
  })

Summary: `Seq.min()` produces consistent results regardless of the order of elements in the input array.


it('behaves the same as Array.join', () => {
    fc.assert(
      fc.property(fc.array(genPrimitive), genPrimitive, (array, joiner) => {
        // @ts-expect-error unexpected values for typescript joiner, but valid at runtime despite the unexpected errors
        expect(Seq(array).join(joiner)).toBe(array.join(joiner));
      })
    );
  })

Summary: `Seq(array).join(joiner)` produces the same result as `array.join(joiner)` for arrays of primitive values.


it('generates unsigned 31-bit integers', () => {
    fc.assert(
      fc.property(genValue, (value) => {
        const hashVal = hash(value);
        expect(Number.isInteger(hashVal)).toBe(true);
        expect(hashVal).toBeGreaterThan(-(2 ** 31));
        expect(hashVal).toBeLessThan(2 ** 31);
      })
    );
  })

Summary: The `hash` function generates unsigned 31-bit integers for given values.


it('slices the same as array slices', () => {
    fc.assert(
      fc.property(
        shrinkInt,
        shrinkInt,
        shrinkInt,
        shrinkInt,
        (from, to, begin, end) => {
          const r = Range(from, to);
          const a = r.toArray();
          expect(r.slice(begin, end).toArray()).toEqual(a.slice(begin, end));
        }
      )
    );
  })

Summary: The result of slicing a `Range` should match the result of slicing its array equivalent.


it('deletes down to empty map', () => {
    fc.assert(
      fc.property(fc.nat(100), (size) => {
        let m = Range(0, size).toMap();
        expect(m.size).toBe(size);
        for (let ii = size - 1; ii >= 0; ii--) {
          m = m.remove(ii);
          expect(m.size).toBe(ii);
        }
        expect(m).toBe(Map());
      })
    );
  })

Summary: A map created from a range should decrease in size with each deletion until it becomes an empty map.


it('sets', () => {
    fc.assert(
      fc.property(fc.nat(100), (len) => {
        let map = Map();
        for (let ii = 0; ii < len; ii++) {
          expect(map.size).toBe(ii);
          map = map.set('' + ii, ii);
        }
        expect(map.size).toBe(len);
        expect(is(map.toSet(), Range(0, len).toSet())).toBe(true);
      })
    );
  })

Summary: A `Map` object has the same number of elements as the number of `set` operations performed, and converting it to a set matches a range set from 0 to the number of operations.


it('has and get', () => {
    fc.assert(
      fc.property(fc.nat(100), (len) => {
        const map = Range(0, len)
          .toKeyedSeq()
          .mapKeys((x) => '' + x)
          .toMap();
        for (let ii = 0; ii < len; ii++) {
          expect(map.get('' + ii)).toBe(ii);
          expect(map.has('' + ii)).toBe(true);
        }
      })
    );
  })

Summary: `Map` correctly retrieves and confirms the existence of stringified numeric keys within a mapped sequence.


it('deletes', () => {
    fc.assert(
      fc.property(fc.nat(100), (len) => {
        let map = Range(0, len).toMap();
        for (let ii = 0; ii < len; ii++) {
          expect(map.size).toBe(len - ii);
          map = map.remove(ii);
        }
        expect(map.size).toBe(0);
        expect(map.toObject()).toEqual({});
      })
    );
  })

Summary: The map should decrease in size by one for each deletion and be empty with a size of zero and an empty object after all elements are removed.


it('toJS isomorphic value', () => {
    fc.assert(
      fc.property(fc.jsonValue(), (v: JsonValue) => {
        const imm = fromJS(v);
        expect(
          // @ts-expect-error Property 'toJS' does not exist on type '{}'.ts(2339)
          imm && imm.toJS ? imm.toJS() : imm
        ).toEqual(v);
      }),
      { numRuns: 30 }
    );
  })

Summary: The conversion from a JSON value to an immutable object using `fromJS` and back to a JSON value using `toJS` should preserve equality with the original JSON value.


it('pop removes the highest index, just like array', () => {
    fc.assert(
      fc.property(fc.nat(100), (len) => {
        const a = arrayOfSize(len);
        let v = List(a);

        while (a.length) {
          expect(v.size).toBe(a.length);
          expect(v.toArray()).toEqual(a);
          v = v.pop();
          a.pop();
        }
        expect(v.size).toBe(a.length);
        expect(v.toArray()).toEqual(a);
      })
    );
  })

Summary: `List.pop()` should remove the highest index element, matching the behavior of native JavaScript arrays.


it('iterates through List in reverse', () => {
      fc.assert(
        fc.property(pInt, pInt, (start, len) => {
          const l1 = Range(0, start + len).toList();
          const l2: List<number> = l1.slice(start, start + len);
          const s = l2.toSeq().reverse(); // impl calls List.__iterator(REVERSE)
          expect(s.size).toBe(len);
          const valueIter = s.values();
          const keyIter = s.keys();
          const entryIter = s.entries();
          for (let ii = 0; ii < len; ii++) {
            expect(valueIter.next().value).toBe(start + len - 1 - ii);
            expect(keyIter.next().value).toBe(ii);
            expect(entryIter.next().value).toEqual([ii, start + len - 1 - ii]);
          }
        })
      );
    })

Summary: Iterating through a sliced `List` in reverse should correctly yield values, keys, and entries in expected reverse order.


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(MAC(), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.true;
          })
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(invertedRegex(regExp.MAC), async testValue => {
            input!.value = testValue;
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 4, maxLength: 4 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 5 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 4', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 3, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 4 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 3', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 2 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0, max: 7 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 8 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('edits name attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tAsciName, 1, 32), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.true;
          })
        );
      })


it('rejects name attribute starting with decimals', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.false;
          })
        );
      })


it('edits smpRate attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async smpRate => {
              inputs[4].value = smpRate;
              await (<WizardTextField>inputs[4]).requestUpdate();
              expect(inputs[4].checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects smpRate attribute in case input is not unsigned int', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async smpRate => {
              inputs[4].value = smpRate;
              await (<WizardTextField>inputs[4]).requestUpdate();
              expect(inputs[4].checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits nofASDU attribute only for valid inputs', async () => {
        const input = <WizardTextField>inputs[5];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async nofASDU => {
              input.value = nofASDU;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects nofASDU attribute in case input is not unsigned int', async () => {
        const input = <WizardTextField>inputs[5];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async nofASDU => {
              input.value = nofASDU;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits bufTime attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async bufTime => {
              inputs[6].value = bufTime;
              await (<WizardTextField>inputs[6]).requestUpdate();
              expect(inputs[6].checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects bufTime attribute starting with not being a unsigned int', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async bufTime => {
              inputs[6].value = bufTime;
              await (<WizardTextField>inputs[6]).requestUpdate();
              expect(inputs[6].checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits intgPd attribute only for valid inputs', async () => {
        const input = <WizardTextField>inputs[7];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async intgPd => {
              input.value = intgPd;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects intgPd attribute starting with not being a unsigned int', async () => {
        const input = <WizardTextField>inputs[7];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(regexString(inverseRegExp.uint, 1), async intgPd => {
            input.value = intgPd;
            await input.requestUpdate();
            expect(input.checkValidity()).to.be.false;
          })
        );
      })


it('edits prefix attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tAsciName, 1, 11), async name => {
            inputs[2].value = name;
            await (<WizardTextField>inputs[2]).requestUpdate();
            expect(inputs[2].checkValidity()).to.be.true;
          })
        );
      })


it('rejects name attribute starting with decimals', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
            inputs[2].value = name;
            await (<WizardTextField>inputs[2]).requestUpdate();
            expect(inputs[2].checkValidity()).to.be.false;
          })
        );
      })


it('edits name attribute only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tAsciName, 1, 32), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.true;
        })
      );
    })


it('rejects name attribute starting with decimals', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.false;
        })
      );
    })


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV4(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv4), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 1, 8), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSI), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSI, 1, 16),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSIAPi, 1), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSIAPi), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSIid, 1, 5),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSIid), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSI, 1, 40),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 3, 3), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(/^[0-7]$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-7]$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              nat({ max: 65535 }).map(num => `${num}`),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-9]*$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(/^\S*$/, 1), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              integer({ min: 1025, max: 65535 }).map(num => `${num}`),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV6(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv6), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV6SubNet(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-9/]*$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              fc.hexaString({ minLength: 1, maxLength: 5 }),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              invertedRegex(/^[0-9a-fA-F]{1,5}$/),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.false;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              nat({ max: 255 }).map(num => `${num}`),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV4(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv4), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 1, 2), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSI), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('edits name attribute only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(regExp.abstractDataAttributeName, 1, 32),
          async name => {
            nameTextField.value = name;
            await nameTextField.requestUpdate();
            expect(nameTextField.checkValidity()).to.be.true;
          }
        )
      );
    })


it('rejects name attribute starting with decimals', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.false;
        })
      );
    })


it('for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            regexString(regExp.lnClass, 4, 4),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tName, 1), async name => {
          parent.wizardUI.inputs[0].value = name;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.desc), async desc => {
          parent.wizardUI.inputs[1].value = desc;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.unsigned, 1), async nomFreq => {
          parent.wizardUI.inputs[2].value = nomFreq;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[2].checkValidity()).to.be.true;
        })
      );
    })


it('rejects action for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.unsigned, 1),
          async nomFreq => {
            parent.wizardUI.inputs[2].value = nomFreq;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[2].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(fc.integer(1, 255), async numPhases => {
          parent.wizardUI.inputs[3].value = String(numPhases);
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[3].checkValidity()).to.be.true;
        })
      );
    })


it('rejects edition for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.integer, 1),
          async nomFreq => {
            parent.wizardUI.inputs[3].value = nomFreq;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[3].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal), async nomFreq => {
          parent.wizardUI.inputs[4].value = nomFreq;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[4].checkValidity()).to.be.true;
        })
      );
    })


it('rejects edition for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.decimal, 1),
          async voltage => {
            parent.wizardUI.inputs[4].value = voltage;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[4].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tName, 1), async name => {
          parent.wizardUI.inputs[1].value = name;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.desc), async desc => {
          parent.wizardUI.inputs[2].value = desc;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tName, 1), async name => {
            parent.wizardUI.inputs[0].value = name;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.desc), async desc => {
            parent.wizardUI.inputs[1].value = desc;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.desc, 1), async type => {
            parent.wizardUI.inputs[2].value = type;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[2].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal), async BitRate => {
            parent.wizardUI.inputs[3].value = BitRate;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[3].checkValidity()).to.be.true;
          })
        );
      })


it('rejects edition for invalid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.decimal, 1),
            async BitRate => {
              parent.wizardUI.inputs[3].value = BitRate;
              await parent.updateComplete;
              expect(parent.wizardUI.inputs[3].checkValidity()).to.be.false;
            }
          )
        );
      })


it("generated random strings with given length", () => {
    fc.assert(
      fc.property(fc.integer({ min: 0, max: 256 }), (n) => {
        expect(nanoid(n).length).toBe(n);
      })
    );
  })

Summary: `nanoid` generates random strings of the specified length.


test("subscribing once", () => {
    fc.assert(
      fc.property(
        anything(),

        (payload) => {
          const callback = jest.fn();
          const hub = makeEventSource();

          const dereg1 = hub.observable.subscribeOnce(callback);
          hub.notify(payload);
          hub.notify(payload);
          hub.notify(payload);

          expect(callback).toHaveBeenCalledTimes(1); // Called only once, not three times
          for (const [arg] of callback.mock.calls) {
            expect(arg).toBe(payload);
          }

          // Deregistering has no effect
          dereg1();
          hub.notify(payload);
          expect(callback).toHaveBeenCalledTimes(1); // Called only once, not three times
        }
      )
    );
  })

Summary: Subscribing once to an event source should result in the callback being called exactly once with the correct payload, regardless of the number of notifications and deregistrations.


describe("Continuous and discrete splits", () => {
  makeTest({
    name: "is empty, with no common elements",
    data: [1.33455, 1.432, 2.0],
    minWeight: 2,
    continuous: [1.33455, 1.432, 2.0],
    discrete: { xs: [], ys: [] },
  });

  makeTest({
    name: "only stores 3.5 as discrete when minWeight is 3",
    data: [1.33455, 1.432, 2.0, 2.0, 3.5, 3.5, 3.5],
    minWeight: 3,
    continuous: [1.33455, 1.432, 2.0, 2.0],
    discrete: { xs: [3.5], ys: [3] },
  });

  makeTest({
    name: "doesn't store 3.5 as discrete when minWeight is 5",
    data: [1.33455, 1.432, 2.0, 2.0, 3.5, 3.5, 3.5],
    minWeight: 5,
    continuous: [1.33455, 1.432, 2.0, 2.0, 3.5, 3.5, 3.5],
    discrete: { xs: [], ys: [] },
  });

  makeTest({
    name: "more general test",
    data: [10, 10, 11, 11, 11, 12, 13, 13, 13, 13, 13, 14],
    minWeight: 3,
    continuous: [10, 10, 12, 14],
    discrete: { xs: [11, 13], ys: [3, 5] },
  });

  const makeDuplicatedArray = (count: number) => {
    const arr = range(1, count + 1);
    return [...arr, ...arr, ...arr, ...arr].sort((a, b) => a - b);
  };

  test("split at count=10", () => {
    expect(split(makeDuplicatedArray(10), 2).discreteShape.xs.length).toEqual(
      10
    );
  });

  test("split at count=500", () => {
    expect(split(makeDuplicatedArray(500), 2).discreteShape.xs.length).toEqual(
      500
    );
  });

  // Function for fast-check property testing
  const testSegments = (counts: number[], weight: number) => {
    // Prepare segments of random-length equal numbers
    const segments: number[][] = [];
    let cur = 0;
    for (const count of counts) {
      cur += 0.01 + Math.random(); // random() can produce 0
      const segment: number[] = [];
      for (let i = 0; i < count; i++) {
        segment.push(cur);
      }
      segments.push(segment);
    }
    const allValues = flatten(segments);
    const result = split(allValues, weight);

    // Then split based on the segment length directly
    const contSegments = segments.filter((s) => s.length < weight);
    const discSegments = segments.filter((s) => s.length >= weight);

    expect(result.continuousSamples).toEqual(flatten(contSegments));
    expect(result.discreteShape).toEqual({
      xs: discSegments.map((s) => s[0]),
      ys: discSegments.map((s) => s.length),
    });
  };

  fc.assert(
    fc.property(
      fc.array(fc.integer({ max: 30 }), { minLength: 0, maxLength: 50 }), // random lengths of segments of equal values
      fc.integer({ min: 2, max: 20 }),
      testSegments
    )
  );
})

Summary: The function `split` separates input data into continuous and discrete segments based on a given minimum weight, ensuring continuous samples are below the weight and discrete shapes meet or exceed it.


it("match", () => {
        const f = Weather.match({
          Rain: n => `${n}mm`,
          [_]: () => "not rain",
        })

        fc.assert(
          fc.property(fc.integer(), n =>
            expect(f(Weather.mk.Rain(n))).toBe(`${n}mm`),
          ),
        )

        expect(f(Weather.mk.Sun)).toBe("not rain")
      })

Summary: `Weather.match` returns a formatted string with rainfall for `Rain` type or "not rain" for other types.


it('should return true for any string that is the same forwards and backwards (ignoring case and non-alphanumerics)', () => {
    fc.assert(
      fc.property(fc.string(), (s) => {
        // Normalize string: remove non-alphanumerics, lowercase
        const normalized = s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
        const reversed = normalized.split('').reverse().join('');
        // If normalized === reversed, isPalindrome should be true
        if (normalized === reversed && normalized.length > 0) {
          return isPalindrome(s) === true;
        }
        // Otherwise, we don't care about the result
        return true;
      })
    );
  })

Summary: `isPalindrome` should return true for strings that are identical forwards and backwards when normalized by removing non-alphanumeric characters and converting to lowercase.


it('should deliver published events to all subscribers', () => {
    fc.assert(
      fc.property(fc.array(fc.string()), (events) => {
        const bus = new EventBus<string>();
        const received: string[] = [];
        bus.subscribe((e) => received.push(e));
        for (const event of events) {
          bus.publish(event);
        }
        // All published events should be received in order
        return JSON.stringify(received) === JSON.stringify(events);
      })
    );
  })

Summary: Published events should be received by all subscribers in the correct order.


test('getContests', () => {
    fc.assert(
      fc.property(electionDescription(groupContext), manifest => {
        manifest.ballotStyles.forEach(ballotStyle => {
          expect(
            manifest.getContests(ballotStyle.ballotStyleId).forEach(contest => {
              expect(ballotStyle.geopoliticalUnitIds).toContain(
                contest.geopoliticalUnitId
              );
            })
          );
        });
      })
    );
  })

Summary: For each ballot style in an election manifest, `getContests` retrieves contests with geopolitical unit IDs that match those in the ballot style.


test("Shuffling selections doesn't affect equality", () => {
    fc.assert(
      fc.property(
        fc
          .tuple(
            partyLists(groupContext, 5),
            fc.uniqueArray(geopoliticalUnit(groupContext), {minLength: 1})
          )
          .chain(([parties, gpIds]) =>
            contestDescription(groupContext, 1, parties, gpIds)
          ),
        c => {
          const contest = c.contestDescription;
          const copy = new ManifestContestDescription(
            groupContext,
            contest.contestId,
            contest.sequenceOrder,
            contest.geopoliticalUnitId,
            contest.voteVariation,
            contest.numberElected,
            contest.votesAllowed,
            contest.name,
            shuffleArray(contest.selections),
            contest.ballotTitle,
            contest.ballotSubtitle
          );

          expect(copy.equals(contest)).toBe(true);
        }
      ),
      fcFastConfig
    );
  })

Summary: Shuffling the selections of a contest should not affect its equality with the original contest.


test('An assertion failure is reproducible', () => {
  fc.assert(
    fc.property(fc.nat().noShrink(), (seed) => {
      const g = dev.Gen.integer();
      const p = dev.property(g, (x) => x < 5);

      const config0: Partial<dev.AssertConfig> = { seed };
      const error0 = tryAssert(p, config0);
      expect(error0).not.toBeNull();
      expect(error0!.message).not.toEqual('');

      const reproductionJson = error0!.message.match(/Reproduction: (\{.*\})/)![1];
      const config1: Partial<dev.AssertConfig> = JSON.parse(reproductionJson);
      const error1 = tryAssert(p, config1);
      expect(error1).not.toBeNull();
      expect(error1!.message).not.toEqual('');

      const normalizeMessage = (str: string): string => str.split('\n').slice(1).join('\n');
      const errorMessage0 = normalizeMessage(error0!.message);
      const errorMessage1 = normalizeMessage(error1!.message);
      expect(errorMessage0).toEqual(errorMessage1);
    }),
  );
})

Summary: An assertion failure can be reproduced with a specific configuration, ensuring that error messages for the original and reproduced failures are identical.


it('reflects [min, max, origin]', () => {
  fc.assert(
    fc.property(genRangeParams(), LocalGen.scaleMode(), ({ min, max, origin }, scaleMode) => {
      const range = Range.createFrom(nativeCalculator, min, max, origin, scaleMode);

      const expectedRange: Partial<Range<number>> = {
        bounds: [min, max],
        origin,
      };
      expect(range).toMatchObject(expectedRange);
    }),
  );
})

Summary: `Range.createFrom` should produce a range object with `min`, `max`, and `origin` properties matching the expected values from the input parameters.


it('should be able to revert toRoman using fromRoman', () => {
    fc.assert(
      fc.property(romanNumberArb, (n) => {
        expect(fromRoman(toRoman(n))).toBe(n);
      }),
    );
  })

Summary: Converting a number to a Roman numeral and back should return the original number.


it('returns [min,max] when given size = 100', () => {
      fc.assert(
        fc.property(genRangeParams(), ({ min, max, origin }) => {
          const range = Range.createFrom(nativeCalculator, min, max, origin, 'linear');

          const bounds = range.getSizedBounds(nativeCalculator.loadIntegerUnchecked(100));

          const expectedBounds: Bounds<number> = [min, max];
          expect(bounds).toMatchObject(expectedBounds);
        }),
      );
    })

Summary: Returns the bounds [min, max] for a range when the size is set to 100.


test('GenTree.unfold(x, id, <accExpander>, <calculateComplexity>) => a tree with a root node of x', () => {
  fc.assert(
    fc.property(
      domainGen.anything(),
      domainGen.func(domainGen.anyShrinks()),
      domainGen.func(domainGen.naturalNumber()),
      (x, accExpander, calculateComplexity) => {
        const tree = GenTree.unfold(x, id, accExpander, calculateComplexity);

        expect(tree.node.value).toEqual(x);
      },
    ),
  );
})

Summary: `GenTree.unfold` should produce a tree where the root node's value is equal to the initial input `x`.


test('GenTree.unfold(x, <accToValue>, <accExpander>, <calculateComplexity>) => a tree with a root node of accToValue(x)', () => {
  fc.assert(
    fc.property(
      domainGen.anything(),
      domainGen.anyFunc(),
      domainGen.func(domainGen.anyShrinks()),
      domainGen.func(domainGen.naturalNumber()),
      (x, accToValue, accExpander, calculateComplexity) => {
        const tree = GenTree.unfold(x, accToValue, accExpander, calculateComplexity);

        expect(tree.node.value).toEqual(accToValue(x));
      },
    ),
  );
})

Summary: `GenTree.unfold` produces a tree where the root node's value is derived from `accToValue` applied to the initial argument `x`.


test('GenTree.concat([tree1, tree2], <calculateComplexity>, <shrink>) => the root node contains the root nodes of [tree1, tree2]', () => {
  fc.assert(
    fc.property(
      domainGen.anyTree(),
      domainGen.anyTree(),
      domainGen.naturalNumber(),
      (tree1, tree2, concatComplexity) => {
        const treeConcat = GenTree.concat([tree1, tree2], () => concatComplexity, Shrink.none());

        const expectedNode: GenTree.Node<unknown[]> = {
          id: NodeId.join(tree1.node.id, tree2.node.id),
          value: [tree1.node.value, tree2.node.value],
          complexity: tree1.node.complexity + tree2.node.complexity + concatComplexity,
        };
        expect(treeConcat.node).toEqual(expectedNode);
      },
    ),
  );
})

Summary: `GenTree.concat` combines two trees into a new root node containing the root nodes of the original trees, with complexity calculated as the sum of both tree complexities plus an additional complexity value.


test.skip('GenTree.concat(trees, <calculateComplexity>, <shrink>) => the root tree contains all the shrinks of each tree', () => {
  fc.assert(
    fc.property(
      domainGen.array(domainGen.anyTree()),
      domainGen.func(domainGen.naturalNumber()),
      (trees, calculateComplexity) => {
        const treeConcat = GenTree.concat(trees, calculateComplexity, Shrink.none());

        expect(count(treeConcat.shrinks)).toEqual(
          trees.reduce((accShrinkCount, tree) => accShrinkCount + count(tree.shrinks), 0),
        );
      },
    ),
  );
})

Summary: The root tree produced by `GenTree.concat` should contain all the shrinks from each individual tree provided.


test('Gen.integer().between(x, y).origin(z), size = 0 *produces* integers equal to z', () => {
  fc.assert(
    fc.property(domainGen.sampleConfig(), domainGen.setOfSize(domainGen.integer(), 3), (config, [a, b, c]) => {
      const [x, z, y] = [a, b, c].sort((a, b) => a - b);
      const gen = dev.Gen.integer().between(x, y).origin(z);

      const sample = dev.sample(gen, { ...config, size: 0 });

      for (const value of sample.values) {
        expect(value).toEqual(z);
      }
    }),
  );
})

Summary: With `size` set to 0, the `Gen.integer().between(x, y).origin(z)` produces integers equal to `z`.


test('Gen.integer().between(x, y).origin(z), size = 50 *produces* integers in the lower half of the range', () => {
  fc.assert(
    fc.property(
      domainGen.sampleConfig(),
      domainGen.setOfSize(domainGen.integer({ min: -100, max: 100 }), 3),
      (config, [a, b, c]) => {
        const [x, z, y] = [a, b, c].sort((a, b) => a - b);
        const gen = dev.Gen.integer().between(x, y).origin(z);

        const sample = dev.sample(gen, { ...config, size: 50 });

        const leftMidpoint = Math.floor((z - x) / 2 + x);
        const rightMidpoint = Math.ceil((y - z) / 2 + z);
        for (const value of sample.values) {
          expect(value).toBeGreaterThanOrEqual(leftMidpoint);
          expect(value).toBeLessThanOrEqual(rightMidpoint);
        }
      },
    ),
  );
})

Summary: `Gen.integer().between(x, y).origin(z)` produces integers concentrated in the lower half of the range between x and y when sampled with size 50.


test('Gen.integer().lessThanEqual(x), x ∉ ℤ *produces* error; maximum must be an integer', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.decimalWithAtLeastOneDp(), (config, x) => {
        const gen = dev.Gen.integer().lessThanEqual(x);

        expect(() => dev.sample(gen, config)).toThrow('Maximum must be an integer');
      }),
    );
  })

Summary: `Gen.integer().lessThanEqual(x)` throws an error when `x` is not an integer, stating that the maximum must be an integer.


test('Gen.integer().origin(x), x ∉ ℤ *produces* error; origin must be an integer', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.decimalWithAtLeastOneDp(), (config, x) => {
        const gen = dev.Gen.integer().origin(x);

        expect(() => dev.sample(gen, config)).toThrow('Origin must be an integer');
      }),
    );
  })

Summary: `Gen.integer().origin(x)` throws an error if `x` is not an integer, ensuring the origin must be an integer.


test('default(max) = 10', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.gen(), (config, elementGen) => {
        const genDefault = dev.Gen.array(elementGen);
        const genAlt = dev.Gen.array(elementGen).ofMaxLength(10);

        expect(dev.sample(genDefault, config)).toEqual(dev.sample(genAlt, config));
      }),
    );
  })

Summary: The array generator's default maximum length is 10, matching the explicitly set maximum length of 10 in alternative generation.


test('Gen.array(gen).ofLength(x) = Gen.array(gen).betweenLengths(x, x)', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.gen(), genArrayLength(), (config, elementGen, x) => {
        const genArray = dev.Gen.array(elementGen).ofLength(x);
        const genArrayAlt = dev.Gen.array(elementGen).betweenLengths(x, x);

        expect(dev.sample(genArray, config)).toEqual(dev.sample(genArrayAlt, config));
      }),
    );
  })

Summary: The property should hold that generating an array of a specific length is equivalent to generating an array with both minimum and maximum lengths set to that specific length.


test('Gen.array(gen).ofMinLength(x), x ∉ ℤ *produces* error; minimum must be an integer', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.gen(), domainGen.decimalWithAtLeastOneDp(), (config, gen, x) => {
        const genArray = dev.Gen.array(gen).ofMinLength(x);

        expect(() => dev.sample(genArray, config)).toThrowError('Minimum must be an integer');
      }),
    );
  })

Summary: Calling `Gen.array(gen).ofMinLength(x)` with a non-integer `x` should produce an error stating that the minimum must be an integer.


test('Gen.array(gen).ofMaxLength(x), x ∉ ℤ *produces* error; maximum must be an integer', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.gen(), domainGen.decimalWithAtLeastOneDp(), (config, gen, x) => {
        const genArray = dev.Gen.array(gen).ofMaxLength(x);

        expect(() => dev.sample(genArray, config)).toThrow('Maximum must be an integer');
      }),
    );
  })

Summary: Generating an array with non-integer maximum length should produce an error with the message 'Maximum must be an integer'.


test('Gen.array(gen).ofMinLength(x), x < 0 *produces* error; minimum must be at least 0', () => {
    fc.assert(
      fc.property(domainGen.sampleConfig(), domainGen.gen(), domainGen.integer({ max: -1 }), (config, gen, x) => {
        const genArray = dev.Gen.array(gen).ofMinLength(x);

        expect(() => dev.sample(genArray, config)).toThrow('Minimum must be at least 0');
      }),
    );
  })

Summary: Generating an array with a specified minimum length less than 0 should produce an error stating the minimum must be at least 0.


test.each([
    { label: 'ASCII', unit: 'binary-ascii' },
    { label: 'Printable characters', unit: 'grapheme' },
    { label: 'Full Unicode range', unit: 'binary' },
    {
      label: 'Special ASCII characters',
      unit: fc.constantFrom(...'-._~!$()*,;=:@/?[]{}\\|^')
    }
  ] as const)('Property-based fuzzy testing - $label', ({ unit }) => {
    fc.assert(
      fc.property(fc.string({ unit }), str => {
        const search = `?key=${encodeQueryValue(str)}`
        const expected = new URLSearchParams(search).get('key')
        expect(expected).toBe(str)
      })
    )
  })


describe('middlewares/max-time', () => {
  fc.assert(fc.property(fc.nat(), fc.nat(), (duration, max,) => {
    it(
      `throws only if the response is too slow(${ duration }<=${ max })`,
      () => {
        const response: Result = {
          id: 'example',
          validators: [],
          duration,
          maxDuration: max,
          response: {
            headers: {},
            cookies: {},
            uri: '',
            status: 0,
            body: '',
          },
        };
        if (duration > max) {
          expect(() => post(response,),)
            .to.throw(
              `The response time was above ${ max } ns`,
            );
          return;
        }
        expect(() => post(response,),).to.not.throw();
      },
    );
  },),);
},)


describe('helper/language', () => {
  after(async() => {
    await locale('en',);
  },);
  fc.assert(fc.property(fc.string(), (lang,) => {
    it(`no_tasks should return english string if set to ${ lang }`, async() => {
      if (
        lang.match(/^[a-z]{2}$/u,)
        && existsSync(process.cwd() + 'language/' + lang + '.yml',)
      ) {
        //skip
        return true;
      }
      await locale(lang,);
      expect(language('no_tasks',),).to.be.equal('Can\'t measure zero tasks.',);
      return true;
    },);
  },),);
  fc.assert(fc.property(fc.string(), (key,) => {
    it(`${ key } should return a string`, () => {
      expect(language(key as languageKey,),).to.be.a('string',);
    },);
  },),);
},)


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(MAC(), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.true;
          })
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(invertedRegex(regExp.MAC), async testValue => {
            input!.value = testValue;
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 4, maxLength: 4 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 5 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 4', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 3, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 4 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 3', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 2 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0, max: 7 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 8 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('edits name attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tAsciName, 1, 32), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.true;
          })
        );
      })


it('rejects name attribute starting with decimals', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.false;
          })
        );
      })


it('edits bufTime attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async bufTime => {
              inputs[6].value = bufTime;
              await (<WizardTextField>inputs[6]).requestUpdate();
              expect(inputs[6].checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects bufTime attribute starting with not being a unsigned int', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async bufTime => {
              inputs[6].value = bufTime;
              await (<WizardTextField>inputs[6]).requestUpdate();
              expect(inputs[6].checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits intgPd attribute only for valid inputs', async () => {
        const input = <WizardTextField>inputs[7];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async intgPd => {
              input.value = intgPd;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects intgPd attribute starting with not being a unsigned int', async () => {
        const input = <WizardTextField>inputs[7];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(regexString(inverseRegExp.uint, 1), async intgPd => {
            input.value = intgPd;
            await input.requestUpdate();
            expect(input.checkValidity()).to.be.false;
          })
        );
      })


it('edits prefix attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tAsciName, 1, 11), async name => {
            inputs[2].value = name;
            await (<WizardTextField>inputs[2]).requestUpdate();
            expect(inputs[2].checkValidity()).to.be.true;
          })
        );
      })


it('rejects name attribute starting with decimals', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
            inputs[2].value = name;
            await (<WizardTextField>inputs[2]).requestUpdate();
            expect(inputs[2].checkValidity()).to.be.false;
          })
        );
      })


it('edits smpRate attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async smpRate => {
              inputs[4].value = smpRate;
              await (<WizardTextField>inputs[4]).requestUpdate();
              expect(inputs[4].checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects smpRate attribute in case input is not unsigned int', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async smpRate => {
              inputs[4].value = smpRate;
              await (<WizardTextField>inputs[4]).requestUpdate();
              expect(inputs[4].checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits nofASDU attribute only for valid inputs', async () => {
        const input = <WizardTextField>inputs[5];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0 }).map(num => `${num}`),
            async nofASDU => {
              input.value = nofASDU;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.true;
            }
          )
        );
      })


it('rejects nofASDU attribute in case input is not unsigned int', async () => {
        const input = <WizardTextField>inputs[5];
        input.nullSwitch?.click();
        await input.requestUpdate();

        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.uint, 1),
            async nofASDU => {
              input.value = nofASDU;
              await input.requestUpdate();
              expect(input.checkValidity()).to.be.false;
            }
          )
        );
      })


it('edits name attribute only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tAsciName, 1, 32), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.true;
        })
      );
    })


it('rejects name attribute starting with decimals', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.false;
        })
      );
    })


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV4(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv4), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 1, 8), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSI), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSI, 1, 16),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSIAPi, 1), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSIAPi), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSIid, 1, 5),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSIid), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              regexString(regExp.OSI, 1, 40),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 3, 3), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(/^[0-7]$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-7]$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              nat({ max: 65535 }).map(num => `${num}`),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-9]*$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(/^\S*$/, 1), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV6(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv6), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV6SubNet(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(/^[0-9/]*$/), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              fc.hexaString({ minLength: 1, maxLength: 5 }),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              invertedRegex(/^[0-9a-fA-F]{1,5}$/),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.false;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(
              nat({ max: 255 }).map(num => `${num}`),
              async testValue => {
                input!.value = testValue;
                await element.requestUpdate();
                expect(input!.checkValidity()).to.be.true;
              }
            )
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(ipV4(), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.IPv4), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('allow to edit for valid input', async () =>
          await fc.assert(
            fc.asyncProperty(regexString(regExp.OSI, 1, 2), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            })
          ))


it('does not allow to edit for invalid input', async () =>
          await fc.assert(
            fc.asyncProperty(invertedRegex(regExp.OSI), async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            })
          ))


it('edits name attribute only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(regExp.abstractDataAttributeName, 1, 32),
          async name => {
            nameTextField.value = name;
            await nameTextField.requestUpdate();
            expect(nameTextField.checkValidity()).to.be.true;
          }
        )
      );
    })


it('rejects name attribute starting with decimals', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
          nameTextField.value = name;
          await nameTextField.requestUpdate();
          expect(nameTextField.checkValidity()).to.be.false;
        })
      );
    })


it('for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            regexString(regExp.lnClass, 4, 4),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tName, 1), async name => {
          parent.wizardUI.inputs[0].value = name;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.desc), async desc => {
          parent.wizardUI.inputs[1].value = desc;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.unsigned, 1), async nomFreq => {
          parent.wizardUI.inputs[2].value = nomFreq;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[2].checkValidity()).to.be.true;
        })
      );
    })


it('rejects action for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.unsigned, 1),
          async nomFreq => {
            parent.wizardUI.inputs[2].value = nomFreq;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[2].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(fc.integer(1, 255), async numPhases => {
          parent.wizardUI.inputs[3].value = String(numPhases);
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[3].checkValidity()).to.be.true;
        })
      );
    })


it('rejects edition for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.integer, 1),
          async nomFreq => {
            parent.wizardUI.inputs[3].value = nomFreq;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[3].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.decimal), async nomFreq => {
          parent.wizardUI.inputs[4].value = nomFreq;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[4].checkValidity()).to.be.true;
        })
      );
    })


it('rejects edition for invalid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(
          regexString(inverseRegExp.decimal, 1),
          async voltage => {
            parent.wizardUI.inputs[4].value = voltage;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[4].checkValidity()).to.be.false;
          }
        )
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.tName, 1), async name => {
          parent.wizardUI.inputs[1].value = name;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
      await fc.assert(
        fc.asyncProperty(regexString(regExp.desc), async desc => {
          parent.wizardUI.inputs[2].value = desc;
          await parent.updateComplete;
          expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
        })
      );
    })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tName, 1), async name => {
            parent.wizardUI.inputs[0].value = name;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[0].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.desc), async desc => {
            parent.wizardUI.inputs[1].value = desc;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[1].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.desc, 1), async type => {
            parent.wizardUI.inputs[2].value = type;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[2].checkValidity()).to.be.true;
          })
        );
      })


it('edits only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal), async BitRate => {
            parent.wizardUI.inputs[3].value = BitRate;
            await parent.updateComplete;
            expect(parent.wizardUI.inputs[3].checkValidity()).to.be.true;
          })
        );
      })


it('rejects edition for invalid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(
            regexString(inverseRegExp.decimal, 1),
            async BitRate => {
              parent.wizardUI.inputs[3].value = BitRate;
              await parent.updateComplete;
              expect(parent.wizardUI.inputs[3].checkValidity()).to.be.false;
            }
          )
        );
      })


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(MAC(), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.true;
          })
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(invertedRegex(regExp.MAC), async testValue => {
            input!.value = testValue;
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 4, maxLength: 4 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 5 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 4', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 3, maxLength: 3 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(hexaString({ minLength: 4 }), async testValue => {
            input!.value = testValue.toUpperCase();
            await element.requestUpdate();
            expect(input!.checkValidity()).to.be.false;
          })
        ))


it('does not allow to edit characters < 3', async () =>
        await fc.assert(
          fc.asyncProperty(
            hexaString({ minLength: 0, maxLength: 2 }),
            async testValue => {
              input!.value = testValue.toUpperCase();
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('allow to edit for valid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 0, max: 7 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.true;
            }
          )
        ))


it('does not allow to edit for invalid input', async () =>
        await fc.assert(
          fc.asyncProperty(
            integer({ min: 8 }).map(num => `${num}`),
            async testValue => {
              input!.value = testValue;
              await element.requestUpdate();
              expect(input!.checkValidity()).to.be.false;
            }
          )
        ))


it('edits name attribute only for valid inputs', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.tAsciName, 1, 32), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.true;
          })
        );
      })


it('rejects name attribute starting with decimals', async () => {
        await fc.assert(
          fc.asyncProperty(regexString(regExp.decimal, 1, 1), async name => {
            inputs[0].value = name;
            await (<WizardTextField>inputs[0]).requestUpdate();
            expect(inputs[0].checkValidity()).to.be.false;
          })
        );
      })