From fd3530ac62dec270a1e9cba493773534635e3e89 Mon Sep 17 00:00:00 2001 From: Alex Turchyn Date: Fri, 8 Nov 2024 20:14:43 +0200 Subject: [PATCH] update Webhooks UI --- app/controllers/webhook_secret_controller.rb | 3 +- .../webhook_settings_controller.rb | 51 +++++++-- app/views/icons/_lock.html.erb | 5 + app/views/webhook_settings/index.html.erb | 34 ++++++ app/views/webhook_settings/new.html.erb | 29 +++++ app/views/webhook_settings/show.html.erb | 96 ++++++++++++----- config/locales/i18n.yml | 40 +++++-- config/routes.rb | 4 +- spec/system/template_spec.rb | 4 +- spec/system/webhook_settings_spec.rb | 100 ++++++++++++++++-- 10 files changed, 312 insertions(+), 54 deletions(-) create mode 100644 app/views/icons/_lock.html.erb create mode 100644 app/views/webhook_settings/index.html.erb create mode 100644 app/views/webhook_settings/new.html.erb diff --git a/app/controllers/webhook_secret_controller.rb b/app/controllers/webhook_secret_controller.rb index 27f35b26..b9b8a3f2 100644 --- a/app/controllers/webhook_secret_controller.rb +++ b/app/controllers/webhook_secret_controller.rb @@ -10,7 +10,8 @@ class WebhookSecretController < ApplicationController webhook_secret_params[:key] => webhook_secret_params[:value] }.compact_blank) - redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_secret_has_been_saved')) + redirect_back(fallback_location: settings_webhook_path(@webhook_url), + notice: I18n.t('webhook_secret_has_been_saved')) end private diff --git a/app/controllers/webhook_settings_controller.rb b/app/controllers/webhook_settings_controller.rb index 2c6362af..1c6e8ee6 100644 --- a/app/controllers/webhook_settings_controller.rb +++ b/app/controllers/webhook_settings_controller.rb @@ -1,24 +1,55 @@ # frozen_string_literal: true class WebhookSettingsController < ApplicationController - before_action :load_webhook_url + before_action :load_webhook_url, only: %i[show update destroy] authorize_resource :webhook_url, parent: false + def index + @webhook_urls = current_account.webhook_urls.order(id: :desc) + @webhook_url = @webhook_urls.first_or_initialize + + render @webhook_urls.size > 1 ? 'index' : 'show' + end + def show; end + def new + @webhook_url = current_account.webhook_urls.build + end + def create - @webhook_url.assign_attributes(webhook_params) + @webhook_url = current_account.webhook_urls.build(create_webhook_params) - @webhook_url.url.present? ? @webhook_url.save! : @webhook_url.delete + @webhook_url.save! - redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_url_has_been_saved')) + redirect_to settings_webhooks_path, notice: I18n.t('webhook_url_has_been_saved') end def update + @webhook_url.update!(update_webhook_params) + + redirect_to settings_webhook_path(@webhook_url), notice: I18n.t('webhook_url_has_been_updated') + end + + def destroy + @webhook_url.delete + + redirect_to settings_webhooks_path, notice: I18n.t('webhook_url_has_been_deleted') + end + + def resend submitter = current_account.submitters.where.not(completed_at: nil).order(:id).last + webhook = current_account.webhook_urls + .where(Arel::Table.new(:webhook_urls)[:events].matches('%"form.completed"%')) + .find_by(id: params[:webhook_id]) + + if submitter.blank? || webhook.blank? + return redirect_back(fallback_location: settings_webhooks_path, + alert: I18n.t('unable_to_resend_webhook_request')) + end SendFormCompletedWebhookRequestJob.perform_async('submitter_id' => submitter.id, - 'webhook_url_id' => @webhook_url.id) + 'webhook_url_id' => webhook.id) redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_request_has_been_sent')) end @@ -26,10 +57,16 @@ class WebhookSettingsController < ApplicationController private def load_webhook_url - @webhook_url = current_account.webhook_urls.first_or_initialize + @webhook_url = current_account.webhook_urls.find_by(id: params[:id]) + + redirect_to settings_webhooks_path unless @webhook_url + end + + def create_webhook_params + params.require(:webhook_url).permit(:url, events: []).reverse_merge(events: []) end - def webhook_params + def update_webhook_params params.require(:webhook_url).permit(:url) end end diff --git a/app/views/icons/_lock.html.erb b/app/views/icons/_lock.html.erb new file mode 100644 index 00000000..b0c02c4a --- /dev/null +++ b/app/views/icons/_lock.html.erb @@ -0,0 +1,5 @@ + + + + + diff --git a/app/views/webhook_settings/index.html.erb b/app/views/webhook_settings/index.html.erb new file mode 100644 index 00000000..f85cd8a1 --- /dev/null +++ b/app/views/webhook_settings/index.html.erb @@ -0,0 +1,34 @@ +
+ <%= render 'shared/settings_nav' %> +
+
+

Webhooks

+
+ <%= render 'shared/test_mode_toggle' %> + <% if @webhook_url.persisted? %> + <%= link_to new_settings_webhook_path, class: 'md:ml-3 btn bg-white btn-outline btn-md gap-2 w-full md:w-fit', data: { turbo_frame: 'modal' } do %> + <%= svg_icon('plus', class: 'w-6 h-6') %> + <%= t('new_webhook') %> + <% end %> + <% end %> +
+
+
+ <% @webhook_urls.each do |webhook_url| %> + <%= link_to settings_webhook_path(webhook_url), class: 'card bg-base-200' do %> +
+

+ <%= svg_icon('world', class: 'w-6 h-6 shrink-0') %> + <%= webhook_url.url %> +

+
+ <% webhook_url.events.each do |event| %> + <%= event %> + <% end %> +
+
+ <% end %> + <% end %> +
+
+
diff --git a/app/views/webhook_settings/new.html.erb b/app/views/webhook_settings/new.html.erb new file mode 100644 index 00000000..5a7dc7ff --- /dev/null +++ b/app/views/webhook_settings/new.html.erb @@ -0,0 +1,29 @@ +<%= render 'shared/turbo_modal', title: t('new_webhook') do %> + <%= form_for @webhook_url, url: settings_webhooks_path, html: { class: 'space-y-4' }, data: { turbo_frame: :_top } do |f| %> +
+
+ <%= f.label :url, 'Webhook URL', class: 'label' %> + <%= f.url_field :url, class: 'base-input', placeholder: 'https://example.com/hook', required: true %> +
+
+ <% WebhookUrl::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %> +
+ <%= f.collection_check_boxes(:events, events, :to_s, :to_s, include_hidden: false) do |b| %> +
+ +
+ <% end %> +
+ <% end %> +
+
+
+ <%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %> +
+ <% end %> +<% end %> diff --git a/app/views/webhook_settings/show.html.erb b/app/views/webhook_settings/show.html.erb index 6c305d88..e9747809 100644 --- a/app/views/webhook_settings/show.html.erb +++ b/app/views/webhook_settings/show.html.erb @@ -1,38 +1,78 @@
<%= render 'shared/settings_nav' %>
-
-

Webhooks

- <%= render 'shared/test_mode_toggle' %> +
+

Webhook

+
+ <% if params[:action] == 'index' %> + <%= render 'shared/test_mode_toggle' %> + <% end %> + <% if @webhook_url.persisted? && params[:action] == 'index' %> + <%= link_to new_settings_webhook_path, class: 'md:ml-3 btn bg-white btn-outline btn-md gap-2 w-full md:w-fit', data: { turbo_frame: 'modal' } do %> + <%= svg_icon('plus', class: 'w-6 h-6') %> + <%= t('new_webhook') %> + <% end %> + <% end %> +
- <%= form_for @webhook_url, url: settings_webhooks_path, method: :post, html: { autocomplete: 'off' } do |f| %> - <%= f.label :url, 'Webhook URL', class: 'text-sm font-semibold' %> -
- <%= f.url_field :url, class: 'input font-mono input-bordered w-full', placeholder: 'https://example.com/hook' %> +
+ <%= label_tag :url, 'Webhook URL', class: 'text-sm font-semibold' %> + <% if @webhook_url.persisted? %> +
+ <%= link_to webhook_secret_path(@webhook_url), class: 'btn btn-outline btn-sm bg-white', data: { turbo_frame: 'modal' } do %> + <%= svg_icon('lock', class: 'w-4 h-4') %> + <%= @webhook_url.secret.present? ? t('edit_secret') : t('add_secret') %> + <% end %> +
+ <%= button_to settings_webhook_path(@webhook_url), class: 'btn btn-warning btn-sm', method: :delete, data: { turbo_confirm: t('are_you_sure_') } do %> + <%= t('delete') %> + <% end %> +
+
+ <% end %> +
+ <%= form_for @webhook_url, url: @webhook_url.persisted? ? settings_webhook_path(@webhook_url) : settings_webhooks_path, html: { autocomplete: 'off' }, data: { turbo: false } do |f| %> +
+ <%= f.url_field :url, class: 'input font-mono input-bordered w-full', placeholder: 'https://example.com/hook', required: true %> <%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button w-full md:w-32' %> - <% if @webhook_url.persisted? %> - - <%= @webhook_url.secret.present? ? t('edit_secret') : t('add_secret') %> - - <% end %>
+ <% unless @webhook_url.persisted? %> +
+ <% WebhookUrl::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %> +
+ <%= f.collection_check_boxes(:events, events, :to_s, :to_s, include_hidden: false) do |b| %> +
+ +
+ <% end %> +
+ <% end %> +
+ <% end %> <% end %> - <%= form_for @webhook_url, url: @webhook_url.url.present? ? webhook_preference_path(@webhook_url) : '', method: :put, html: { autocomplete: 'off' } do |f| %> - <% WebhookUrl::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %> -
- <% events.each do |event| %> - <%= f.fields_for :events do |ff| %> -
- -
- <% end %> + <% if @webhook_url.persisted? %> + <%= form_for @webhook_url, url: webhook_preference_path(@webhook_url), method: :put, html: { autocomplete: 'off', class: 'mt-2' } do |f| %> +
+ <% WebhookUrl::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %> +
+ <% events.each do |event| %> + <%= f.fields_for :events do |ff| %> +
+ +
+ <% end %> + <% end %> +
<% end %>
<% end %> @@ -44,12 +84,12 @@
-
+
<%= t('submission_example_payload') %> <% if @webhook_url.url.present? && @webhook_url.events.include?('form.completed') %> - <%= button_to button_title(title: 'Test Webhook', disabled_with: t('sending'), icon_disabled: svg_icon('loader', class: 'w-4 h-4 animate-spin')), settings_webhooks_path, class: 'btn btn-neutral btn-outline btn-sm', method: :put %> + <%= button_to button_title(title: 'Test Webhook', disabled_with: t('sending'), icon_disabled: svg_icon('loader', class: 'w-4 h-4 animate-spin')), settings_webhook_resend_path(@webhook_url), class: 'btn btn-neutral btn-outline btn-sm', method: :post %> <% end %>
diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index e9220590..12b896aa 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -511,13 +511,17 @@ en: &en webhook_secret_has_been_saved: Webhook Secret has been saved. webhook_url_has_been_saved: Webhook URL has been saved. webhook_request_has_been_sent: Webhook request has been sent. + webhook_url_has_been_updated: Webhook URL has been updated. + webhook_url_has_been_deleted: Webhook URL has been deleted. + unable_to_resend_webhook_request: Unable to resend webhook request. + new_webhook: New Webhook + delete_webhook: Delete webhook count_submissions_have_been_created: '%{count} submissions have been created.' gmail_has_been_connected: Gmail has been connected microsoft_account_has_been_connected: Microsoft Account has been connected sms_length_cant_be_longer_than_120_bytes: SMS length can't be longer than 120 bytes connected_successfully: Connected successfully. user_nameid_not_found: 'User %{nameid} not found.' - webhook_request_has_been_sent: Webhook request has been sent. sso_settings_have_been_updated: SSO settings have been updated. sms_has_been_sent: SMS has been sent. account_has_been_created: Account has been created. @@ -1156,13 +1160,17 @@ es: &es webhook_secret_has_been_saved: El secreto del Webhook ha sido guardado. webhook_url_has_been_saved: La URL del Webhook ha sido guardada. webhook_request_has_been_sent: La solicitud del Webhook ha sido enviada. + webhook_url_has_been_updated: La URL del Webhook ha sido actualizada. + webhook_url_has_been_deleted: La URL del Webhook ha sido eliminada. + unable_to_resend_webhook_request: No se pudo reenviar la solicitud del webhook. + new_webhook: Nuevo Webhook + delete_webhook: Eliminar webhook count_submissions_have_been_created: '%{count} envíos han sido creados.' gmail_has_been_connected: Gmail ha sido conectado. microsoft_account_has_been_connected: La cuenta de Microsoft ha sido conectada. sms_length_cant_be_longer_than_120_bytes: La longitud del SMS no puede ser mayor a 120 bytes. connected_successfully: Conectado con éxito. user_nameid_not_found: 'Usuario %{nameid} no encontrado.' - webhook_request_has_been_sent: La solicitud del Webhook ha sido enviada. sso_settings_have_been_updated: La configuración de SSO ha sido actualizada. sms_has_been_sent: El SMS ha sido enviado. account_has_been_created: La cuenta ha sido creada. @@ -1801,13 +1809,17 @@ it: &it webhook_secret_has_been_saved: Il segreto del Webhook è stato salvato. webhook_url_has_been_saved: "L'URL del Webhook è stato salvato." webhook_request_has_been_sent: La richiesta del Webhook è stata inviata. + webhook_url_has_been_updated: "L'URL del Webhook è stata aggiornata." + webhook_url_has_been_deleted: "L'URL del Webhook è stata eliminata." + unable_to_resend_webhook_request: Impossibile reinviare la richiesta del webhook. + new_webhook: Nuovo Webhook + delete_webhook: Elimina webhook count_submissions_have_been_created: '%{count} invii sono stati creati.' gmail_has_been_connected: Gmail è stato connesso. microsoft_account_has_been_connected: "L'account Microsoft è stato connesso." sms_length_cant_be_longer_than_120_bytes: "La lunghezza dell'SMS non può superare i 120 byte." connected_successfully: Collegamento avvenuto con successo. user_nameid_not_found: 'Utente %{nameid} non trovato.' - webhook_request_has_been_sent: La richiesta del Webhook è stata inviata. sso_settings_have_been_updated: Le impostazioni SSO sono state aggiornate. sms_has_been_sent: "L'SMS è stato inviato." account_has_been_created: "L'account è stato creato." @@ -2447,13 +2459,17 @@ fr: &fr webhook_secret_has_been_saved: Le secret du Webhook a été enregistré. webhook_url_has_been_saved: "L'URL du Webhook a été enregistrée." webhook_request_has_been_sent: La demande du Webhook a été envoyée. + webhook_url_has_been_updated: "L'URL du Webhook a été mise à jour." + webhook_url_has_been_deleted: "L'URL du Webhook a été supprimée." + unable_to_resend_webhook_request: Impossible de renvoyer la requête du webhook. + new_webhook: Nouveau Webhook + delete_webhook: Supprimer le webhook count_submissions_have_been_created: '%{count} soumissions ont été créées.' gmail_has_been_connected: Gmail a été connecté. microsoft_account_has_been_connected: Le compte Microsoft a été connecté. sms_length_cant_be_longer_than_120_bytes: La longueur du SMS ne peut pas dépasser 120 octets. connected_successfully: Connecté avec succès. user_nameid_not_found: 'Utilisateur %{nameid} introuvable.' - webhook_request_has_been_sent: La demande du Webhook a été envoyée. sso_settings_have_been_updated: Les paramètres de SSO ont été mis à jour. sms_has_been_sent: Le SMS a été envoyé. account_has_been_created: Le compte a été créé. @@ -3092,13 +3108,17 @@ pt: &pt webhook_secret_has_been_saved: O segredo do Webhook foi salvo. webhook_url_has_been_saved: A URL do Webhook foi salva. webhook_request_has_been_sent: A solicitação do Webhook foi enviada. + webhook_url_has_been_updated: URL do Webhook foi atualizada. + webhook_url_has_been_deleted: URL do Webhook foi excluída. + unable_to_resend_webhook_request: Não foi possível reenviar a solicitação do webhook. + new_webhook: Novo Webhook + delete_webhook: Excluir webhook count_submissions_have_been_created: '%{count} submissões foram criadas.' gmail_has_been_connected: O Gmail foi conectado microsoft_account_has_been_connected: A conta da Microsoft foi conectada sms_length_cant_be_longer_than_120_bytes: O comprimento do SMS não pode ultrapassar 120 bytes connected_successfully: Conectado com sucesso. user_nameid_not_found: 'Usuário %{nameid} não encontrado.' - webhook_request_has_been_sent: A solicitação do Webhook foi enviada. sso_settings_have_been_updated: As configurações de SSO foram atualizadas. sms_has_been_sent: O SMS foi enviado. account_has_been_created: A conta foi criada. @@ -3699,8 +3719,8 @@ de: &de api_key: API-Schlüssel logo: Logo back: Zurück - add_secret: Geheimnis hinzufügen - edit_secret: Geheimnis bearbeiten + add_secret: Geheimnis hinzuf + edit_secret: Geheimnis bearb submission_example_payload: Beispiel-Payload für Einreichung there_are_no_signatures: Es gibt keine Unterschriften signed_with_trusted_certificate: Signiert mit vertrauenswürdigem Zertifikat @@ -3737,13 +3757,17 @@ de: &de webhook_secret_has_been_saved: Das Webhook-Geheimnis wurde gespeichert. webhook_url_has_been_saved: Die Webhook-URL wurde gespeichert. webhook_request_has_been_sent: Die Webhook-Anfrage wurde gesendet. + webhook_url_has_been_updated: Webhook-URL wurde aktualisiert. + webhook_url_has_been_deleted: Webhook-URL wurde gelöscht. + unable_to_resend_webhook_request: Webhook-Anfrage konnte nicht erneut gesendet werden. + new_webhook: Neuer Webhook + delete_webhook: Webhook löschen count_submissions_have_been_created: '%{count} Einreichungen wurden erstellt.' gmail_has_been_connected: Gmail wurde verbunden. microsoft_account_has_been_connected: Microsoft-Konto wurde verbunden. sms_length_cant_be_longer_than_120_bytes: Die SMS-Länge darf 120 Bytes nicht überschreiten. connected_successfully: Erfolgreich verbunden. user_nameid_not_found: 'Benutzer %{nameid} nicht gefunden.' - webhook_request_has_been_sent: Die Webhook-Anfrage wurde gesendet. sso_settings_have_been_updated: Die SSO-Einstellungen wurden aktualisiert. sms_has_been_sent: Die SMS wurde gesendet. account_has_been_created: Das Konto wurde erstellt. diff --git a/config/routes.rb b/config/routes.rb index a2d5af4b..01ef6759 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -168,7 +168,9 @@ Rails.application.routes.draw do defaults: { status: :integration } resource :personalization, only: %i[show create], controller: 'personalization_settings' resources :api, only: %i[index create], controller: 'api_settings' - resource :webhooks, only: %i[show create update], controller: 'webhook_settings' + resources :webhooks, except: %i[edit], controller: 'webhook_settings' do + post :resend + end resource :account, only: %i[show update destroy] resources :profile, only: %i[index] do collection do diff --git a/spec/system/template_spec.rb b/spec/system/template_spec.rb index 859b654d..0e36ef94 100644 --- a/spec/system/template_spec.rb +++ b/spec/system/template_spec.rb @@ -44,7 +44,9 @@ RSpec.describe 'Template' do it 'archives a template' do expect do - click_button 'Archive' + accept_confirm('Are you sure?') do + click_button 'Archive' + end end.to change { Template.active.count }.by(-1) expect(page).to have_content('Template has been archived') diff --git a/spec/system/webhook_settings_spec.rb b/spec/system/webhook_settings_spec.rb index a12b98f8..b999b753 100644 --- a/spec/system/webhook_settings_spec.rb +++ b/spec/system/webhook_settings_spec.rb @@ -10,22 +10,58 @@ RSpec.describe 'Webhook Settings' do sign_in(user) end - it 'shows webhook settings page' do + it 'shows webhook settings page with empty form when there are no webhooks' do + visit settings_webhooks_path + + expect(page).to have_content('Webhook') + expect(page).to have_content('Webhook URL') + expect(page).to have_field('webhook_url[url]', type: 'url') + expect(page).to have_button('Save') + + WebhookUrl::EVENTS.each do |event| + expect(page).to have_field(event, type: 'checkbox') + end + end + + it 'shows list of webhooks when there are more than one' do + webhook_urls = create_list(:webhook_url, 2, account:) + visit settings_webhooks_path expect(page).to have_content('Webhooks') - expect(page).to have_field('Webhook URL') + expect(page).to have_link('New Webhook') + + webhook_urls.each do |webhook_url| + expect(page).to have_content(webhook_url.url) + + within("a[href='#{settings_webhook_path(webhook_url)}']") do + webhook_url.events.each do |event| + expect(page).to have_content(event) + end + end + end + end + + it 'shows webhook settings page with pre-filled form when there is one webhook' do + webhook_url = create(:webhook_url, account:) + + visit settings_webhooks_path + + expect(page).to have_content('Webhook') + expect(page).to have_field('webhook_url[url]', type: 'url', with: webhook_url.url) expect(page).to have_button('Save') + expect(page).to have_button('Delete') + expect(page).to have_link('Add Secret') WebhookUrl::EVENTS.each do |event| - expect(page).to have_field(event, type: 'checkbox', disabled: true) + expect(page).to have_field(event, type: 'checkbox', checked: webhook_url.events.include?(event)) end end it 'creates the webhook' do visit settings_webhooks_path - fill_in 'Webhook URL', with: 'https://example.com/webhook' + fill_in 'webhook_url[url]', with: 'https://example.com/webhook' expect do click_button 'Save' @@ -34,6 +70,8 @@ RSpec.describe 'Webhook Settings' do webhook_url = account.webhook_urls.first expect(webhook_url.url).to eq('https://example.com/webhook') + expect(page).to have_content('Webhook URL has been saved.') + expect(page.current_path).to eq(settings_webhooks_path) end it 'updates the webhook' do @@ -41,12 +79,14 @@ RSpec.describe 'Webhook Settings' do visit settings_webhooks_path - fill_in 'Webhook URL', with: 'https://example.org/webhook' + fill_in 'webhook_url[url]', with: 'https://example.org/webhook' click_button 'Save' webhook_url.reload expect(webhook_url.url).to eq('https://example.org/webhook') + expect(page).to have_content('Webhook URL has been updated.') + expect(page.current_path).to eq(settings_webhook_path(webhook_url)) end it 'deletes the webhook' do @@ -54,11 +94,14 @@ RSpec.describe 'Webhook Settings' do visit settings_webhooks_path - fill_in 'Webhook URL', with: '' - expect do - click_button 'Save' + accept_confirm('Are you sure?') do + click_button 'Delete' + end end.to change(WebhookUrl, :count).by(-1) + + expect(page).to have_content('Webhook URL has been deleted.') + expect(page.current_path).to eq(settings_webhooks_path) end it 'updates the webhook events' do @@ -94,6 +137,9 @@ RSpec.describe 'Webhook Settings' do expect(webhook_url.secret).to eq({ 'X-Signature' => 'secret-value' }) end + + expect(page).to have_link('Edit Secret') + expect(page).to have_content('Webhook Secret has been saved.') end it 'removes a secret from the webhook' do @@ -113,5 +159,43 @@ RSpec.describe 'Webhook Settings' do expect(webhook_url.secret).to eq({}) end + + expect(page).to have_link('Add Secret') + expect(page).to have_content('Webhook Secret has been saved.') + end + + context 'when testing the webhook' do + let!(:webhook_url) { create(:webhook_url, account:) } + let!(:template) { create(:template, account:, author: user) } + let!(:submission) { create(:submission, template:, created_by_user: user) } + let!(:submitter) do + create(:submitter, submission:, uuid: template.submitters.first['uuid'], completed_at: Time.current) + end + + it 'sends the webhook request' do + visit settings_webhooks_path + + expect do + click_button 'Test Webhook' + end.to change(SendFormCompletedWebhookRequestJob.jobs, :size).by(1) + + args = SendFormCompletedWebhookRequestJob.jobs.last['args'].first + + expect(args['webhook_url_id']).to eq(webhook_url.id) + expect(args['submitter_id']).to eq(submitter.id) + expect(page).to have_content('Webhook request has been sent.') + end + + it "doesn't resend the webhook request when the webhook is doesn't exist" do + visit settings_webhooks_path + + webhook_url.destroy + + expect do + click_button 'Test Webhook' + end.not_to change(SendFormCompletedWebhookRequestJob.jobs, :size) + + expect(page).to have_content('Unable to resend webhook request.') + end end end