Skip to content

Commit

Permalink
Refactor grapheme actions, update changelog and add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
fabian-hiller committed Oct 11, 2024
1 parent ca9a94e commit 0e5546b
Show file tree
Hide file tree
Showing 62 changed files with 1,880 additions and 148 deletions.
1 change: 1 addition & 0 deletions library/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to the library will be documented in this file.
## v1.0.0 (Month DD, YYYY)

- Add `checkItemsAsync` action (pull request #856)
- Add `graphemes`, `maxGraphemes`, `minGraphemes` and `notGraphemes` action (pull request #853)
- Change types and implementation to support Standard Schema

## v0.42.1 (September 20, 2024)
Expand Down
45 changes: 38 additions & 7 deletions library/src/actions/graphemes/graphemes.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { describe, expect, test } from 'vitest';
import type { StringIssue } from '../../schemas/index.ts';
import { _getGraphemeCount } from '../../utils/index.ts';
import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts';
import { graphemes, type GraphemesAction, type GraphemesIssue } from './graphemes.ts';
import { _getGraphemes } from '../../utils/index.ts';
import {
graphemes,
type GraphemesAction,
type GraphemesIssue,
} from './graphemes.ts';

describe('graphemes', () => {
describe('should return action object', () => {
Expand All @@ -12,7 +17,7 @@ describe('graphemes', () => {
expects: '5',
requirement: 5,
async: false,
_run: expect.any(Function),
'~validate': expect.any(Function),
};

test('with undefined message', () => {
Expand Down Expand Up @@ -44,14 +49,31 @@ describe('graphemes', () => {
const action = graphemes(5);

test('for untyped inputs', () => {
expect(action._run({ typed: false, value: null }, {})).toStrictEqual({
const issues: [StringIssue] = [
{
kind: 'schema',
type: 'string',
input: null,
expected: 'string',
received: 'null',
message: 'message',
},
];
expect(
action['~validate']({ typed: false, value: null, issues }, {})
).toStrictEqual({
typed: false,
value: null,
issues,
});
});

test('for valid strings', () => {
expectNoActionIssue(action, ['😀😀😀😀😀', '12345', 'hello']);
expectNoActionIssue(action, ['12345', '12 45', '1234 ', 'hello']);
});

test('for valid emoji', () => {
expectNoActionIssue(action, ['😀👋🏼🧩👩🏻‍🏫🫥']);
});
});

Expand All @@ -69,8 +91,17 @@ describe('graphemes', () => {
expectActionIssue(
action,
baseIssue,
['😀😀😀😀', '1234', 'foobar', '😀😀😀😀😀😀', '🧑‍💻'],
(value) => `${_getGraphemes(value)}`
['', ' ', '1', '1234', '123 ', '123456', '12 456', '123456789'],
(value) => `${_getGraphemeCount(value)}`
);
});

test('for invalid emoji', () => {
expectActionIssue(
action,
baseIssue,
['😀', '😀👋🏼🧩👩🏻‍🏫', '😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎'],
(value) => `${_getGraphemeCount(value)}`
);
});
});
Expand Down
27 changes: 13 additions & 14 deletions library/src/actions/graphemes/graphemes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
BaseValidation,
ErrorMessage,
} from '../../types/index.ts';
import { _addIssue, _getGraphemes } from '../../utils/index.ts';
import { _addIssue, _getGraphemeCount } from '../../utils/index.ts';

/**
* Graphemes issue type.
Expand Down Expand Up @@ -41,8 +41,8 @@ export interface GraphemesAction<
TInput extends string,
TRequirement extends number,
TMessage extends
| ErrorMessage<GraphemesIssue<TInput, TRequirement>>
| undefined,
| ErrorMessage<GraphemesIssue<TInput, TRequirement>>
| undefined,
> extends BaseValidation<TInput, TInput, GraphemesIssue<TInput, TRequirement>> {
/**
* The action type.
Expand Down Expand Up @@ -90,8 +90,8 @@ export function graphemes<
TInput extends string,
const TRequirement extends number,
const TMessage extends
| ErrorMessage<GraphemesIssue<TInput, TRequirement>>
| undefined,
| ErrorMessage<GraphemesIssue<TInput, TRequirement>>
| undefined,
>(
requirement: TRequirement,
message: TMessage
Expand All @@ -113,15 +113,14 @@ export function graphemes(
expects: `${requirement}`,
requirement,
message,
_run(dataset, config) {
if (!dataset.typed) {
return dataset;
}
const count = _getGraphemes(dataset.value);
if (count !== this.requirement) {
_addIssue(this, 'graphemes', dataset, config, {
received: `${count}`,
});
'~validate'(dataset, config) {
if (dataset.typed) {
const count = _getGraphemeCount(dataset.value);
if (count !== this.requirement) {
_addIssue(this, 'graphemes', dataset, config, {
received: `${count}`,
});
}
}
return dataset;
},
Expand Down
9 changes: 5 additions & 4 deletions library/src/actions/maxGraphemes/maxGraphemes.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,20 @@ describe('maxGraphemes', () => {
});

describe('should infer correct types', () => {
type Action = MaxGraphemesAction<string, 10, undefined>;
type Input = 'example string';
type Action = MaxGraphemesAction<Input, 10, undefined>;

test('of input', () => {
expectTypeOf<InferInput<Action>>().toEqualTypeOf<string>();
expectTypeOf<InferInput<Action>>().toEqualTypeOf<Input>();
});

test('of output', () => {
expectTypeOf<InferOutput<Action>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Action>>().toEqualTypeOf<Input>();
});

test('of issue', () => {
expectTypeOf<InferIssue<Action>>().toEqualTypeOf<
MaxGraphemesIssue<string, 10>
MaxGraphemesIssue<Input, 10>
>();
});
});
Expand Down
44 changes: 34 additions & 10 deletions library/src/actions/maxGraphemes/maxGraphemes.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, test } from 'vitest';
import { _getGraphemes } from '../../utils/index.ts';
import type { StringIssue } from '../../schemas/index.ts';
import { _getGraphemeCount } from '../../utils/index.ts';
import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts';
import {
maxGraphemes,
Expand All @@ -9,17 +10,14 @@ import {

describe('maxGraphemes', () => {
describe('should return action object', () => {
const baseAction: Omit<
MaxGraphemesAction<string, 5, never>,
'message'
> = {
const baseAction: Omit<MaxGraphemesAction<string, 5, never>, 'message'> = {
kind: 'validation',
type: 'max_graphemes',
reference: maxGraphemes,
expects: '<=5',
requirement: 5,
async: false,
_run: expect.any(Function),
'~validate': expect.any(Function),
};

test('with undefined message', () => {
Expand Down Expand Up @@ -51,14 +49,31 @@ describe('maxGraphemes', () => {
const action = maxGraphemes(5);

test('for untyped inputs', () => {
expect(action._run({ typed: false, value: null }, {})).toStrictEqual({
const issues: [StringIssue] = [
{
kind: 'schema',
type: 'string',
input: null,
expected: 'string',
received: 'null',
message: 'message',
},
];
expect(
action['~validate']({ typed: false, value: null, issues }, {})
).toStrictEqual({
typed: false,
value: null,
issues,
});
});

test('for valid strings', () => {
expectNoActionIssue(action, ['🧑🏻‍💻', '😀😀😀😀', 'foo']);
expectNoActionIssue(action, ['', ' ', '1', 'foo', '12345', '12 45']);
});

test('for valid emoji', () => {
expectNoActionIssue(action, ['😀', '😀👋🏼', '😀👋🏼🧩👩🏻‍🏫', '😀👋🏼🧩👩🏻‍🏫🫥']);
});
});

Expand All @@ -79,8 +94,17 @@ describe('maxGraphemes', () => {
expectActionIssue(
action,
baseIssue,
['😀😀😀😀😀😀', 'foobarbaz123'],
(value) => `${_getGraphemes(value)}`
['123456', '12345 ', '123456789', 'foo bar baz'],
(value) => `${_getGraphemeCount(value)}`
);
});

test('for invalid emoji', () => {
expectActionIssue(
action,
baseIssue,
['😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎'],
(value) => `${_getGraphemeCount(value)}`
);
});
});
Expand Down
37 changes: 18 additions & 19 deletions library/src/actions/maxGraphemes/maxGraphemes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
BaseValidation,
ErrorMessage,
} from '../../types/index.ts';
import { _addIssue, _getGraphemes } from '../../utils/index.ts';
import { _addIssue, _getGraphemeCount } from '../../utils/index.ts';

/**
* Max graphemes issue type.
Expand Down Expand Up @@ -41,13 +41,13 @@ export interface MaxGraphemesAction<
TInput extends string,
TRequirement extends number,
TMessage extends
| ErrorMessage<MaxGraphemesIssue<TInput, TRequirement>>
| undefined,
| ErrorMessage<MaxGraphemesIssue<TInput, TRequirement>>
| undefined,
> extends BaseValidation<
TInput,
TInput,
MaxGraphemesIssue<TInput, TRequirement>
> {
TInput,
TInput,
MaxGraphemesIssue<TInput, TRequirement>
> {
/**
* The action type.
*/
Expand Down Expand Up @@ -81,7 +81,7 @@ export function maxGraphemes<
TInput extends string,
const TRequirement extends number,
>(
requirement: TRequirement,
requirement: TRequirement
): MaxGraphemesAction<TInput, TRequirement, undefined>;

/**
Expand All @@ -96,8 +96,8 @@ export function maxGraphemes<
TInput extends string,
const TRequirement extends number,
const TMessage extends
| ErrorMessage<MaxGraphemesIssue<TInput, TRequirement>>
| undefined,
| ErrorMessage<MaxGraphemesIssue<TInput, TRequirement>>
| undefined,
>(
requirement: TRequirement,
message: TMessage
Expand All @@ -119,15 +119,14 @@ export function maxGraphemes(
expects: `<=${requirement}`,
requirement,
message,
_run(dataset, config) {
if (!dataset.typed) {
return dataset;
}
const count = _getGraphemes(dataset.value);
if (count > this.requirement) {
_addIssue(this, 'graphemes', dataset, config, {
received: `${count}`,
});
'~validate'(dataset, config) {
if (dataset.typed) {
const count = _getGraphemeCount(dataset.value);
if (count > this.requirement) {
_addIssue(this, 'graphemes', dataset, config, {
received: `${count}`,
});
}
}
return dataset;
},
Expand Down
9 changes: 5 additions & 4 deletions library/src/actions/minGraphemes/minGraphemes.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,20 @@ describe('minGraphemes', () => {
});

describe('should infer correct types', () => {
type Action = MinGraphemesAction<string, 10, undefined>;
type Input = 'example string';
type Action = MinGraphemesAction<Input, 10, undefined>;

test('of input', () => {
expectTypeOf<InferInput<Action>>().toEqualTypeOf<string>();
expectTypeOf<InferInput<Action>>().toEqualTypeOf<Input>();
});

test('of output', () => {
expectTypeOf<InferOutput<Action>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Action>>().toEqualTypeOf<Input>();
});

test('of issue', () => {
expectTypeOf<InferIssue<Action>>().toEqualTypeOf<
MinGraphemesIssue<string, 10>
MinGraphemesIssue<Input, 10>
>();
});
});
Expand Down
Loading

0 comments on commit 0e5546b

Please sign in to comment.