diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index d99f082a23e2dd62415abd148c0cd4b47edf7df1..3a7488a75aa21524980580d0d168f21610ba2d33 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -1880,13 +1880,9 @@ public class Conversation extends AbstractEntity if (min == null || max == null || min >= max) return null; final String value = firstValue(field); - final Float parsedValue; - if (value == null || value.equals("")) { - parsedValue = null; - } else { - parsedValue = parseFloat(value); - if (parsedValue == null || parsedValue < min || parsedValue > max) return null; - } + if (value == null || value.equals("")) return null; + final Float parsedValue = parseFloat(value); + if (parsedValue == null || parsedValue < min || parsedValue > max) return null; final List options = optionValues(field); if (options == null) return null; @@ -1902,7 +1898,7 @@ public class Conversation extends AbstractEntity } } if (step == null || (step > 0f && !landsOnStep(max, min, step))) return null; - return parsedValue == null || step == 0f || landsOnStep(parsedValue, min, step) ? step : null; + return step == 0f || landsOnStep(parsedValue, min, step) ? step : null; } static String formatSliderValue(final float value, final String datatype) { diff --git a/src/test/java/eu/siacs/conversations/entities/ConversationTest.java b/src/test/java/eu/siacs/conversations/entities/ConversationTest.java index 0ba456ab4e8f9ec47ef185f036fb3ac9c32f5f9f..c15a7a0ea190e2b42a669ed1d3b176d7db213a13 100644 --- a/src/test/java/eu/siacs/conversations/entities/ConversationTest.java +++ b/src/test/java/eu/siacs/conversations/entities/ConversationTest.java @@ -211,6 +211,15 @@ public class ConversationTest { Assert.assertEquals(Float.valueOf(0f), Conversation.steppedSliderStep(field)); } + @Test + public void steppedSliderStepRejectsMissingOrMalformedRangeBounds() { + final var missingMin = sliderField("xs:integer", null, "10", "5"); + final var malformedMax = sliderField("xs:integer", "0", "not-a-number", "5"); + + Assert.assertNull(Conversation.steppedSliderStep(missingMin)); + Assert.assertNull(Conversation.steppedSliderStep(malformedMax)); + } + @Test public void formatSliderValueDoesNotClampLargeIntegerDatatypesToInt() { Assert.assertEquals("3000000000", Conversation.formatSliderValue(3_000_000_000f, "xs:long")); @@ -268,23 +277,34 @@ public class ConversationTest { } @Test - public void sliderFieldViewHolderBindsEmptyValueWithoutCrashing() { - final var context = new ContextThemeWrapper( - RuntimeEnvironment.getApplication(), - com.google.android.material.R.style.Theme_MaterialComponents_DayNight_NoActionBar); + public void rangedNumericFieldWithBadBoundsFallsBackToTextInput() { final var session = withOccupantId.pagerAdapter.new CommandSession( "test", "node", mock(XmppConnectionService.class)); try { - final var binding = CommandSliderFieldBinding.inflate(LayoutInflater.from(context)); - final var holder = session.new SliderFieldViewHolder(binding); - final var field = sliderField("xs:integer", "0", "70", "", "0", "35", "70"); - final var item = session.new Field( - eu.siacs.conversations.xmpp.forms.Field.parse(field), - session.TYPE_SLIDER_FIELD); + session.responseElement = new Element("x", Namespace.DATA); + session.responseElement.setAttribute("type", "form"); + final var missingMin = sliderField("xs:integer", null, "10", "5"); + final var malformedMax = sliderField("xs:integer", "0", "not-a-number", "5"); - holder.bind(item); + Assert.assertEquals(session.TYPE_TEXT_FIELD, session.mkField(missingMin).viewType); + Assert.assertEquals(session.TYPE_TEXT_FIELD, session.mkField(malformedMax).viewType); + } finally { + session.loadingTimer.cancel(); + } + } + + @Test + public void rangedNumericFieldWithEmptyValueFallsBackToTextInput() { + final var session = withOccupantId.pagerAdapter.new CommandSession( + "test", "node", mock(XmppConnectionService.class)); + try { + session.responseElement = new Element("x", Namespace.DATA); + session.responseElement.setAttribute("type", "form"); + final var emptyValue = sliderField("xs:integer", "0", "70", "", "0", "35", "70"); + final var missingValue = sliderField("xs:integer", "0", "70", null, "0", "35", "70"); - Assert.assertEquals(0f, binding.slider.getValue(), 0.0001f); + Assert.assertEquals(session.TYPE_TEXT_FIELD, session.mkField(emptyValue).viewType); + Assert.assertEquals(session.TYPE_TEXT_FIELD, session.mkField(missingValue).viewType); } finally { session.loadingTimer.cancel(); }