Skip to content

[_]: feat/enhance email address validation and availability checks#77

Open
jzunigax2 wants to merge 1 commit into
masterfrom
feat/add-taken-address-check
Open

[_]: feat/enhance email address validation and availability checks#77
jzunigax2 wants to merge 1 commit into
masterfrom
feat/add-taken-address-check

Conversation

@jzunigax2

Copy link
Copy Markdown
Contributor
  • Updated email address validation logic to include availability checks against the backend.
  • Introduced new rules for email address format validation and improved user feedback for taken addresses.
  • Enhanced the UI to reflect the loading state during availability checks and updated button states accordingly.
  • Added localization support for new validation messages in multiple languages.
  • Refactored related tests to cover new functionality and ensure robust validation behavior.

- Updated email address validation logic to include availability checks against the backend.
- Introduced new rules for email address format validation and improved user feedback for taken addresses.
- Enhanced the UI to reflect the loading state during availability checks and updated button states accordingly.
- Added localization support for new validation messages in multiple languages.
- Refactored related tests to cover new functionality and ensure robust validation behavior.
@jzunigax2 jzunigax2 self-assigned this Jul 18, 2026
@jzunigax2
jzunigax2 requested a review from xabg2 as a code owner July 18, 2026 05:25
@jzunigax2 jzunigax2 added the enhancement New feature or request label Jul 18, 2026
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
77.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Email setup now validates username format and backend availability, handles unavailable or uncertain addresses during submission, supports suggestion-specific labels, and adds localized messages and tests across the service, validation hook, UI, and rule logic.

Email availability flow

Layer / File(s) Summary
Mail availability API
src/services/sdk/mail/index.ts, src/services/sdk/mail/mail.service.test.ts
Adds and tests the typed checkAddressAvailability mail service method.
Availability rule contract
src/features/identity-setup/hooks/emailAddressRules.ts, src/features/identity-setup/hooks/emailAddressRules.test.ts
Adds availability states, format-only validation, suggestion-aware labels, and backend-dependent rule validity with corresponding tests.
Debounced availability validation
src/features/identity-setup/hooks/useEmailAddressValidation.ts, src/features/identity-setup/hooks/useEmailAddressValidation.test.ts
Adds domain-aware debounced checks, stale-request protection, availability state, manual checks, and canSubmit behavior.
Submission and availability rendering
src/features/identity-setup/hooks/useUpdateEmail.ts, src/features/identity-setup/components/UpdateEmail.tsx, src/features/identity-setup/components/EmailAddressRulesPanel.tsx, src/i18n/locales/*.json
Submissions await availability, duplicate submits are prevented, loading state is rendered, rule interpolation is supported, and availability messages are localized.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: xabg2, xabg2

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: improved email validation and backend availability checks.
Description check ✅ Passed The description is directly aligned with the changeset and summarizes validation, UI, locale, and test updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-taken-address-check

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/identity-setup/hooks/emailAddressRules.test.ts`:
- Line 242: Rewrite the changed test descriptions using plain-language “When …,
then …” behavior statements, without naming implementation symbols. In
src/features/identity-setup/hooks/emailAddressRules.test.ts lines 242-242,
replace the isEmailAddressFormatValid suite description; in
src/features/identity-setup/hooks/useEmailAddressValidation.test.ts lines
30-188, remove hook and callback names from the affected suite and test
descriptions while preserving their behavioral meaning.
- Around line 243-252: Update the affected tests around
isEmailAddressFormatValid to follow the AAA pattern: assign each input during
Arrange, call isEmailAddressFormatValid in a separate Act statement, then assert
the stored result. Add blank lines between the Arrange, Act, and Assert sections
while preserving the existing inputs and expected outcomes.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.test.ts`:
- Line 30: Update the test descriptions within the useEmailAddressValidation
suite to use “When …, then …” wording focused on user-observable situations and
outcomes. Remove references to implementation names such as the hook,
validateAddress, and checkAvailability while preserving each test’s existing
behavior and assertions.
- Around line 161-175: Add a deferred-request test for checkAvailability that
starts with one username/domain, changes the current input before the
availability promise resolves, then resolves the old request successfully and
asserts its result cannot set canSubmit to true or authorize submission. Cover
the stale-result path in useEmailAddressValidation and include the rejection
behavior if the existing test utilities support it.
- Around line 31-39: Update the test setup around beforeEach and afterEach to
call vi.restoreAllMocks() at the start of beforeEach before configuring
checkAddressAvailability.mockResolvedValue. Remove the vi.clearAllMocks() call
from afterEach while preserving fake-timer setup and restoration.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.ts`:
- Around line 56-65: Update checkAvailability in useEmailAddressValidation so
requests are invalidated immediately when the username or domain changes, and
ensure a request whose requestId no longer matches latestRequestIdRef.current
returns a non-success availability state instead of its stale result. Keep
lastCheck updates restricted to the current request, and preserve the existing
valid-result behavior when the request remains current.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8e165380-9d77-4953-9e6e-e1000e9d99dd

📥 Commits

Reviewing files that changed from the base of the PR and between 573e054 and 6a1f549.

📒 Files selected for processing (13)
  • src/features/identity-setup/components/EmailAddressRulesPanel.tsx
  • src/features/identity-setup/components/UpdateEmail.tsx
  • src/features/identity-setup/hooks/emailAddressRules.test.ts
  • src/features/identity-setup/hooks/emailAddressRules.ts
  • src/features/identity-setup/hooks/useEmailAddressValidation.test.ts
  • src/features/identity-setup/hooks/useEmailAddressValidation.ts
  • src/features/identity-setup/hooks/useUpdateEmail.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/services/sdk/mail/index.ts
  • src/services/sdk/mail/mail.service.test.ts

});
});

describe('isEmailAddressFormatValid', () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Rewrite implementation-focused test descriptions as plain-language behavior.

  • src/features/identity-setup/hooks/emailAddressRules.test.ts#L242-L242: replace the function-named suite with a “When …, then …” behavior description.
  • src/features/identity-setup/hooks/useEmailAddressValidation.test.ts#L30-L188: remove references to the hook and callback names from changed suite/test descriptions.

As per coding guidelines, descriptions must use the “When …, then …” pattern without referencing variable, function, or type names.

📍 Affects 2 files
  • src/features/identity-setup/hooks/emailAddressRules.test.ts#L242-L242 (this comment)
  • src/features/identity-setup/hooks/useEmailAddressValidation.test.ts#L30-L188
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/emailAddressRules.test.ts` at line 242,
Rewrite the changed test descriptions using plain-language “When …, then …”
behavior statements, without naming implementation symbols. In
src/features/identity-setup/hooks/emailAddressRules.test.ts lines 242-242,
replace the isEmailAddressFormatValid suite description; in
src/features/identity-setup/hooks/useEmailAddressValidation.test.ts lines
30-188, remove hook and callback names from the affected suite and test
descriptions while preserving their behavioral meaning.

Source: Coding guidelines

Comment on lines +243 to +252
test('When username satisfies every format rule, then it is valid', () => {
expect(isEmailAddressFormatValid('jane.doe-99_x')).toBe(true);
});

test('When username is a reserved name, then it is invalid', () => {
expect(isEmailAddressFormatValid('admin')).toBe(false);
});

test('When username breaks a format rule, then it is invalid', () => {
expect(isEmailAddressFormatValid('.jane')).toBe(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Separate Arrange, Act, and Assert.

These tests invoke the subject inside expect, so the Act and Assert phases are not separated.

Proposed structure
 test('When the address satisfies every format rule, then it is valid', () => {
-  expect(isEmailAddressFormatValid('jane.doe-99_x')).toBe(true);
+  const result = isEmailAddressFormatValid('jane.doe-99_x');
+
+  expect(result).toBe(true);
 });

As per coding guidelines, “Structure tests using the AAA pattern (Arrange, Act, Assert) with blank-line separation between sections.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('When username satisfies every format rule, then it is valid', () => {
expect(isEmailAddressFormatValid('jane.doe-99_x')).toBe(true);
});
test('When username is a reserved name, then it is invalid', () => {
expect(isEmailAddressFormatValid('admin')).toBe(false);
});
test('When username breaks a format rule, then it is invalid', () => {
expect(isEmailAddressFormatValid('.jane')).toBe(false);
test('When username satisfies every format rule, then it is valid', () => {
const result = isEmailAddressFormatValid('jane.doe-99_x');
expect(result).toBe(true);
});
test('When username is a reserved name, then it is invalid', () => {
expect(isEmailAddressFormatValid('admin')).toBe(false);
});
test('When username breaks a format rule, then it is invalid', () => {
expect(isEmailAddressFormatValid('.jane')).toBe(false);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/emailAddressRules.test.ts` around lines 243
- 252, Update the affected tests around isEmailAddressFormatValid to follow the
AAA pattern: assign each input during Arrange, call isEmailAddressFormatValid in
a separate Act statement, then assert the stored result. Add blank lines between
the Arrange, Act, and Assert sections while preserving the existing inputs and
expected outcomes.

Source: Coding guidelines

});
};

describe('useEmailAddressValidation', () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove implementation names from behavior descriptions.

Descriptions such as “the hook,” validateAddress, and checkAvailability should describe user-observable situations and outcomes instead.

As per coding guidelines, tests must use “When …, then …” descriptions without referencing variable, function, or type names.

Also applies to: 41-81, 161-188

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.test.ts` at line
30, Update the test descriptions within the useEmailAddressValidation suite to
use “When …, then …” wording focused on user-observable situations and outcomes.
Remove references to implementation names such as the hook, validateAddress, and
checkAvailability while preserving each test’s existing behavior and assertions.

Source: Coding guidelines

Comment on lines 31 to 39
beforeEach(() => {
vi.useFakeTimers();
checkAddressAvailability.mockResolvedValue({ available: true, suggestion: null });
});

afterEach(() => {
vi.useRealTimers();
vi.clearAllMocks();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Restore mocks in beforeEach.

Use vi.restoreAllMocks() before configuring the default mock, rather than clearing mocks in afterEach.

Proposed fix
 beforeEach(() => {
+  vi.restoreAllMocks();
   vi.useFakeTimers();
   checkAddressAvailability.mockResolvedValue({ available: true, suggestion: null });
 });

 afterEach(() => {
   vi.useRealTimers();
-  vi.clearAllMocks();
 });

As per coding guidelines, “Reset mocks in beforeEach with vi.restoreAllMocks().”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
beforeEach(() => {
vi.useFakeTimers();
checkAddressAvailability.mockResolvedValue({ available: true, suggestion: null });
});
afterEach(() => {
vi.useRealTimers();
vi.clearAllMocks();
});
beforeEach(() => {
vi.restoreAllMocks();
vi.useFakeTimers();
checkAddressAvailability.mockResolvedValue({ available: true, suggestion: null });
});
afterEach(() => {
vi.useRealTimers();
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.test.ts` around
lines 31 - 39, Update the test setup around beforeEach and afterEach to call
vi.restoreAllMocks() at the start of beforeEach before configuring
checkAddressAvailability.mockResolvedValue. Remove the vi.clearAllMocks() call
from afterEach while preserving fake-timer setup and restoration.

Source: Coding guidelines

Comment on lines +161 to +175
test('When checkAvailability is called on submit, then it re-queries the backend with the current username', async () => {
const { result } = renderValidationHook();
await typeAndSettle(result, 'jane.doe');
checkAddressAvailability.mockClear();
checkAddressAvailability.mockResolvedValue({ available: false, suggestion: 'jane.doe1@inxt.me' });

let outcome;
await act(async () => {
outcome = await result.current.checkAvailability();
});

expect(checkAddressAvailability).toHaveBeenCalledWith('jane.doe', DOMAIN);
expect(outcome).toEqual({ status: 'taken', suggestion: 'jane.doe1@inxt.me' });
expect(result.current.canSubmit).toBe(false);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Cover a check that becomes stale before resolving.

Add a deferred-request test that changes the username or domain before the manual availability request resolves and asserts that the old successful result cannot authorize submission. This regression test is required for the stale-result path at useEmailAddressValidation.ts Lines 56-65.

As per coding guidelines, tests must cover edge cases and rejection paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.test.ts` around
lines 161 - 175, Add a deferred-request test for checkAvailability that starts
with one username/domain, changes the current input before the availability
promise resolves, then resolves the old request successfully and asserts its
result cannot set canSubmit to true or authorize submission. Cover the
stale-result path in useEmailAddressValidation and include the rejection
behavior if the existing test utilities support it.

Source: Coding guidelines

Comment on lines +56 to +65
const checkAvailability = useCallback(async (): Promise<AddressAvailability> => {
if (!isEmailAddressFormatValid(username)) return UNKNOWN_AVAILABILITY;

const requestId = ++latestRequestIdRef.current;
const result = await fetchAvailability(username, domain);
if (requestId === latestRequestIdRef.current) {
setLastCheck({ value: username, domain, result });
}

return result;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not return a stale availability result to the submit flow.

The request-ID check only protects lastCheck; the stale result is still returned. If the username or domain changes while this request is pending, useUpdateEmail.submit() can accept the old result and advance with values captured before the await. Invalidate requests immediately on input/domain changes and return a non-success state when the request is no longer current.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/identity-setup/hooks/useEmailAddressValidation.ts` around lines
56 - 65, Update checkAvailability in useEmailAddressValidation so requests are
invalidated immediately when the username or domain changes, and ensure a
request whose requestId no longer matches latestRequestIdRef.current returns a
non-success availability state instead of its stale result. Keep lastCheck
updates restricted to the current request, and preserve the existing
valid-result behavior when the request remains current.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant