-
Notifications
You must be signed in to change notification settings - Fork 9
Accessibility improvements: add missing labels for input fields #2970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8368663
Update locator for bulk edit row to accommodate row with multiple inp…
labkey-susanh 08d747b
Update EntityBulkInsertDialog and EntityBulkUpdateDialog amount/units…
cnathe 6dbfb9e
EntityTypeDesigner update to helpTarget() locator
cnathe 01eeeeb
locator fix
cnathe 830bb41
Merge branch 'develop' into fb_inputLabels
cnathe b39bef5
EntityBulkUpdateDialog getFieldNames() to account for the hide-label …
cnathe 83fcebe
mising newlines
labkey-susanh 3fd15fb
Merge remote-tracking branch 'origin/develop' into fb_inputLabels
labkey-susanh 65a7347
Renamings
labkey-susanh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
217 changes: 217 additions & 0 deletions
217
src/org/labkey/test/components/ui/entities/EntityBulkDialog.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| package org.labkey.test.components.ui.entities; | ||
|
|
||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.labkey.api.util.Pair; | ||
| import org.labkey.test.Locator; | ||
| import org.labkey.test.components.bootstrap.ModalDialog; | ||
| import org.labkey.test.components.html.Checkbox; | ||
| import org.labkey.test.components.html.Input; | ||
| import org.labkey.test.components.react.FilteringReactSelect; | ||
| import org.labkey.test.components.react.ReactDateTimePicker; | ||
| import org.labkey.test.components.react.ReactSelect; | ||
| import org.labkey.test.components.react.ToggleButton; | ||
| import org.labkey.test.components.ui.files.FileAttachmentContainer; | ||
| import org.labkey.test.params.FieldKey; | ||
| import org.openqa.selenium.WebElement; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| import static org.labkey.test.WebDriverWrapper.WAIT_FOR_JAVASCRIPT; | ||
|
|
||
| /** | ||
| * Abstract base for {@link EntityBulkInsertDialog} and {@link EntityBulkUpdateDialog}. | ||
| */ | ||
| public abstract class EntityBulkDialog extends ModalDialog | ||
| { | ||
| protected int _changeCounter = 0; | ||
|
|
||
| protected EntityBulkDialog(ModalDialogFinder finder) | ||
| { | ||
| super(finder); | ||
| } | ||
|
|
||
| /** | ||
| * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) | ||
| * @return current value of the specified field | ||
| */ | ||
| public String getTextArea(CharSequence fieldIdentifier) | ||
| { | ||
| return elementCache().textArea(fieldIdentifier).get(); | ||
| } | ||
|
|
||
| /** | ||
| * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) | ||
| * @return current value of the specified field | ||
| */ | ||
| public String getNumericField(CharSequence fieldIdentifier) | ||
| { | ||
| return elementCache().textInput(fieldIdentifier).get(); | ||
| } | ||
|
|
||
| /** | ||
| * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) | ||
| * @return current value of the specified field | ||
| */ | ||
| public boolean getBooleanField(CharSequence fieldIdentifier) | ||
| { | ||
| return elementCache().checkbox(fieldIdentifier).get(); | ||
| } | ||
|
|
||
| public String getFieldValue(WebElement input) | ||
| { | ||
| String value = input.getText(); | ||
| if (StringUtils.isEmpty(value)) | ||
| value = input.getAttribute("value"); | ||
| if (StringUtils.isEmpty(value)) | ||
| value = input.getAttribute("placeholder"); | ||
| if (StringUtils.isEmpty(value) && "checkbox".equals(input.getAttribute("type"))) | ||
| value = input.getAttribute("title"); | ||
| return value; | ||
| } | ||
|
|
||
| protected String getValueForReactSelect(ReactSelect reactSelect) | ||
| { | ||
| if (!reactSelect.getSelections().isEmpty()) | ||
| { | ||
| return reactSelect.getSelections().get(0); | ||
| } | ||
| else | ||
| { | ||
| return ""; | ||
| } | ||
| } | ||
|
|
||
| private WebElement getAmountUnitsRow() | ||
| { | ||
| String fieldLabel = "Amount and Units"; | ||
| return elementCache().formRowByControlLabel(fieldLabel); | ||
| } | ||
|
|
||
| public Pair<String, String> getAmountAndUnitsReadOnlyValues() | ||
| { | ||
| String amountVal = getFieldValue(getAmountInput()); | ||
| String unitVal = Locator.tagWithClass("div", "select-input__value-container").withoutAttribute("type", "hidden").findElement(getAmountUnitsRow()).getText(); | ||
| return new Pair<>(amountVal, unitVal); | ||
| } | ||
|
|
||
| public Pair<String, String> getAmountAndUnitsInputValues() | ||
| { | ||
| enableAmountAndUnits(); | ||
| String amountVal = getWrapper().getFormElement(getAmountInput()); | ||
| String unitVal = getValueForReactSelect(getAmountUnitSelect()); | ||
| return new Pair<>(amountVal, unitVal); | ||
| } | ||
|
|
||
| public void enableAmountAndUnits() | ||
| { | ||
| ToggleButton toggle = new ToggleButton.ToggleButtonFinder(getDriver()).findOrNull(getAmountUnitsRow()); | ||
| if (toggle != null && !toggle.isOn()) | ||
| { | ||
| toggle.set(true); | ||
| _changeCounter++; | ||
| } | ||
| } | ||
|
|
||
| public void disableAmountAndUnits() | ||
| { | ||
| ToggleButton toggle = new ToggleButton.ToggleButtonFinder(getDriver()).findOrNull(getAmountUnitsRow()); | ||
| if (toggle != null && toggle.isOn()) | ||
| { | ||
| toggle.set(false); | ||
| _changeCounter--; | ||
| } | ||
| } | ||
|
|
||
| private WebElement getAmountInput() | ||
| { | ||
| return elementCache().amountInputLoc.findElement(getAmountUnitsRow()); | ||
| } | ||
|
|
||
| public ReactSelect getAmountUnitSelect() | ||
| { | ||
| enableAmountAndUnits(); | ||
| return new ReactSelect(getAmountUnitsRow(), getDriver()); | ||
| } | ||
|
|
||
| public void setAmountUnit(String amount, String unit) | ||
| { | ||
| enableAmountAndUnits(); | ||
|
|
||
| if (amount != null) | ||
| getWrapper().setFormElement(getAmountInput(), amount); | ||
| if (unit != null) | ||
| { | ||
| ReactSelect reactSelect = getAmountUnitSelect(); | ||
| if (!unit.isEmpty()) | ||
| reactSelect.select(unit); | ||
| else | ||
| reactSelect.clearSelection(); | ||
| } | ||
|
|
||
| if (amount != null && unit != null) | ||
| _changeCounter++; | ||
|
labkey-susanh marked this conversation as resolved.
|
||
| } | ||
|
|
||
| @Override | ||
| protected abstract ElementCache newElementCache(); | ||
|
|
||
| @Override | ||
| protected ElementCache elementCache() | ||
| { | ||
| return (ElementCache) super.elementCache(); | ||
| } | ||
|
|
||
| protected abstract class ElementCache extends ModalDialog.ElementCache | ||
| { | ||
| protected final Locator textInputLoc = Locator.tagWithAttribute("input", "type", "text"); | ||
| protected final Locator checkboxLoc = Locator.tagWithAttribute("input", "type", "checkbox"); | ||
| protected final Locator.XPathLocator amountInputLoc = Locator.tag("input").withAttribute("aria-label", "Amount"); | ||
|
|
||
| protected final Map<String, WebElement> _rows = new HashMap<>(); | ||
|
|
||
| /** | ||
| * Returns the form row div that contains the controls for the given field. | ||
| */ | ||
| public abstract WebElement formRow(CharSequence fieldIdentifier); | ||
|
|
||
| // For composite fields (e.g. StoredAmount + Units) that render a <div> label instead of <label for="...">, | ||
| private WebElement formRowByControlLabel(String fieldLabel) | ||
| { | ||
| return _rows.computeIfAbsent(fieldLabel, k -> | ||
| Locator.tagWithClass("div", "row") | ||
| .withChild(Locator.tagWithClass("div", "control-label").withText(fieldLabel)) | ||
| .waitForElement(this, WAIT_FOR_JAVASCRIPT)); | ||
| } | ||
|
|
||
| public FilteringReactSelect selectionField(CharSequence fieldIdentifier) | ||
| { | ||
| return new FilteringReactSelect(formRow(fieldIdentifier), getDriver()); | ||
| } | ||
|
|
||
| public Checkbox checkbox(CharSequence fieldIdentifier) | ||
| { | ||
| return new Checkbox(checkboxLoc.findElement(formRow(fieldIdentifier))); | ||
| } | ||
|
|
||
| public Input textInput(CharSequence fieldIdentifier) | ||
| { | ||
| return new Input(textInputLoc.findElement(formRow(fieldIdentifier)), getDriver()); | ||
| } | ||
|
|
||
| public Input textArea(CharSequence fieldIdentifier) | ||
| { | ||
| return new Input(Locator.tag("textarea").findElement(formRow(fieldIdentifier)), getDriver()); | ||
| } | ||
|
|
||
| public ReactDateTimePicker dateInput(CharSequence fieldIdentifier) | ||
| { | ||
| return new ReactDateTimePicker.ReactDateTimeInputFinder(getDriver()).find(formRow(fieldIdentifier)); | ||
| } | ||
|
|
||
| public FileAttachmentContainer fileUploadField(CharSequence fieldIdentifier) | ||
| { | ||
| return new FileAttachmentContainer(formRow(fieldIdentifier), getDriver()); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.