Heavy Confirmation Flow for DisplayAd-Destroy (#14862)
* wham, bam, done! * refactor and remove switch statement * add guards to handleRecord function * make cypress spec more robust
This commit is contained in:
parent
79a537b62d
commit
9d1eaee84e
6 changed files with 182 additions and 54 deletions
|
|
@ -51,11 +51,9 @@ module Admin
|
|||
@display_ad = DisplayAd.find(params[:id])
|
||||
|
||||
if @display_ad.destroy
|
||||
flash[:success] = "Display Ad has been deleted!"
|
||||
redirect_to admin_display_ads_path
|
||||
render json: { message: "Display Ad has been deleted!" }, status: :ok
|
||||
else
|
||||
flash[:danger] = "Something went wrong with deleting the Display Ad."
|
||||
render :edit
|
||||
render json: { error: "Something went wrong with deleting the Display Ad." }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,20 +13,38 @@ window.addEventListener('load', () => {
|
|||
}
|
||||
});
|
||||
|
||||
const nonRedirectEndpoints = [
|
||||
'/admin/content_manager/badge_achievements',
|
||||
'/admin/customization/display_ads',
|
||||
];
|
||||
|
||||
const redirectEndpoints = ['/admin/advanced/broadcasts'];
|
||||
|
||||
export default class ConfirmationModalController extends ModalController {
|
||||
static targets = ['itemId', 'username', 'endpoint'];
|
||||
|
||||
removeRecordAsync({ id, outcome }) {
|
||||
document.querySelector(`[data-row-id="${id}"]`).remove();
|
||||
displaySnackbar(outcome.message);
|
||||
}
|
||||
|
||||
redirectAfterDestroy({ endpoint, outcome }) {
|
||||
localStorage.setItem('outcome', outcome.message);
|
||||
window.location.replace(`${endpoint}?redirected`);
|
||||
}
|
||||
|
||||
handleRecord({ endpoint, id, outcome }) {
|
||||
switch (endpoint) {
|
||||
case '/admin/content_manager/badge_achievements':
|
||||
document.querySelector(`[data-row-id="${id}"]`).remove();
|
||||
displaySnackbar(outcome.message);
|
||||
break;
|
||||
case '/admin/advanced/broadcasts':
|
||||
localStorage.setItem('outcome', outcome.message);
|
||||
window.location.replace(`${endpoint}?redirected`);
|
||||
break;
|
||||
if (nonRedirectEndpoints.includes(endpoint)) {
|
||||
this.removeRecordAsync({ id, outcome });
|
||||
return;
|
||||
}
|
||||
|
||||
if (redirectEndpoints.includes(endpoint)) {
|
||||
this.redirectAfterDestroy({ endpoint, outcome });
|
||||
return;
|
||||
}
|
||||
|
||||
displayErrorAlert('Something went wrong.');
|
||||
}
|
||||
|
||||
async sendToEndpoint({ itemId, endpoint }) {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,56 @@
|
|||
<nav class="flex mb-4" aria-label="Display Ads navigation">
|
||||
<%= form_tag(admin_display_ads_path, method: "get") do %>
|
||||
<%= text_field_tag(:search, params[:search], aria: { label: "Search" }, class: "crayons-header--search-input crayons-textfield", placeholder: "Search by Org name") %>
|
||||
<% end %>
|
||||
<div class="ml-auto">
|
||||
<div class="justify-content-end">
|
||||
<%= link_to "Make A New Display Ad", new_admin_display_ad_path, class: "crayons-btn" %>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<%= paginate @display_ads %>
|
||||
|
||||
<table class="crayons-table" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">Organization</th>
|
||||
<th scope="col">Placement Area</th>
|
||||
<th scope="col">Published</th>
|
||||
<th scope="col">Approved</th>
|
||||
<th scope="col">Success Rate</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="crayons-card">
|
||||
<% @display_ads.each do |display_ad| %>
|
||||
<tr>
|
||||
<td><%= link_to display_ad.id, edit_admin_display_ad_path(display_ad) %></td>
|
||||
<td><%= link_to display_ad.organization.name, admin_organization_path(display_ad.organization) %></td>
|
||||
<td><%= display_ad.human_readable_placement_area %></td>
|
||||
<td><%= display_ad.published %></td>
|
||||
<td><%= display_ad.approved %></td>
|
||||
<td><%= display_ad.success_rate %></td>
|
||||
<td><%= link_to "Edit", edit_admin_display_ad_path(display_ad), class: "crayons-btn" %></td>
|
||||
<td><%= link_to "Destroy", admin_display_ad_path(display_ad), class: "crayons-btn crayons-btn--danger", method: :delete, data: { confirm: "Are you sure?" } %></td>
|
||||
</tr>
|
||||
<div
|
||||
data-controller="confirmation-modal"
|
||||
data-confirmation-modal-root-selector-value="#confirmation-modal-root"
|
||||
data-confirmation-modal-content-selector-value="#confirmation-modal"
|
||||
data-confirmation-modal-title-value="Confirm changes"
|
||||
data-confirmation-modal-size-value="m">
|
||||
<nav class="flex mb-4" aria-label="Display Ads navigation">
|
||||
<%= form_tag(admin_display_ads_path, method: "get") do %>
|
||||
<%= text_field_tag(:search, params[:search], aria: { label: "Search" }, class: "crayons-header--search-input crayons-textfield", placeholder: "Search by Org name") %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="ml-auto">
|
||||
<div class="justify-content-end">
|
||||
<%= link_to "Make A New Display Ad", new_admin_display_ad_path, class: "crayons-btn" %>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<%= paginate @display_ads %>
|
||||
<%= paginate @display_ads %>
|
||||
|
||||
<table class="crayons-table" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">Organization</th>
|
||||
<th scope="col">Placement Area</th>
|
||||
<th scope="col">Published</th>
|
||||
<th scope="col">Approved</th>
|
||||
<th scope="col">Success Rate</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="crayons-card">
|
||||
<% @display_ads.each do |display_ad| %>
|
||||
<tr data-row-id="<%= display_ad.id %>">
|
||||
<td><%= link_to display_ad.id, edit_admin_display_ad_path(display_ad) %></td>
|
||||
<td><%= link_to display_ad.organization.name, admin_organization_path(display_ad.organization) %></td>
|
||||
<td><%= display_ad.human_readable_placement_area %></td>
|
||||
<td><%= display_ad.published %></td>
|
||||
<td><%= display_ad.approved %></td>
|
||||
<td><%= display_ad.success_rate %></td>
|
||||
<td><%= link_to "Edit", edit_admin_display_ad_path(display_ad), class: "crayons-btn" %></td>
|
||||
<td>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--danger"
|
||||
data-item-id="<%= display_ad.id %>"
|
||||
data-endpoint="/admin/customization/display_ads"
|
||||
data-username="<%= current_user.username %>"
|
||||
data-action="click->confirmation-modal#openModal">Destroy</button>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<%= render partial: "admin/shared/destroy_confirmation_modal" %>
|
||||
|
||||
<%= paginate @display_ads %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
describe('Display Ads', () => {
|
||||
beforeEach(() => {
|
||||
cy.testSetup();
|
||||
cy.fixture('users/adminUser.json').as('user');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.loginAndVisit(user, '/admin/customization/display_ads');
|
||||
|
||||
cy.findByRole('table').within(() => {
|
||||
cy.findByRole('button', { name: 'Destroy' }).click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete a display ad', () => {
|
||||
it('should display confirmation modal', () => {
|
||||
cy.findByRole('dialog').contains('Confirm changes').should('be.visible');
|
||||
});
|
||||
|
||||
it('should display warning text if confirmation text does not match', () => {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.get('input').type('Text that does not match.');
|
||||
cy.findByRole('button', { name: 'Confirm changes' }).click();
|
||||
|
||||
cy.get('.crayons-notice')
|
||||
.contains('The confirmation text did not match.')
|
||||
.should('be.visible');
|
||||
|
||||
cy.findByRole('button', { name: 'Close' }).click();
|
||||
});
|
||||
|
||||
cy.findByRole('table').within(() => {
|
||||
cy.findByRole('button', { name: 'Destroy' }).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove display ad if confirmation text matches', () => {
|
||||
cy.get('@user').then((user) => {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.get('input').type(
|
||||
`My username is @${user.username} and this action is 100% safe and appropriate.`,
|
||||
);
|
||||
cy.findByRole('button', { name: 'Confirm changes' }).click();
|
||||
});
|
||||
|
||||
cy.findByTestId('snackbar').within(() => {
|
||||
cy.findByRole('alert').should(
|
||||
'have.text',
|
||||
'Display Ad has been deleted!',
|
||||
);
|
||||
});
|
||||
|
||||
cy.findByRole('table').within(() => {
|
||||
cy.findByRole('button', { name: 'Destroy' }).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('generates error message when remove action fails', () => {
|
||||
cy.intercept('DELETE', '/admin/customization/display_ads/**', {
|
||||
statusCode: 422,
|
||||
body: {
|
||||
error: 'Something went wrong with deleting the Display Ad.',
|
||||
},
|
||||
});
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.get('input').type(
|
||||
`My username is @${user.username} and this action is 100% safe and appropriate.`,
|
||||
);
|
||||
cy.findByRole('button', { name: 'Confirm changes' }).click();
|
||||
});
|
||||
|
||||
cy.findByTestId('alertzone').within(() => {
|
||||
cy.findByRole('alert')
|
||||
.contains('Something went wrong with deleting the Display Ad.')
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
cy.findByRole('table').within(() => {
|
||||
cy.findByRole('button', { name: 'Destroy' }).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -77,7 +77,6 @@ RSpec.describe "/admin/customization/display_ads", type: :request do
|
|||
expect do
|
||||
delete admin_display_ad_path(display_ad.id)
|
||||
end.to change { DisplayAd.all.count }.by(-1)
|
||||
expect(response.body).to redirect_to admin_display_ads_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -121,7 +120,6 @@ RSpec.describe "/admin/customization/display_ads", type: :request do
|
|||
expect do
|
||||
delete admin_display_ad_path(display_ad.id)
|
||||
end.to change { DisplayAd.all.count }.by(-1)
|
||||
expect(response.body).to redirect_to admin_display_ads_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -622,3 +622,15 @@ seeder.create_if_none(Broadcast) do
|
|||
active: true,
|
||||
)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_none(DisplayAd) do
|
||||
DisplayAd.create!(
|
||||
organization_id: 1,
|
||||
body_markdown: "<h1>This is an add</h1>",
|
||||
placement_area: "sidebar_left",
|
||||
published: true,
|
||||
approved: true,
|
||||
)
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue