Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions src/journal/tests/test_journal_frontend.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import os
import shutil

from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils import timezone
Expand All @@ -8,6 +13,7 @@
from press.models import Press
from utils.testing import helpers
from utils import setting_handler
from core import files as core_files
from core import models as core_models
from submission import models as submission_models

Expand Down Expand Up @@ -270,3 +276,85 @@ def test_search_excludes_artucle(self):
response,
self.article_title,
)


class TestTableModalKeyboardDismiss(TestCase):
"""
Regression tests for #5387: the enlarged-table modal must be keyboard
dismissable. Without tabindex="-1" on the modal, Bootstrap cannot move
focus into it, so keyboard users can never reach the close button.
"""

@classmethod
def setUpTestData(cls):
cls.press = helpers.create_press()
cls.journal_domain = "tablemodal.janeway.systems"
cls.journal = make_test_journal(
code="tablemodal",
domain=cls.journal_domain,
)
setting_handler.save_setting(
"general",
"journal_theme",
cls.journal,
"clean",
)
helpers.create_roles(["Author"])
cls.owner = helpers.create_user(
"table_modal_owner@janeway.systems",
["author"],
cls.journal,
)
cls.article = helpers.create_article(
journal=cls.journal,
title="An article with a table",
stage=submission_models.STAGE_PUBLISHED,
date_published=timezone.now(),
owner=cls.owner,
)
galley_html = (
'<div class="table-expansion" id="T1">'
"<table><caption>Table 1</caption>"
"<tr><td>Cell</td></tr></table>"
"</div>"
)
uploaded_file = SimpleUploadedFile(
"tables.html",
galley_html.encode("utf-8"),
content_type="text/html",
)
file_obj = core_files.save_file_to_article(
uploaded_file,
cls.article,
cls.owner,
label="HTML",
is_galley=True,
)
cls.galley = helpers.create_galley(
cls.article,
file_obj=file_obj,
label="HTML",
type="html",
)
cls.addClassCleanup(
shutil.rmtree,
os.path.join(settings.BASE_DIR, "files", "articles", str(cls.article.pk)),
ignore_errors=True,
)

def test_table_modal_is_focusable_for_keyboard_dismissal(self):
response = self.client.get(
reverse(
"article_view",
kwargs={
"identifier_type": "id",
"identifier": self.article.pk,
},
),
SERVER_NAME=self.journal_domain,
)
self.assertEqual(response.status_code, 200)
self.assertContains(
response,
'id="table-T1" tabindex="-1"',
)
17 changes: 14 additions & 3 deletions src/static/common/js/reversable-links.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,26 @@ function drawUserAttention(targetElement){
element.tabIndex = "-1"
element.focus();

const restoreTabIndex = () => {
if (oldTabIndex === null) {
element.removeAttribute('tabIndex');
} else {
element.tabIndex = oldTabIndex;
}
};

const timeout = setTimeout(() => {
element.classList.remove('draw-attention');
if (element.classList.length === 0) {
element.removeAttribute('class');
}
if (oldTabIndex === null) {
element.removeAttribute('tabIndex');
if (document.activeElement === element) {
// Removing tabindex while the element is focused sends focus
// back to <body>, so tabbing would restart from the top of
// the page. Wait until focus moves on before restoring.
element.addEventListener('blur', restoreTabIndex, { once: true });
} else {
element.tabIndex = oldTabIndex;
restoreTabIndex();
}
attentionTimeouts.delete(element);
}, 2000);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ul class="flex direction-column gap-0-5">
<ul class="article-authors-full flex direction-column gap-0-5">
{% for author in article.frozen_authors.all %}
<li>{% include "common/elements/journal/article_author_display.html" %}</li>
{% endfor %}
Expand Down
4 changes: 2 additions & 2 deletions src/themes/clean/templates/elements/journal/table_modal.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="modal " id="table-{{ tableid }}">
<div class="modal-dialog modal-xl">
<div class="modal " id="table-{{ tableid }}" tabindex="-1" role="dialog" aria-labelledby="copy-of-{{ tableid }}-label">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">

<!-- Modal body -->
Expand Down
Loading