diff --git a/app/assets/stylesheets/components/_spinner-button.scss b/app/assets/stylesheets/components/_spinner-button.scss
index cad1be060b1..d26a86ea673 100644
--- a/app/assets/stylesheets/components/_spinner-button.scss
+++ b/app/assets/stylesheets/components/_spinner-button.scss
@@ -1,90 +1,7 @@
-@keyframes spinner-button-dot-one {
- 0% { transform: scale(0); }
- 25% { transform: scale(1); }
- 50% { transform: scale(0); }
-}
-
-@keyframes spinner-button-dot-two {
- 0% { transform: scale(0); }
- 20% { transform: scale(0); }
- 45% { transform: scale(1); }
- 70% { transform: scale(0); }
-}
-
-@keyframes spinner-button-dot-three {
- 0% { transform: scale(0); }
- 40% { transform: scale(0); }
- 65% { transform: scale(1); }
- 90% { transform: scale(0); }
-}
-
-.spinner-button {
- display: inline-block;
-}
-
.spinner-button--spinner-active {
- .spinner-button__content {
- position: relative;
-
- a,
- button:not([type]),
- [type="submit"],
- [type="button"] {
- background-color: color('primary-darker');
- color: transparent;
- opacity: 1;
- }
- }
+ @include u-text('center');
- .spinner-button__spinner {
- display: flex;
- height: 12px;
- left: 50%;
- margin-left: -23px;
- margin-top: -6px;
- pointer-events: none;
- position: absolute;
- top: 50%;
- width: 46px;
- }
-
- .spinner-button__spinner-dot {
- height: 12px;
- margin-left: 5px;
- width: 12px;
-
- &::after {
- animation-duration: 1.25s;
- animation-iteration-count: infinite;
- animation-timing-function: linear;
- background-color: color('white');
- border-radius: 50%;
- content: '';
- display: block;
- height: 100%;
- transform: scale(0);
- width: 100%;
- }
-
- &:first-child {
- margin-left: 0;
- }
-
- &:nth-child(1)::after {
- animation-name: spinner-button-dot-one;
- }
-
- &:nth-child(2)::after {
- animation-name: spinner-button-dot-two;
- }
-
- &:nth-child(3)::after {
- animation-name: spinner-button-dot-three;
- }
+ .spinner-button__content {
+ @include u-display('none');
}
}
-
-.spinner-button__action-message {
- @include u-text('bold', 'primary-darker');
- @include u-margin-top(2);
-}
diff --git a/app/javascript/packs/form-steps-wait.js b/app/javascript/packs/form-steps-wait.js
deleted file mode 100644
index 299138a624b..00000000000
--- a/app/javascript/packs/form-steps-wait.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { loadPolyfills } from '@18f/identity-polyfill';
-
-/**
- * @typedef FormStepsWaitElements
- *
- * @prop {HTMLFormElement} form
- */
-
-/**
- * @typedef FormStepsWaitOptions
- *
- * @prop {number} pollIntervalMs Poll interval.
- * @prop {string} waitStepPath URL path to wait step, used in polling.
- */
-
-/** @type {FormStepsWaitOptions} */
-const DEFAULT_OPTIONS = {
- pollIntervalMs: 3000,
- waitStepPath: `${window.location.pathname}_wait`,
-};
-
-export class FormStepsWait {
- constructor(form) {
- /** @type {FormStepsWaitElements} */
- this.elements = { form };
-
- this.options = {
- ...DEFAULT_OPTIONS,
- ...this.elements.form.dataset,
- };
-
- this.options.pollIntervalMs = Number(this.options.pollIntervalMs);
- }
-
- bind() {
- this.elements.form.addEventListener('submit', (event) => this.handleSubmit(event));
- }
-
- /**
- * @param {Event} event Form submit event.
- */
- async handleSubmit(event) {
- event.preventDefault();
-
- const { form } = this.elements;
- const { action, method } = form;
-
- const response = await window.fetch(action, {
- method,
- body: new window.FormData(form),
- });
-
- this.handleResponse(response);
- }
-
- handleResponse(response) {
- const { waitStepPath, pollIntervalMs } = this.options;
- if (!response.ok) {
- // If form submission fails, assume there's a server-side flash error to be shown to the user.
- window.location.reload();
- } else if (response.redirected && new URL(response.url).pathname !== waitStepPath) {
- window.location.href = response.url;
- } else {
- setTimeout(() => this.poll(), pollIntervalMs);
- }
- }
-
- async poll() {
- const { waitStepPath } = this.options;
- const response = await window.fetch(waitStepPath, { method: 'HEAD' });
- this.handleResponse(response);
- }
-}
-
-loadPolyfills(['fetch']).then(() => {
- const forms = [...document.querySelectorAll('[data-form-steps-wait]')];
- forms.forEach((form) => new FormStepsWait(form).bind());
-});
diff --git a/app/javascript/packs/spinner-button.js b/app/javascript/packs/spinner-button.js
index 78eb173327b..42b2a096e93 100644
--- a/app/javascript/packs/spinner-button.js
+++ b/app/javascript/packs/spinner-button.js
@@ -2,60 +2,30 @@
* @typedef SpinnerButtonElements
*
* @prop {HTMLDivElement} wrapper
+ * @prop {HTMLImageElement} spinner
* @prop {HTMLButtonElement|HTMLInputElement|HTMLLinkElement} button
- * @prop {HTMLDivElement?} actionMessage
*/
-/**
- * @typedef SpinnerButtonOptions
- *
- * @prop {number} longWaitDurationMs
- */
-
-/** @type {SpinnerButtonOptions} */
-const DEFAULT_OPTIONS = {
- longWaitDurationMs: 15000,
-};
-
export class SpinnerButton {
constructor(wrapper) {
/** @type {SpinnerButtonElements} */
this.elements = {
wrapper,
- button: wrapper.querySelector('a,button:not([type]),[type="submit"],[type="button"]'),
- actionMessage: wrapper.querySelector('.spinner-button__action-message'),
- };
-
- this.options = {
- ...DEFAULT_OPTIONS,
- ...this.elements.wrapper.dataset,
+ spinner: wrapper.querySelector('.spinner-button__spinner'),
+ button: wrapper.querySelector('a,button:not([type]),[type="submit"]'),
};
- this.options.longWaitDurationMs = Number(this.options.longWaitDurationMs);
+ this.bindEvents();
}
- bind() {
+ bindEvents() {
this.elements.button.addEventListener('click', () => this.showSpinner());
}
showSpinner() {
- const { wrapper, button, actionMessage } = this.elements;
- wrapper.classList.add('spinner-button--spinner-active');
-
- // Avoid setting disabled immediately to allow click event to propagate for form submission.
- setTimeout(() => button.setAttribute('disabled', ''), 0);
-
- if (actionMessage) {
- actionMessage.textContent = /** @type {string} */ (actionMessage.dataset.message);
- }
-
- setTimeout(() => this.handleLongWait(), this.options.longWaitDurationMs);
- }
-
- handleLongWait() {
- this.elements.actionMessage?.classList.remove('usa-sr-only');
+ this.elements.wrapper.classList.add('spinner-button--spinner-active');
+ this.elements.spinner.classList.remove('usa-sr-only');
}
}
-const wrappers = [...document.querySelectorAll('.spinner-button')];
-wrappers.forEach((wrapper) => new SpinnerButton(wrapper).bind());
+[...document.querySelectorAll('.spinner-button')].forEach((wrapper) => new SpinnerButton(wrapper));
diff --git a/app/views/idv/cac/verify.html.erb b/app/views/idv/cac/verify.html.erb
index 1bd7c488e1d..eb4b99b4e53 100644
--- a/app/views/idv/cac/verify.html.erb
+++ b/app/views/idv/cac/verify.html.erb
@@ -45,26 +45,9 @@
<%= "#{t('in_person_proofing.forms.ssn')}: #{flow_session[:pii_from_doc][:ssn]}" %>
- <%= render 'shared/spinner-button',
- action_message: t('cac_proofing.info.verifying'),
- class: 'grid-col-12 tablet:grid-col-6' do %>
- <%= button_to(
- t('forms.buttons.continue'),
- url_for,
- method: :put,
- form: {
- class: 'button_to read-after-submit',
- data: {
- form_steps_wait: '',
- wait_step_path: idv_cac_step_path(step: :verify_wait),
- poll_interval_ms: AppConfig.env.poll_rate_for_verify_in_seconds.to_i * 1000,
- },
- },
- class: 'btn btn-primary btn-wide width-full'
- ) %>
- <% end %>
+ <%= button_to(t('forms.buttons.continue'), url_for, method: :put,
+ class: 'btn btn-primary btn-wide sm-col-6 col-12') %>
-<% javascript_pack_tag_once 'form-steps-wait' %>
<%= render 'idv/cac/start_over_or_cancel' %>
diff --git a/app/views/idv/doc_auth/verify.html.erb b/app/views/idv/doc_auth/verify.html.erb
index c75ae1c53d9..c0e2ee1e193 100644
--- a/app/views/idv/doc_auth/verify.html.erb
+++ b/app/views/idv/doc_auth/verify.html.erb
@@ -39,27 +39,14 @@
) %>
<%= "#{t('doc_auth.forms.ssn')}: #{flow_session[:pii_from_doc][:ssn]}" %>
-
- <%= render 'shared/spinner-button',
- action_message: t('doc_auth.info.verifying'),
- class: 'grid-col-12 tablet:grid-col-6' do %>
- <%= button_to(
- t('forms.buttons.continue'),
- url_for,
- method: :put,
- form: {
- class: 'button_to read-after-submit',
- data: {
- form_steps_wait: '',
- wait_step_path: idv_doc_auth_step_path(step: :verify_wait),
- poll_interval_ms: AppConfig.env.poll_rate_for_verify_in_seconds.to_i * 1000,
- },
- },
- class: 'btn btn-primary btn-wide width-full',
- ) %>
- <% end %>
+
+ <%= button_to(
+ t('forms.buttons.continue'),
+ url_for,
+ method: :put,
+ class: 'btn btn-primary btn-wide sm-col-6 col-12',
+ ) %>
-<% javascript_pack_tag_once 'form-steps-wait' %>
<%= render 'idv/doc_auth/start_over_or_cancel' %>
diff --git a/app/views/idv/phone/new.html.erb b/app/views/idv/phone/new.html.erb
index cd6d5e56508..480598bf989 100644
--- a/app/views/idv/phone/new.html.erb
+++ b/app/views/idv/phone/new.html.erb
@@ -26,19 +26,8 @@
-<%= validated_form_for(@idv_form,
- url: idv_phone_path,
- data: {
- form_steps_wait: '',
- wait_step_path: idv_phone_path,
- poll_interval_ms: AppConfig.env.poll_rate_for_verify_in_seconds.to_i * 1000,
- },
- html: {
- autocomplete: 'off',
- method: :put,
- role: 'form',
- class: 'mt2',
- }) do |f| %>
+<%= validated_form_for(@idv_form, url: idv_phone_path,
+ html: { autocomplete: 'off', method: :put, role: 'form', class: 'mt2' }) do |f| %>
<%= f.label :phone, label: t('idv.form.phone'), class: 'bold' %>
<%= f.input :phone, required: true, input_html: { aria: { invalid: false }, class: 'sm-col-8' }, label: false,
wrapper_html: { class: 'mr2' } %>
@@ -47,15 +36,9 @@
<%= render 'idv/phone/verification_options' %>
<% end %>
- <%= render 'shared/spinner-button',
- action_message: t('doc_auth.info.verifying'),
- class: 'mt3' do %>
- <%= f.button :submit, t('forms.buttons.continue'), class: 'btn-wide sm-col-6 col-12' %>
- <% end %>
+ <%= f.button :submit, t('forms.buttons.continue'), class: 'btn-wide mt3 sm-col-6 col-12' %>
<% end %>
<%= link_to t('links.cancel'), idv_cancel_path, class: 'h5' %>
-
-<% javascript_pack_tag_once 'form-steps-wait' %>
diff --git a/app/views/shared/_spinner-button.html.erb b/app/views/shared/_spinner-button.html.erb
index 7feff00cbc1..bf882f96192 100644
--- a/app/views/shared/_spinner-button.html.erb
+++ b/app/views/shared/_spinner-button.html.erb
@@ -1,30 +1,19 @@
<%#
yields: Button or link markup (required).
-locals:
-* action_message: Message describing the action being performed, shown visually to users when the
- animation has been active for a long time, and immediately to users of assistive
- technology.
-* class: Additional class names to add to alert wrapper.
%>
<%
content = yield.presence or raise "no block content given"
- classes = ['spinner-button']
- classes << local_assigns[:class] if local_assigns[:class]
%>
-<%= tag.div class: classes do %>
+
<% javascript_pack_tag_once 'spinner-button' %>
diff --git a/config/locales/cac_proofing/en.yml b/config/locales/cac_proofing/en.yml
index 7fa25e918f0..2b5ee75b4b3 100644
--- a/config/locales/cac_proofing/en.yml
+++ b/config/locales/cac_proofing/en.yml
@@ -28,7 +28,6 @@ en:
your PIV/CAC PIN and have you select a certificate.
state_id_description: If you don't have a PIV or CAC, you can use a state-issued
ID to verify your identity.
- verifying: Verifying…
welcome: We verify your identity to make sure you are you—not someone pretending
to be you. Verifying your identity also allows you to access services that
handle Personal Identifiable Information.
diff --git a/config/locales/cac_proofing/es.yml b/config/locales/cac_proofing/es.yml
index e2d9bccdab0..95bd207d7f2 100644
--- a/config/locales/cac_proofing/es.yml
+++ b/config/locales/cac_proofing/es.yml
@@ -27,7 +27,6 @@ es:
pedirá su PIN de PIV / CAC y le pedirá que seleccione un certificado.
state_id_description: Si no tiene un PIV o CAC, pude usar una identificación
emitida por el estado para verificar su identidad.
- verifying: Verificando…
welcome: Verificamos su identidad para asegurarnos de que es usted, no alguien
que finge ser usted. La verificación de su identidad también le permite acceder
a los servicios que manejan información de identificación personal.
diff --git a/config/locales/cac_proofing/fr.yml b/config/locales/cac_proofing/fr.yml
index 35cd61e411a..706d04b3c81 100644
--- a/config/locales/cac_proofing/fr.yml
+++ b/config/locales/cac_proofing/fr.yml
@@ -33,7 +33,6 @@ fr:
un certificat.
state_id_description: Si vous n'avez pas de PIV ou de CAC, vous pouvez utiliser
un identifiant émis par l'État pour vérifier votre identité.
- verifying: Vérification…
welcome: Nous vérifions votre identité pour nous assurer que vous êtes bien
vous, et non quelqu'un qui se fait passer pour vous. La vérification de votre
identité vous permet également d'accéder aux services qui traitent les informations
diff --git a/config/locales/doc_auth/en.yml b/config/locales/doc_auth/en.yml
index 51bd21afc08..bc62dfa0633 100644
--- a/config/locales/doc_auth/en.yml
+++ b/config/locales/doc_auth/en.yml
@@ -141,7 +141,6 @@ en:
identity.
use_cac: Do you have a government employee ID?
use_cac_link: Use a PIV/CAC instead
- verifying: Verifying…
welcome: We verify your identity to make sure you are you—not someone pretending
to be you. Verifying your identity lets you access services that handle sensitive
information.
diff --git a/config/locales/doc_auth/es.yml b/config/locales/doc_auth/es.yml
index b6066b20830..b67e97cc532 100644
--- a/config/locales/doc_auth/es.yml
+++ b/config/locales/doc_auth/es.yml
@@ -151,7 +151,6 @@ es:
su identidad.
use_cac: "¿Tiene un documento de identidad de empleado del gobierno?"
use_cac_link: Utilice un PIV/CAC en su lugar
- verifying: Verificando…
welcome: Verificamos su identidad para asegurarnos de que usted es usted, y
no alguien que pretende ser usted. Verificar su identidad le permite acceder
a servicios que manejan información confidencial.
diff --git a/config/locales/doc_auth/fr.yml b/config/locales/doc_auth/fr.yml
index fc3d6dad4a6..9481b056459 100644
--- a/config/locales/doc_auth/fr.yml
+++ b/config/locales/doc_auth/fr.yml
@@ -164,7 +164,6 @@ fr:
upload_no_image_storage: Nous ne stockons pas les images que vous téléchargez.
use_cac: Avez-vous une carte d'identité d'employé du gouvernement?
use_cac_link: Utilisez plutôt une PIV/CAC
- verifying: Vérification…
welcome: Nous vérifions votre identité pour nous assurer que vous êtes bien,
et non quelqu'un prétendant être vous. La vérification de votre identité vous
permet d'accéder à des services traitant des informations sensibles.
diff --git a/spec/features/accessibility/idv_pages_spec.rb b/spec/features/accessibility/idv_pages_spec.rb
index bf469f8924d..92294958b14 100644
--- a/spec/features/accessibility/idv_pages_spec.rb
+++ b/spec/features/accessibility/idv_pages_spec.rb
@@ -43,7 +43,7 @@
complete_all_doc_auth_steps
click_continue
- expect(page).to have_current_path(idv_review_path, wait: 5)
+ expect(current_path).to eq idv_review_path
expect(page).to be_accessible.according_to :section508, :"best-practice"
expect(page).to label_required_fields
expect(page).to be_uniquely_titled
diff --git a/spec/features/idv/steps/phone_step_spec.rb b/spec/features/idv/steps/phone_step_spec.rb
index 4798f223d09..74b2051aa78 100644
--- a/spec/features/idv/steps/phone_step_spec.rb
+++ b/spec/features/idv/steps/phone_step_spec.rb
@@ -15,17 +15,14 @@
expect(page).to have_current_path(idv_otp_delivery_method_path)
end
- it 'redirects to the confirmation step when the phone matches the 2fa phone number', js: true do
+ it 'redirects to the confirmation step when the phone matches the 2fa phone number' do
user = user_with_2fa
start_idv_from_sp
complete_idv_steps_before_phone_step(user)
fill_out_phone_form_ok(MfaContext.new(user).phone_configurations.first.phone)
-
- expect(page).to have_selector('.spinner-button')
click_idv_continue
- expect(page).to have_selector('.spinner-button--spinner-active')
- expect(page).to have_content(t('idv.titles.session.review'), wait: 1)
+ expect(page).to have_content(t('idv.titles.session.review'))
expect(page).to have_current_path(idv_review_path)
end
diff --git a/spec/javascripts/packs/form-steps-wait-spec.js b/spec/javascripts/packs/form-steps-wait-spec.js
deleted file mode 100644
index a543d6f6736..00000000000
--- a/spec/javascripts/packs/form-steps-wait-spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import { fireEvent } from '@testing-library/dom';
-import { useSandbox } from '../support/sinon';
-import useDefineProperty from '../support/define-property';
-import { FormStepsWait } from '../../../app/javascript/packs/form-steps-wait';
-
-describe('FormStepsWait', () => {
- const sandbox = useSandbox({ useFakeTimers: true });
- const defineProperty = useDefineProperty();
-
- function createForm({ action, method, options }) {
- document.body.innerHTML = `
-
- `;
-
- const form = document.body.firstElementChild;
- Object.assign(form.dataset, options);
- return form;
- }
-
- it('submits form via fetch', () => {
- const action = new URL('/', window.location).toString();
- const method = 'post';
- const form = createForm({ action, method });
- new FormStepsWait(form).bind();
- const mock = sandbox
- .mock(window)
- .expects('fetch')
- .once()
- .withArgs(
- action,
- sandbox.match({
- method,
- body: sandbox.match((formData) => /** @type {FormData} */ (formData).has('foo')),
- }),
- )
- .resolves({ ok: true });
-
- const didNativeSubmit = fireEvent.submit(form);
-
- expect(didNativeSubmit).to.be.false();
- mock.verify();
- });
-
- it('reloads on failed submit', (done) => {
- const action = new URL('/', window.location).toString();
- const method = 'post';
- const form = createForm({ action, method });
- new FormStepsWait(form).bind();
- sandbox
- .stub(window, 'fetch')
- .withArgs(action, sandbox.match({ method }))
- .resolves({ ok: false });
- defineProperty(window, 'location', { value: { reload: done } });
-
- fireEvent.submit(form);
- });
-
- it('navigates on redirected response', (done) => {
- const action = new URL('/', window.location).toString();
- const redirect = new URL('/next', window.location).toString();
- const method = 'post';
- const form = createForm({ action, method });
- new FormStepsWait(form).bind();
- sandbox
- .stub(window, 'fetch')
- .withArgs(action, sandbox.match({ method }))
- .resolves({ ok: true, redirected: true, url: redirect });
- defineProperty(window, 'location', {
- value: {
- set href(url) {
- expect(url).to.equal(redirect);
- done();
- },
- },
- });
-
- fireEvent.submit(form);
- });
-
- it('polls for completion', (done) => {
- const action = new URL('/', window.location).toString();
- const pollIntervalMs = 1000;
- const waitStepPath = '/wait';
- const redirect = new URL('/next', window.location).toString();
- const method = 'post';
- const form = createForm({ action, method, options: { waitStepPath, pollIntervalMs } });
- new FormStepsWait(form).bind();
- sandbox
- .stub(window, 'fetch')
- .withArgs(action, sandbox.match({ method }))
- .resolves({
- ok: true,
- redirected: true,
- url: new URL(waitStepPath, window.location).toString(),
- })
- .withArgs(waitStepPath, sandbox.match({ method: 'HEAD' }))
- .resolves({ ok: true, redirected: true, url: redirect });
-
- defineProperty(window, 'location', {
- value: {
- set href(url) {
- expect(url).to.equal(redirect);
- done();
- },
- },
- });
-
- fireEvent.submit(form);
- sandbox.stub(global, 'setTimeout').callsFake((callback, timeout) => {
- expect(timeout).to.equal(pollIntervalMs);
- callback();
- });
- });
-});
diff --git a/spec/javascripts/packs/spinner-button-spec.js b/spec/javascripts/packs/spinner-button-spec.js
index 6044b037799..d6def6255be 100644
--- a/spec/javascripts/packs/spinner-button-spec.js
+++ b/spec/javascripts/packs/spinner-button-spec.js
@@ -1,105 +1,34 @@
-import sinon from 'sinon';
import userEvent from '@testing-library/user-event';
-import { getByRole } from '@testing-library/dom';
import { SpinnerButton } from '../../../app/javascript/packs/spinner-button';
describe('SpinnerButton', () => {
- let clock;
-
- const longWaitDurationMs = 1000;
-
- function createWrapper({ actionMessage, tagName = 'a' } = {}) {
- document.body.innerHTML = `
-
+ `;
+ wrapper = wrapper.firstElementChild;
});
it('shows spinner on click', () => {
- const wrapper = createWrapper();
- const spinnerButton = new SpinnerButton(wrapper);
- spinnerButton.bind();
- const { button } = spinnerButton.elements;
+ const { button, spinner } = new SpinnerButton(wrapper).elements;
userEvent.click(button);
expect(wrapper.classList.contains('spinner-button--spinner-active')).to.be.true();
- });
-
- it('disables button without preventing form handlers', () => {
- const wrapper = createWrapper({ tagName: 'button' });
- let submitted = false;
- const form = document.createElement('form');
- form.action = '#';
- form.addEventListener('submit', (event) => {
- submitted = true;
- event.preventDefault();
- });
- document.body.appendChild(form);
- form.appendChild(wrapper);
- const spinnerButton = new SpinnerButton(wrapper);
- spinnerButton.bind();
- const { button } = spinnerButton.elements;
-
- userEvent.type(button, '{enter}');
- clock.tick(0);
-
- expect(submitted).to.be.true();
- expect(button.hasAttribute('disabled')).to.be.true();
- });
-
- it('announces action message', () => {
- const wrapper = createWrapper({ actionMessage: 'Verifying...' });
- const status = getByRole(wrapper, 'status');
- const spinnerButton = new SpinnerButton(wrapper);
- spinnerButton.bind();
- const { button } = spinnerButton.elements;
-
- expect(status.textContent).to.be.empty();
-
- userEvent.click(button);
-
- expect(status.textContent).to.equal('Verifying...');
- expect(status.classList.contains('usa-sr-only')).to.be.true();
- });
-
- it('shows action message visually after long delay', () => {
- const wrapper = createWrapper({ actionMessage: 'Verifying...' });
- const status = getByRole(wrapper, 'status');
- const spinnerButton = new SpinnerButton(wrapper);
- spinnerButton.bind();
- const { button } = spinnerButton.elements;
-
- expect(status.textContent).to.be.empty();
-
- userEvent.click(button);
- clock.tick(longWaitDurationMs - 1);
- expect(status.classList.contains('usa-sr-only')).to.be.true();
- clock.tick(1);
- expect(status.classList.contains('usa-sr-only')).to.be.false();
+ expect(spinner.classList.contains('usa-sr-only')).to.be.false();
});
});
diff --git a/spec/javascripts/support/define-property.js b/spec/javascripts/support/define-property.js
deleted file mode 100644
index 0b6de51756c..00000000000
--- a/spec/javascripts/support/define-property.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * A proxy to Object.defineProperty to use in redefining an existing object and reverting that
- * definition to its original value after the test has completed.
- *
- * @return {ObjectConstructor['defineProperty']}
- */
-export default function useDefineProperty() {
- let redefined = [];
-
- afterEach(() => {
- redefined.forEach(([object, property, originalDescriptor]) => {
- delete object[property];
- if (originalDescriptor !== undefined) {
- Object.defineProperty(object, property, originalDescriptor);
- }
- });
-
- redefined = [];
- });
-
- return function defineProperty(object, property, descriptor) {
- const originalDescriptor = Object.getOwnPropertyDescriptor(object, property);
- redefined.push([object, property, originalDescriptor]);
- Object.defineProperty(object, property, descriptor);
- };
-}
diff --git a/spec/javascripts/support/sinon.js b/spec/javascripts/support/sinon.js
index 68977531360..d6b350e59f8 100644
--- a/spec/javascripts/support/sinon.js
+++ b/spec/javascripts/support/sinon.js
@@ -3,27 +3,12 @@ import sinon from 'sinon';
/**
* Returns an instance of a Sinon sandbox, and automatically restores all stubbed methods after each
* test case.
- *
- * @param {sinon.SinonSandboxConfig=} config
*/
-export function useSandbox(config) {
- const { useFakeTimers = false, ...remainingConfig } = config ?? {};
- const sandbox = sinon.createSandbox(remainingConfig);
-
- beforeEach(() => {
- // useFakeTimers overrides global timer functions as soon as sandbox is created, thus leaking
- // across tests. Instead, wait until tests start to initialize.
- if (useFakeTimers) {
- sandbox.useFakeTimers();
- }
- });
+export function useSandbox() {
+ const sandbox = sinon.createSandbox();
afterEach(() => {
sandbox.restore();
-
- if (useFakeTimers) {
- sandbox.clock.restore();
- }
});
return sandbox;
diff --git a/spec/support/features/doc_auth_helper.rb b/spec/support/features/doc_auth_helper.rb
index 026b0f9e3d3..01180d88e0c 100644
--- a/spec/support/features/doc_auth_helper.rb
+++ b/spec/support/features/doc_auth_helper.rb
@@ -129,9 +129,6 @@ def complete_all_doc_auth_steps(expect_accessible: false)
complete_doc_auth_steps_before_verify_step(expect_accessible: expect_accessible)
expect(page).to be_accessible.according_to :section508, :"best-practice" if expect_accessible
click_idv_continue
- # In JavaScript contexts, a spinner is shown while verification is in-progress. The only
- # reliable measure of completion is that the page eventually navigates away.
- expect(page).to_not have_current_path(idv_doc_auth_verify_step, wait: 10)
end
def mock_doc_auth_no_name_pii(method)
diff --git a/spec/views/shared/_spinner-button.html.erb_spec.rb b/spec/views/shared/_spinner-button.html.erb_spec.rb
deleted file mode 100644
index 2d808c9c5c7..00000000000
--- a/spec/views/shared/_spinner-button.html.erb_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'rails_helper'
-
-describe 'shared/_spinner-button.html.erb' do
- it 'raises an error if no block given' do
- expect { render 'shared/spinner-button' }.to raise_error('no block content given')
- end
-
- describe 'classes' do
- let(:classes) { nil }
-
- before do
- render('shared/spinner-button', class: classes) { tag.button }
- end
-
- context 'without custom classes given' do
- let(:classes) { nil }
-
- it 'renders with default classes' do
- expect(rendered).to have_selector('.spinner-button')
- end
- end
-
- context 'with custom classes' do
- let(:classes) { 'my-custom-class' }
-
- it 'renders with additional custom classes' do
- expect(rendered).to have_selector('.spinner-button.my-custom-class')
- end
- end
- end
-
- describe 'action message' do
- let(:action_message) { nil }
-
- before do
- render('shared/spinner-button', action_message: action_message) { tag.button }
- end
-
- context 'without action message' do
- let(:action_message) { nil }
-
- it 'omits action message element' do
- expect(rendered).to_not have_selector('.spinner-button__action-message')
- end
- end
-
- context 'with action message' do
- let(:action_message) { 'Verifying...' }
-
- it 'renders action message element' do
- expect(rendered).to have_selector(
- '.spinner-button__action-message[data-message="Verifying..."]',
- text: '',
- )
- end
- end
- end
-end
diff --git a/tsconfig.json b/tsconfig.json
index 4eef56be3f8..7287f8b0613 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,7 +14,6 @@
"include": [
"app/javascript/packages",
"app/javascript/packs/document-capture.jsx",
- "app/javascript/packs/form-steps-wait.js",
"app/javascript/packs/form-validation.js",
"app/javascript/packs/intl-tel-input.js",
"app/javascript/packs/spinner-button.js",