diff --git a/packages/core/src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts b/packages/core/src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts index d77f499..6c43ab8 100644 --- a/packages/core/src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts +++ b/packages/core/src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts @@ -209,14 +209,11 @@ export function createReactiveFieldStatus({ }); const $tooltips = computed(() => { - if ($error.value) { - return extractRulesTooltips({ - field: { - $rules: $rules.value, - }, - }); - } - return []; + return extractRulesTooltips({ + field: { + $rules: $rules.value, + }, + }); }); const $silentErrors = computed(() => { diff --git a/packages/core/src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts b/packages/core/src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts index b8ee560..394e178 100644 --- a/packages/core/src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts +++ b/packages/core/src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts @@ -61,6 +61,8 @@ export function createReactiveRuleStatus({ scopeState = scope.run(() => { const $defaultMetadata = computed<$InternalRegleRuleMetadataConsumer>(() => ({ $invalid: !$valid.value, + $pending: $pending.value, + $dirty: $dirty.value, $params: $params.value, ...$metadata.value, })); @@ -79,18 +81,18 @@ export function createReactiveRuleStatus({ function computeRuleProcessor(key: 'message' | 'tooltip'): string | string[] { let result: string | string[] = ''; - const customMessageRule = customMessages ? customMessages[ruleKey]?.[key] : undefined; + const customProcessor = customMessages ? customMessages[ruleKey]?.[key] : undefined; - if (customMessageRule) { - if (typeof customMessageRule === 'function') { - result = customMessageRule(state.value, $defaultMetadata.value); + if (customProcessor) { + if (typeof customProcessor === 'function') { + result = customProcessor(state.value, $defaultMetadata.value); } else { - result = customMessageRule; + result = customProcessor; } } if (isFormRuleDefinition(rule)) { const patchedKey = `_${key}_patched` as const; - if (!(customMessageRule && !rule.value[patchedKey])) { + if (!(customProcessor && !rule.value[patchedKey])) { if (typeof rule.value[key] === 'function') { result = rule.value[key](state.value, $defaultMetadata.value); } else { @@ -106,7 +108,7 @@ export function createReactiveRuleStatus({ if (isEmpty(message)) { message = 'Error'; - if (typeof window !== 'undefined') { + if (typeof window !== 'undefined' && typeof process === 'undefined') { console.warn(`No error message defined for ${path}.${ruleKey}`); } } diff --git a/packages/core/src/types/rules/rule.definition.type.ts b/packages/core/src/types/rules/rule.definition.type.ts index 48b1fcf..b0c82de 100644 --- a/packages/core/src/types/rules/rule.definition.type.ts +++ b/packages/core/src/types/rules/rule.definition.type.ts @@ -71,7 +71,7 @@ export type UnwrapRuleWithParams | undefined> = */ export type RegleRuleMetadataDefinition = RegleRuleMetadataExtended | boolean; -type DefaultMetadataProperties = Pick, '$invalid'>; +type DefaultMetadataProperties = Pick, '$invalid' | '$dirty' | '$pending'>; /** * Will be used to consumme metadata on related helpers and rule status diff --git a/packages/rules/src/helpers/tests/withTooltip.spec.ts b/packages/rules/src/helpers/tests/withTooltip.spec.ts index 6a5fbbc..0205c9d 100644 --- a/packages/rules/src/helpers/tests/withTooltip.spec.ts +++ b/packages/rules/src/helpers/tests/withTooltip.spec.ts @@ -4,13 +4,13 @@ import { withTooltip } from '../withTooltip'; describe('withTooltip', () => { it('should register tooltips to an inline rule', () => { const inlineRule = withTooltip((value) => true, 'Hello tooltip'); - expect(inlineRule.tooltip?.(null, { $invalid: false })).toBe('Hello tooltip'); + expect(inlineRule.tooltip?.(null, { $invalid: false, $dirty: false, $pending: false })).toBe('Hello tooltip'); expect(inlineRule._tooltip).toBe('Hello tooltip'); }); it('should register tooltips to an rule definition', () => { const inlineRule = withTooltip(required, 'Hello tooltip'); - expect(inlineRule.tooltip?.(null, { $invalid: false })).toBe('Hello tooltip'); + expect(inlineRule.tooltip?.(null, { $invalid: false, $dirty: false, $pending: false })).toBe('Hello tooltip'); expect(inlineRule._tooltip).toBe('Hello tooltip'); }); }); diff --git a/tests/unit/useRegle/errors/tooltips.spec.ts b/tests/unit/useRegle/errors/tooltips.spec.ts index 0c7d1aa..15faea7 100644 --- a/tests/unit/useRegle/errors/tooltips.spec.ts +++ b/tests/unit/useRegle/errors/tooltips.spec.ts @@ -50,6 +50,7 @@ function tooltipsRules() { createRuleFunctionOneTooltip, createRuleFunctionMultipleTooltip, }; + return useRegle(form, { email: allRules, user: { @@ -97,7 +98,6 @@ describe('tooltips', () => { expect(vm.r$.$fields.user.$fields.firstName.$tooltips).toStrictEqual(expectedTooltips); expect(vm.r$.$fields.user.$fields.nested.$fields.child.$tooltips).toStrictEqual(expectedTooltips); expect(vm.r$.$fields.user.$fields.nested.$fields.collection.$field.$tooltips).toStrictEqual(expectedTooltips); - expect(vm.r$.$fields.user.$fields.nested.$fields.collection.$field.$tooltips).toStrictEqual(expectedTooltips); expect(vm.r$.$fields.user.$fields.nested.$fields.collection.$each[0].$fields.name.$tooltips).toStrictEqual( expectedTooltips ); diff --git a/ui-tests/fixtures/ui-vue3/src/components/regle.global.config.ts b/ui-tests/fixtures/ui-vue3/src/components/regle.global.config.ts index 7919a1b..d16974f 100644 --- a/ui-tests/fixtures/ui-vue3/src/components/regle.global.config.ts +++ b/ui-tests/fixtures/ui-vue3/src/components/regle.global.config.ts @@ -44,14 +44,17 @@ export const strongPassword = createRule({ message(_, { result }) { return `Your password is ${result?.value.toLocaleLowerCase()}`; }, - tooltip(_, { result }) { - let diversity = diversityTypes - .filter((f) => !result?.contains.includes(f)) - .map((value) => diversityMessages[value]); - if ((result?.length ?? 0) < 10) { - diversity.push('At least 10 characters'); + tooltip(_, { result, $dirty }) { + if ($dirty) { + let diversity = diversityTypes + .filter((f) => !result?.contains.includes(f)) + .map((value) => diversityMessages[value]); + if ((result?.length ?? 0) < 8) { + diversity.push('At least 8 characters'); + } + return diversity; } - return diversity; + return []; }, }); diff --git a/ui-tests/specs/base.uispec.ts b/ui-tests/specs/base.uispec.ts index b4dcc24..9ceac46 100644 --- a/ui-tests/specs/base.uispec.ts +++ b/ui-tests/specs/base.uispec.ts @@ -39,7 +39,7 @@ test('it should render the page correctly', async ({ index }) => { expect(await index.page.$('[data-testid=project-0-url] .errors')).toBeNull(); await expect(index.page.locator('[data-testid=password] .tooltips')).toContainText( - `At least one owercase letter (a-z)At least one uppercase letter (A-Z)At least one symbol ($€@&..)At least one number (0-9)At least 10 characters` + `At least one owercase letter (a-z)At least one uppercase letter (A-Z)At least one symbol ($€@&..)At least one number (0-9)At least 8 characters` ); await expect(index.page.locator('[data-testid=confirmPassword] .errors')).toContainText( 'You need to provide a value'