diff options
Diffstat (limited to 'src/test/java/sevenUnitsGUI')
-rw-r--r-- | src/test/java/sevenUnitsGUI/PresenterTest.java | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/src/test/java/sevenUnitsGUI/PresenterTest.java b/src/test/java/sevenUnitsGUI/PresenterTest.java new file mode 100644 index 0000000..3364e83 --- /dev/null +++ b/src/test/java/sevenUnitsGUI/PresenterTest.java @@ -0,0 +1,356 @@ +/** + * Copyright (C) 2022 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package sevenUnitsGUI; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.RoundingMode; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import sevenUnits.unit.BaseDimension; +import sevenUnits.unit.BritishImperial; +import sevenUnits.unit.LinearUnitValue; +import sevenUnits.unit.Metric; +import sevenUnits.unit.Unit; +import sevenUnits.unit.UnitType; +import sevenUnits.utils.NameSymbol; +import sevenUnits.utils.Nameable; +import sevenUnits.utils.ObjectProduct; +import sevenUnits.utils.UncertainDouble; + +/** + * @author Adrien Hopkins + * + * @since 2022-02-10 + */ +public final class PresenterTest { + private static final Path TEST_SETTINGS = Path.of("src", "test", "resources", + "test-settings.txt"); + static final Set<Unit> testUnits = Set.of(Metric.METRE, Metric.KILOMETRE, + Metric.METRE_PER_SECOND, Metric.KILOMETRE_PER_HOUR); + + static final Set<ObjectProduct<BaseDimension>> testDimensions = Set + .of(Metric.Dimensions.LENGTH, Metric.Dimensions.VELOCITY); + + /** + * @return rounding rules used by {@link #testRoundingRules} + * @since 2022-04-16 + */ + private static final Stream<Function<UncertainDouble, String>> getRoundingRules() { + final var SCIENTIFIC_ROUNDING = StandardDisplayRules.uncertaintyBased(); + final var INTEGER_ROUNDING = StandardDisplayRules.fixedDecimals(0); + final var SIG_FIG_ROUNDING = StandardDisplayRules.fixedPrecision(4); + + return Stream.of(SCIENTIFIC_ROUNDING, INTEGER_ROUNDING, SIG_FIG_ROUNDING); + } + + private static final Set<String> names(Set<? extends Nameable> units) { + return units.stream().map(Nameable::getName).collect(Collectors.toSet()); + } + + /** + * Test method for {@link Presenter#convertExpressions} + * + * @since 2022-02-12 + */ + @Test + void testConvertExpressions() { + // setup + final ViewBot viewBot = new ViewBot(); + final Presenter presenter = new Presenter(viewBot); + + viewBot.setFromExpression("10000.0 m"); + viewBot.setToExpression("km"); + + // convert expression + presenter.convertExpressions(); + + // test result + final List<UnitConversionRecord> outputs = viewBot + .expressionConversionList(); + assertEquals("10000.0 m = 10.00000 km", + outputs.get(outputs.size() - 1).toString()); + } + + /** + * Tests that unit-conversion Views can correctly convert units + * + * @since 2022-02-12 + */ + @Test + void testConvertUnits() { + // setup + final ViewBot viewBot = new ViewBot(); + final Presenter presenter = new Presenter(viewBot); + + viewBot.setFromUnitNames(names(testUnits)); + viewBot.setToUnitNames(names(testUnits)); + viewBot.setFromSelection("metre"); + viewBot.setToSelection("kilometre"); + viewBot.setInputValue("10000.0"); + + // convert units + presenter.convertUnits(); + + /* + * use result from system as expected - I'm not testing unit conversion + * here (that's for the backend tests), I'm just testing that it correctly + * calls the unit conversion system + */ + final LinearUnitValue expectedInput = LinearUnitValue.of(Metric.METRE, + UncertainDouble.fromRoundedString("10000.0")); + final LinearUnitValue expectedOutput = expectedInput + .convertTo(Metric.KILOMETRE); + final UnitConversionRecord expectedUC = UnitConversionRecord.valueOf( + expectedInput.getUnit().getName(), + expectedOutput.getUnit().getName(), "10000.0", + expectedOutput.getValue().toString(false, RoundingMode.HALF_EVEN)); + assertEquals(List.of(expectedUC), viewBot.unitConversionList()); + } + + /** + * Tests that duplicate units are successfully removed, if that is asked for + * + * @since 2022-04-16 + */ + @Test + void testDuplicateUnits() { + final var metre = Metric.METRE; + final var meter = Metric.METRE.withName(NameSymbol.of("meter", "m")); + + // load 2 duplicate units + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + presenter.database.clear(); + presenter.database.addUnit("metre", metre); + presenter.database.addUnit("meter", meter); + presenter.setOneWayConversionEnabled(false); + + // test that only one of them is included if duplicate units disabled + presenter.setShowDuplicates(false); + presenter.updateView(); + assertEquals(1, viewBot.getFromUnitNames().size()); + assertEquals(1, viewBot.getToUnitNames().size()); + + // test that both of them is included if duplicate units enabled + presenter.setShowDuplicates(true); + presenter.updateView(); + assertEquals(2, viewBot.getFromUnitNames().size()); + assertEquals(2, viewBot.getToUnitNames().size()); + } + + /** + * Tests that one-way conversion correctly filters From and To units + * + * @since 2022-04-16 + */ + @Test + void testOneWayConversion() { + // metre is metric, inch is non-metric, tempC is semi-metric + final var allNames = Set.of("metre", "inch", "tempC"); + final var metricNames = Set.of("metre", "tempC"); + final var nonMetricNames = Set.of("inch", "tempC"); + + // load view with one metric and one non-metric unit + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + presenter.database.clear(); + presenter.database.addUnit("metre", Metric.METRE); + presenter.database.addUnit("inch", BritishImperial.Length.INCH); + presenter.database.addUnit("tempC", Metric.CELSIUS); + + // test that units are removed from each side when one-way conversion is + // enabled + presenter.setOneWayConversionEnabled(true); + assertEquals(nonMetricNames, viewBot.getFromUnitNames()); + assertEquals(metricNames, viewBot.getToUnitNames()); + + // test that units are kept when one-way conversion is disabled + presenter.setOneWayConversionEnabled(false); + assertEquals(allNames, viewBot.getFromUnitNames()); + assertEquals(allNames, viewBot.getToUnitNames()); + } + + /** + * Tests the prefix-viewing functionality. + * + * @since 2022-04-16 + */ + @Test + void testPrefixViewing() { + // setup + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + viewBot.setViewablePrefixNames(Set.of("kilo", "milli")); + presenter.setNumberDisplayRule(UncertainDouble::toString); + + // view prefix + viewBot.setViewedPrefixName("kilo"); + presenter.prefixSelected(); // just in case + + // get correct values + final var expectedNameSymbol = presenter.database.getPrefix("kilo") + .getNameSymbol(); + final var expectedMultiplierString = String + .valueOf(Metric.KILO.getMultiplier()); + + // test that presenter's values are correct + final var prefixRecord = viewBot.prefixViewList().get(0); + assertEquals(expectedNameSymbol, prefixRecord.getNameSymbol()); + assertEquals(expectedMultiplierString, prefixRecord.multiplierString()); + } + + /** + * Tests that rounding rules are used correctly. + * + * @since 2022-04-16 + */ + @ParameterizedTest + @MethodSource("getRoundingRules") + void testRoundingRules(Function<UncertainDouble, String> roundingRule) { + // setup + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + presenter.setNumberDisplayRule(roundingRule); + + // convert and round + viewBot.setInputValue("12345.6789"); + viewBot.setFromSelection("metre"); + viewBot.setToSelection("kilometre"); + presenter.convertUnits(); + + // test the result of the rounding + final String expectedOutputString = roundingRule + .apply(UncertainDouble.fromRoundedString("12.3456789")); + final String actualOutputString = viewBot.unitConversionList().get(0) + .outputValueString(); + assertEquals(expectedOutputString, actualOutputString); + } + + /** + * Tests that settings can be saved to and loaded from a file. + * + * @since 2022-04-16 + */ + @Test + void testSettingsSaving() { + // setup + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + + // set and save custom settings + presenter.setOneWayConversionEnabled(true); + presenter.setShowDuplicates(true); + presenter.setNumberDisplayRule(StandardDisplayRules.fixedPrecision(11)); + presenter.setPrefixRepetitionRule( + DefaultPrefixRepetitionRule.COMPLEX_REPETITION); + presenter.saveSettings(TEST_SETTINGS); + + // overwrite custom settings + presenter.setOneWayConversionEnabled(false); + presenter.setShowDuplicates(false); + presenter.setNumberDisplayRule(StandardDisplayRules.uncertaintyBased()); + + // load settings & test that they're the same + presenter.loadSettings(TEST_SETTINGS); + assertTrue(presenter.oneWayConversionEnabled()); + assertTrue(presenter.duplicatesShown()); + assertEquals(StandardDisplayRules.fixedPrecision(11), + presenter.getNumberDisplayRule()); + } + + /** + * Ensures the Presenter generates the correct data upon a unit-viewing. + * + * @since 2022-04-16 + */ + @Test + void testUnitViewing() { + // setup + final var viewBot = new ViewBot(); + final var presenter = new Presenter(viewBot); + viewBot.setViewableUnitNames(names(testUnits)); + + // view unit + viewBot.setViewedUnitName("metre"); + presenter.unitNameSelected(); // just in case this isn't triggered + // automatically + + // get correct values + final var expectedNameSymbol = presenter.database.getUnit("metre") + .getNameSymbol(); + final var expectedDefinition = "(Base unit)"; + final var expectedDimensionName = presenter + .getDimensionName(Metric.METRE.getDimension()); + final var expectedUnitType = UnitType.METRIC; + + // test for correctness + final var viewRecord = viewBot.unitViewList().get(0); + assertEquals(expectedNameSymbol, viewRecord.getNameSymbol()); + assertEquals(expectedDefinition, viewRecord.definition()); + assertEquals(expectedDimensionName, viewRecord.dimensionName()); + assertEquals(expectedUnitType, viewRecord.unitType()); + } + + /** + * Test for {@link Presenter#updateView()} + * + * @since 2022-02-12 + */ + @Test + void testUpdateView() { + // setup + final ViewBot viewBot = new ViewBot(); + final Presenter presenter = new Presenter(viewBot); + presenter.setOneWayConversionEnabled(false); + + // override default database units + presenter.database.clear(); + for (final Unit unit : testUnits) { + presenter.database.addUnit(unit.getPrimaryName().orElseThrow(), unit); + } + for (final var dimension : testDimensions) { + presenter.database.addDimension( + dimension.getPrimaryName().orElseThrow(), dimension); + } + + // set from and to units + viewBot.setFromUnitNames(names(testUnits)); + viewBot.setToUnitNames(names(testUnits)); + viewBot.setDimensionNames(names(testDimensions)); + viewBot.setSelectedDimensionName(Metric.Dimensions.LENGTH.getName()); + + // filter to length units only, then get the filtered sets of units + presenter.updateView(); + final Set<String> fromUnits = viewBot.getFromUnitNames(); + final Set<String> toUnits = viewBot.getToUnitNames(); + + // test that fromUnits/toUnits is [METRE, KILOMETRE] + assertEquals(Set.of("metre", "kilometre"), fromUnits); + assertEquals(Set.of("metre", "kilometre"), toUnits); + } +} |