Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194package social.grain
import org.junit.Assert.assertEqualsimport org.junit.Assert.assertNullimport org.junit.Testimport social.grain.data.api.PinnedFeedimport social.grain.data.model.AspectRatioimport social.grain.data.model.GrainExifimport social.grain.util.compactCountimport social.grain.util.monthDayimport social.grain.util.nowIsoimport social.grain.util.parseIsoimport social.grain.util.relativeTimeimport java.time.Instant
/** * The small conversions that sit under every screen. * * None of them can fail loudly: a mis-rounded shutter speed or a count that * reads "1.0K" is simply wrong on screen, in a caption nobody is checking * against the source. */class FormattingTest {
// MARK: - Counts
@Test fun countsBelowAThousandAreWrittenOutInFull() { assertEquals("0", 0.compactCount()) assertEquals("999", 999.compactCount()) }
@Test fun thousandsAndMillionsDropTheirTrailingZero() { assertEquals("1K", 1_000.compactCount()) assertEquals("1.2K", 1_200.compactCount()) assertEquals("2K", 2_000.compactCount()) assertEquals("12.3K", 12_345.compactCount()) assertEquals("1M", 1_000_000.compactCount()) assertEquals("1.5M", 1_500_000.compactCount()) }
// MARK: - Dates
@Test fun timestampsAreWrittenTheWayJavascriptWritesThem() { assertEquals( "2026-03-01T12:00:00.000Z", nowIso(Instant.parse("2026-03-01T12:00:00Z")), ) }
@Test fun timestampsParseWithOrWithoutFractionalSecondsAndAnOffset() { assertEquals( Instant.parse("2026-03-01T12:00:00Z"), parseIso("2026-03-01T12:00:00.000Z"), ) assertEquals(Instant.parse("2026-03-01T12:00:00Z"), parseIso("2026-03-01T12:00:00Z")) assertEquals( "An offset is still a moment in time", Instant.parse("2026-03-01T12:00:00Z"), parseIso("2026-03-01T13:00:00+01:00"), ) assertNull(parseIso("some time last week")) }
@Test fun relativeTimeCountsUpThroughTheUnitsAndThenGivesADate() { val now = System.currentTimeMillis() fun ago(seconds: Long) = relativeTime(Instant.ofEpochMilli(now - seconds * 1000))
assertEquals("now", ago(5)) assertEquals("59m", ago(59 * 60)) assertEquals("2h", ago(2 * 3600)) assertEquals("3d", ago(3 * 86_400)) assertEquals("2w", ago(14 * 86_400)) assertEquals("Anything older is a date", "Mar 5", relativeTime("2020-03-05T12:00:00Z")) }
@Test fun aMissingOrUnreadableTimestampFormatsAsNothingAtAll() { assertEquals("", relativeTime(null)) assertEquals("", relativeTime("not a date")) assertEquals("", monthDay(null)) assertEquals("Mar 5", monthDay("2020-03-05T12:00:00Z")) }
// MARK: - Aspect ratios
@Test fun anAspectRatioWithNoHeightIsTreatedAsSquare() { assertEquals(1.5f, AspectRatio(3, 2).ratio) assertEquals("A zero height would otherwise divide by zero", 1f, AspectRatio(3, 0).ratio) }
// MARK: - Exif
private fun exif( make: String? = null, model: String? = null, lensMake: String? = null, lensModel: String? = null, fNumber: String? = null, exposureTime: String? = null, focal: String? = null, iso: Int? = null, ) = GrainExif( make = make, model = model, lensMake = lensMake, lensModel = lensModel, fNumber = fNumber, exposureTime = exposureTime, focalLengthIn35mmFormat = focal, iSO = iso, )
@Test fun theCameraNameJoinsTheMakeAndModelAndSkipsWhatIsMissing() { assertEquals("Fujifilm X100V", exif(make = "Fujifilm", model = "X100V").cameraName) assertEquals("X100V", exif(model = "X100V").cameraName) assertNull(exif().cameraName) assertNull("Empty strings are as absent as nulls", exif(make = "", model = "").cameraName) }
@Test fun theLensNamePrefersTheModelAndFallsBackToTheMake() { assertEquals("XF 23mm f/2", exif(lensModel = "XF 23mm f/2").lensName) assertEquals("Fujinon", exif(lensMake = "Fujinon").lensName) assertNull(exif().lensName) }
@Test fun apertureDropsTheZeroesTheServerLeavesOn() { assertEquals("f/2", exif(fNumber = "2.0").formattedFNumber) assertEquals("f/2.8", exif(fNumber = "f/2.80").formattedFNumber) assertEquals("f/1.4", exif(fNumber = "1.4").formattedFNumber) assertEquals("Something unparseable is passed through", "wide", exif(fNumber = "wide").formattedFNumber) assertNull(exif().formattedFNumber) }
@Test fun shutterSpeedIsNormalisedToAWholeFractionOrSeconds() { assertEquals("1/500s", exif(exposureTime = "1/500").formattedExposureTime) assertEquals("1/500s", exif(exposureTime = "0.002s").formattedExposureTime) assertEquals("30s", exif(exposureTime = "30").formattedExposureTime) assertEquals("1.5s", exif(exposureTime = "1.5").formattedExposureTime) assertEquals("fast", exif(exposureTime = "fast").formattedExposureTime) assertNull(exif().formattedExposureTime) }
@Test fun focalLengthIsRoundedToWholeMillimetres() { assertEquals("35mm", exif(focal = "35").formattedFocalLength) assertEquals("35mm", exif(focal = "34.6mm").formattedFocalLength) assertEquals("long", exif(focal = "long").formattedFocalLength) assertNull(exif().formattedFocalLength) }
@Test fun theSettingsLineJoinsWhateverIsKnownAndIsAbsentWhenNothingIs() { val full = exif(fNumber = "2.0", exposureTime = "1/500", focal = "35", iso = 400) assertEquals("35mm · f/2 · 1/500s · ISO 400", full.settingsLine) assertEquals("ISO 400", exif(iso = 400).settingsLine) assertNull(exif().settingsLine) }
@Test fun aPhotoWithNothingToSayHidesTheExifPanel() { assertEquals(false, exif().hasDisplayableData) assertEquals(true, exif(iso = 100).hasDisplayableData) assertEquals(true, exif(make = "Leica").hasDisplayableData) }
// MARK: - Pinned feeds
@Test fun theDefaultPinsAreTheThreeGrainShipsWith() { assertEquals(listOf("recent", "following", "foryou"), PinnedFeed.defaults.map { it.id }) assertEquals("Recent", PinnedFeed.defaults.first().label) }
@Test fun aPlainFeedNamesItselfByIdAndACompoundOneByType() { assertEquals("following", PinnedFeed.defaults[1].feedName) assertNull(PinnedFeed.defaults[1].feedValue)
val location = PinnedFeed("location:8928308280fffff", "Mission", "location", "/l") assertEquals("location", location.feedName) assertEquals("8928308280fffff", location.feedValue) }}