diff --git a/app/components/dsfr/input_component.rb b/app/components/dsfr/input_component.rb index 3ee07149b..367ed74b0 100644 --- a/app/components/dsfr/input_component.rb +++ b/app/components/dsfr/input_component.rb @@ -32,7 +32,7 @@ class Dsfr::InputComponent < ApplicationComponent }.merge(input_group_error_class_names)) } if email? - opts[:data] = { controller: 'email-input' } + opts[:data] = { controller: 'email-input', email_input_url_value: show_email_suggestions_path } end opts end diff --git a/app/controllers/email_checker_controller.rb b/app/controllers/email_checker_controller.rb new file mode 100644 index 000000000..b794b4d7a --- /dev/null +++ b/app/controllers/email_checker_controller.rb @@ -0,0 +1,5 @@ +class EmailCheckerController < ApplicationController + def show + render json: EmailChecker.check(email: params[:email]) + end +end diff --git a/app/javascript/controllers/email_input_controller.ts b/app/javascript/controllers/email_input_controller.ts index 8eed97fa9..8b64a7e92 100644 --- a/app/javascript/controllers/email_input_controller.ts +++ b/app/javascript/controllers/email_input_controller.ts @@ -1,18 +1,39 @@ -import { suggest } from 'email-butler'; +import { httpRequest } from '@utils'; import { show, hide } from '@utils'; import { ApplicationController } from './application_controller'; +type checkEmailResponse = { + success: boolean; + email_suggestions: string[]; +}; + export class EmailInputController extends ApplicationController { static targets = ['ariaRegion', 'suggestion', 'input']; + static values = { + url: String + }; + + declare readonly urlValue: string; + declare readonly ariaRegionTarget: HTMLElement; declare readonly suggestionTarget: HTMLElement; declare readonly inputTarget: HTMLInputElement; - checkEmail() { - const suggestion = suggest(this.inputTarget.value); - if (suggestion && suggestion.full) { - this.suggestionTarget.innerHTML = suggestion.full; + async checkEmail() { + if (!this.inputTarget.value) { + return; + } + + const url = new URL(this.urlValue, document.baseURI); + url.searchParams.append('email', this.inputTarget.value); + + const data: checkEmailResponse | null = await httpRequest( + url.toString() + ).json(); + + if (data && data.email_suggestions && data.email_suggestions.length > 0) { + this.suggestionTarget.innerHTML = data.email_suggestions[0]; show(this.ariaRegionTarget); this.ariaRegionTarget.setAttribute('aria-live', 'assertive'); } diff --git a/bun.lockb b/bun.lockb index 9cc8b3bb3..7c777a111 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/config/routes.rb b/config/routes.rb index c4973d1ae..8b5f2152e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -161,6 +161,7 @@ Rails.application.routes.draw do end get 'password_complexity' => 'password_complexity#show', as: 'show_password_complexity' + get 'check_email' => 'email_checker#show', as: 'show_email_suggestions' resources :targeted_user_links, only: [:show] diff --git a/package.json b/package.json index 8d5144609..edad7ebc6 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "core-js": "^3.37.1", "date-fns": "^2.30.0", "debounce": "^1.2.1", - "email-butler": "^1.0.13", "geojson": "^0.5.0", "graphiql": "^3.2.3", "graphql": "^16.8.1", diff --git a/spec/controllers/email_checker_controller_spec.rb b/spec/controllers/email_checker_controller_spec.rb new file mode 100644 index 000000000..4572c2cd4 --- /dev/null +++ b/spec/controllers/email_checker_controller_spec.rb @@ -0,0 +1,39 @@ +describe EmailCheckerController, type: :controller do + describe '#show' do + render_views + before { get :show, format: :json, params: params } + let(:body) { JSON.parse(response.body, symbolize_names: true) } + + context 'valid email' do + let(:params) { { email: 'martin@orange.fr' } } + it do + expect(response).to have_http_status(:success) + expect(body).to eq({ success: true }) + end + end + + context 'email with typo' do + let(:params) { { email: 'martin@orane.fr' } } + it do + expect(response).to have_http_status(:success) + expect(body).to eq({ success: true, email_suggestions: ['martin@orange.fr'] }) + end + end + + context 'empty' do + let(:params) { { email: '' } } + it do + expect(response).to have_http_status(:success) + expect(body).to eq({ success: false }) + end + end + + context 'notanemail' do + let(:params) { { email: 'clarkkent' } } + it do + expect(response).to have_http_status(:success) + expect(body).to eq({ success: false }) + end + end + end +end