mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-26 15:48:28 -04:00
Merge branch 'main' of https://github.com/GSA/notifications-admin into 2515-remove-autofocus-js
This commit is contained in:
@@ -20,14 +20,14 @@ def test_owasp_useful_headers_set(
|
||||
assert search(
|
||||
r"script-src 'self' static\.example\.com 'unsafe-eval' https:\/\/js-agent\.new"
|
||||
r"relic\.com https:\/\/gov-bam\.nr-data\.net https:\/\/www\.googletagmanager\."
|
||||
r"com https:\/\/www\.google-analytics\."
|
||||
r"com https:\/\/dap\.digitalgov\."
|
||||
r"gov 'nonce-.*';",
|
||||
r"com https:\/\/www\.google-analytics\.com https:\/\/dap\.digitalgov\.gov "
|
||||
r"https:\/\/cdn\.socket\.io",
|
||||
csp,
|
||||
)
|
||||
assert search(r"'nonce-[^']+';", csp)
|
||||
assert search(
|
||||
r"connect-src 'self' https:\/\/gov-bam.nr-data\.net https:\/\/www\.google-analytics\."
|
||||
r"com;",
|
||||
r"connect-src 'self' https:\/\/gov-bam\.nr-data\.net https:\/\/www\.google-analytics\."
|
||||
r"com http:\/\/localhost:6011 ws:\/\/localhost:6011;",
|
||||
csp,
|
||||
)
|
||||
assert search(r"style-src 'self' static\.example\.com 'nonce-.*';", csp)
|
||||
|
||||
@@ -16,16 +16,22 @@ def test_non_logged_in_user_can_see_homepage(
|
||||
client_request.logout()
|
||||
page = client_request.get("main.index", _test_page_title=False)
|
||||
|
||||
assert page.h1.text.strip() == (
|
||||
"Reach people where they are with government-powered text messages"
|
||||
)
|
||||
heading = page.h1.text.strip()
|
||||
assert heading in [
|
||||
"Reach people where they are with government-powered text messages",
|
||||
"There's currently a technical issue.",
|
||||
]
|
||||
|
||||
# Assert the entire HTML of the button to include the image
|
||||
button = page.select_one(
|
||||
"a.usa-button.login-button.login-button--primary.margin-right-2"
|
||||
)
|
||||
assert "Sign in with" in button.text.strip() # Assert button text
|
||||
assert button.find("img")["alt"] == "Login.gov logo" # Assert image presence
|
||||
|
||||
if heading == "There's currently a technical issue.":
|
||||
assert button is None
|
||||
else:
|
||||
assert button is not None
|
||||
assert "Sign in with" in button.text.strip()
|
||||
assert button.find("img")["alt"] == "Login.gov logo"
|
||||
|
||||
assert page.select_one("meta[name=description]") is not None
|
||||
assert page.select_one("#whos-using-notify a") is None
|
||||
|
||||
@@ -945,7 +945,7 @@ def test_load_edit_template_with_copy_of_template(
|
||||
assert page.select_one("form")["method"] == "post"
|
||||
|
||||
assert page.select_one("input")["value"] == (expected_name)
|
||||
assert page.select_one("textarea").text == ("\r\nYour ((thing)) is due soon")
|
||||
assert page.select_one("textarea").text.strip() == ("Your ((thing)) is due soon")
|
||||
mock_get_service_email_template.assert_called_once_with(
|
||||
SERVICE_TWO_ID,
|
||||
TEMPLATE_ONE_ID,
|
||||
|
||||
@@ -164,12 +164,12 @@ def test_should_show_empty_text_box(
|
||||
)
|
||||
|
||||
textbox = page.select_one(
|
||||
"[data-module=autofocus][data-force-focus=True] .usa-input"
|
||||
".usa-input"
|
||||
)
|
||||
assert "value" not in textbox
|
||||
assert textbox["name"] == "placeholder_value"
|
||||
assert textbox["class"] == [
|
||||
"usa-input",
|
||||
"form-control", "usa-input",
|
||||
]
|
||||
# data-module=autofocus is set on a containing element so it
|
||||
# shouldn’t also be set on the textbox itself
|
||||
|
||||
@@ -18,6 +18,12 @@ Object.defineProperty(HTMLElement.prototype, 'clientWidth', {
|
||||
});
|
||||
|
||||
// beforeAll hook to set up the DOM and load D3.js script
|
||||
beforeAll(() => {
|
||||
jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(() => ({
|
||||
resolvedOptions: () => ({ timeZone: 'UTC' })
|
||||
}));
|
||||
});
|
||||
|
||||
beforeAll(done => {
|
||||
// Set up the DOM with the D3 script included
|
||||
document.body.innerHTML = `
|
||||
|
||||
26
tests/javascripts/fileUpload.domLoad.test.js
Normal file
26
tests/javascripts/fileUpload.domLoad.test.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// This will use the real function and listener
|
||||
const {
|
||||
initUploadStatusAnnouncer
|
||||
} = require('../../app/assets/javascripts/fileUpload.js');
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
test('writes upload message to the live region on DOMContentLoaded', () => {
|
||||
// Setup the DOM
|
||||
document.body.innerHTML = `
|
||||
<div id="upload-status-live" aria-live="assertive" role="status" class="usa-sr-only">Old message</div>
|
||||
<span id="upload-success" class="usa-sr-only">File upload successful</span>
|
||||
`;
|
||||
|
||||
// Register the listener (same as page load does)
|
||||
initUploadStatusAnnouncer();
|
||||
|
||||
// Simulate the page load event
|
||||
document.dispatchEvent(new Event('DOMContentLoaded'));
|
||||
|
||||
// Live region will be cleared first, then updated
|
||||
jest.advanceTimersByTime(300);
|
||||
|
||||
const srRegion = document.getElementById('upload-status-live');
|
||||
expect(srRegion.textContent).toBe('File upload successful\u00A0');
|
||||
});
|
||||
@@ -1,13 +1,12 @@
|
||||
const helpers = require('./support/helpers.js');
|
||||
|
||||
beforeAll(() => {
|
||||
require('../../app/assets/javascripts/fileUpload.js');
|
||||
});
|
||||
const { announceUploadStatusFromElement } = require('../../app/assets/javascripts/fileUpload.js');
|
||||
|
||||
afterAll(() => {
|
||||
require('./support/teardown.js');
|
||||
});
|
||||
|
||||
|
||||
describe('File upload', () => {
|
||||
|
||||
let form;
|
||||
@@ -72,12 +71,116 @@ describe('File upload', () => {
|
||||
|
||||
});
|
||||
|
||||
test("It should add a link to cancel the upload by reloading the page", () => {
|
||||
|
||||
expect(form.querySelector("a[href='']")).not.toBeNull();
|
||||
|
||||
test("It should display a disabled Uploading button", () => {
|
||||
const uploadingButton = form.querySelector("button.uploading-button");
|
||||
expect(uploadingButton).not.toBeNull();
|
||||
expect(uploadingButton.textContent).toMatch(/Uploading/);
|
||||
expect(uploadingButton.getAttribute('aria-disabled')).toBe("true");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('File upload "upload-trigger" click handler', () => {
|
||||
let form;
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = `
|
||||
<form method="post" enctype="multipart/form-data" data-module="file-upload">
|
||||
<button type="button" data-module="upload-trigger" data-file-input-id="test-file-input">Upload your file</button>
|
||||
<input type="file" id="test-file-input" style="display:none;">
|
||||
</form>
|
||||
`;
|
||||
|
||||
form = document.querySelector('form');
|
||||
|
||||
// Register the module
|
||||
window.GOVUK.modules.start();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
test('clicking upload trigger simulates file input click', () => {
|
||||
const uploadButton = form.querySelector('[data-module="upload-trigger"]');
|
||||
const fileInput = document.getElementById('test-file-input');
|
||||
|
||||
// Spy on fileInput.click
|
||||
const clickSpy = jest.spyOn(fileInput, 'click').mockImplementation(() => {});
|
||||
|
||||
// Trigger the click
|
||||
helpers.triggerEvent(uploadButton, 'click');
|
||||
|
||||
expect(clickSpy).toHaveBeenCalled();
|
||||
|
||||
clickSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('announceUploadStatusFromElement', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
document.body.innerHTML = `
|
||||
<div id="upload-status-live" aria-live="assertive" role="status" class="usa-sr-only"></div>
|
||||
`;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
test('announces error message from #upload-error', () => {
|
||||
document.body.innerHTML += `
|
||||
<span id="upload-error" class="usa-sr-only">File upload failed</span>
|
||||
`;
|
||||
|
||||
const srRegion = document.getElementById('upload-status-live');
|
||||
|
||||
// Call the function
|
||||
announceUploadStatusFromElement();
|
||||
|
||||
// Confirm it clears first
|
||||
expect(srRegion.textContent).toBe('');
|
||||
|
||||
// Fast-forward the timer
|
||||
jest.advanceTimersByTime(300);
|
||||
|
||||
// Confirm it updates after delay
|
||||
expect(srRegion.textContent).toBe('File upload failed\u00A0');
|
||||
});
|
||||
|
||||
test('announces success message from #upload-success if no error is present', () => {
|
||||
document.body.innerHTML += `
|
||||
<span id="upload-success" class="usa-sr-only">File upload successful</span>
|
||||
`;
|
||||
|
||||
const srRegion = document.getElementById('upload-status-live');
|
||||
|
||||
announceUploadStatusFromElement();
|
||||
|
||||
expect(srRegion.textContent).toBe('');
|
||||
|
||||
jest.advanceTimersByTime(301);
|
||||
|
||||
expect(srRegion.textContent).toBe('File upload successful\u00A0');
|
||||
});
|
||||
|
||||
test('does nothing if neither success nor error is present', () => {
|
||||
const srRegion = document.getElementById('upload-status-live');
|
||||
|
||||
srRegion.textContent = 'Old message';
|
||||
|
||||
announceUploadStatusFromElement();
|
||||
|
||||
// Should not clear or update if no message element is found
|
||||
expect(srRegion.textContent).toBe('Old message');
|
||||
|
||||
jest.advanceTimersByTime(300);
|
||||
|
||||
// Still unchanged
|
||||
expect(srRegion.textContent).toBe('Old message');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -347,24 +347,4 @@ describe('FullscreenTable', () => {
|
||||
|
||||
});
|
||||
|
||||
describe("when the table is focused", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
// start module
|
||||
window.GOVUK.modules.start();
|
||||
|
||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
||||
tableFrame.focus();
|
||||
|
||||
});
|
||||
|
||||
test("it should make the parent frame a focus style", () => {
|
||||
|
||||
expect(container.classList.contains('js-focus-style')).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user