Skip to content

Commit

Permalink
Replace manual HTML tests with regression tests (#37)
Browse files Browse the repository at this point in the history
Also add more example objects and a script for viewing rendered
HTML.
  • Loading branch information
aazuspan authored Nov 29, 2024
1 parent fd42463 commit 122be19
Show file tree
Hide file tree
Showing 47 changed files with 470 additions and 228 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,4 @@ __pycache__/
htmlcov/
dist/
*.egg-info/
.tox/

tests/data/
.tox/
16 changes: 13 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ Additional arguments can be passed to `pytest` after the script name, e.g.:
hatch run test:all -k feature
```

Rendered HTML is tested using [pytest-regressions](https://pytest-regressions.readthedocs.io/en/latest/overview.html), which compares the current HTML output for each object to the previously recorded output. Tests will fail if the HTML output changes. If the change is correct (i.e. an update to the HTML formatting or a difference in object representations in Earth Engine), use the `--force-regen` argument to regenerate a new "reference" HTML output.

### Building New Tests

New features should have unit tests. If your test needs to use `getInfo` to retrieve data from an Earth Engine object, you'll need to use the caching system described below.

Using `getInfo` to retrieve data from an Earth Engine object can be slow and network-dependent. To speed up tests, `eerepr` uses a caching function `tests.cache.get_info` to load data. This function takes an Earth Engine object and either 1) retrieves its info from a local cache file if it has been used before, or 2) retrieves it from the server and adds it to the cache. The cache directory and file (`tests/data/data.json`) will be created automatically the first time tests are run.
Using `getInfo` to retrieve data from an Earth Engine object can be slow and network-dependent. To speed up tests, `eerepr` uses a caching function `tests.cache.get_info` to load data. This function takes an Earth Engine object and either 1) retrieves its info from a local cache file if it has been used before, or 2) retrieves it from the server and adds it to the cache. The cache directory and file (`tests/data/.cache.json`) will be created automatically the first time tests are run.

To demonstrate, let's write a new dummy test that checks the properties of a custom `ee.Image`.

Expand All @@ -75,6 +77,14 @@ def test_my_image():
assert "custom_property" in info["properties"]
```

The first time the test is run, `getInfo` will be used to retrieve the image metadata and store it in `tests/data/data.json`. Subsequent runs will pull the data directly from the cache.
The first time the test is run, `getInfo` will be used to retrieve the image metadata and store it in `tests/data/.cache.json`. Subsequent runs will pull the data directly from the cache. Caches are kept locally and are not version-controlled.

When a new object is added to regression testing, the first run will fail and generate a new reference file. Subsequent tests will pass. Output from regression testing *is* version controlled, so new outputs should be committed.

### Previewing HTML Output

Caches are kept locally and are not version-controlled, so there's no need to commit newly added objects.
Running the command below renders an HTML repr with a variety of different EE objects and opens it in the default web browser. Use this to visually compare results with outputs from the Code Editor.

```bash
hatch run test:html
```
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ dependencies = ["pre-commit"]
dependencies = [
"pytest",
"pytest-cov",
"pytest-regressions",
]

[tool.hatch.envs.test.scripts]
all = "pytest . {args}"
cov = "pytest . --cov=eerepr {args}"
html = "python tests/preview_html.py"

[tool.ruff.lint]
select = ["E", "I", "F", "B", "FA", "UP", "ISC", "PT", "Q", "RET", "SIM", "PERF"]
Expand Down
2 changes: 1 addition & 1 deletion tests/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import ee

CACHE_DIR = Path(__file__).parent / "data/"
CACHE_PATH = CACHE_DIR / "data.json"
CACHE_PATH = CACHE_DIR / ".cache.json"


def get_info(obj: ee.ComputedObject) -> dict:
Expand Down
2 changes: 2 additions & 0 deletions tests/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.cache.json
.preview.html
6 changes: 6 additions & 0 deletions tests/data/test_regression_array_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'<li><label class=''ee-shut''>[[1, 2], [3, 4]]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: [1, 2]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>2</span></li></ul></li><li><label class=''ee-shut''>1: [3, 4]<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>3</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>4</span></li></ul></li></ul></li>'
10 changes: 10 additions & 0 deletions tests/data/test_regression_band_dict_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'<li><label class=''ee-shut''>"B1", unsigned int16, EPSG:32610, 1830x1830 px<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>id:</span><span
class=''ee-v''>B1</span></li><li><span class=''ee-k''>crs:</span><span class=''ee-v''>EPSG:32610</span></li><li><label
class=''ee-shut''>data_type: unsigned int16<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>PixelType</span></li><li><span class=''ee-k''>max:</span><span
class=''ee-v''>65535</span></li><li><span class=''ee-k''>min:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>precision:</span><span class=''ee-v''>int</span></li></ul></li><li><label
class=''ee-shut''>dimensions: [1830, 1830]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1830</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>1830</span></li></ul></li></ul></li>'
3 changes: 3 additions & 0 deletions tests/data/test_regression_classifier_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<li><label class='ee-shut'>Classifier.smileKNN<input type='checkbox' class='ee-toggle'></label><ul><li><span
class='ee-k'>type:</span><span class='ee-v'>Classifier.smileKNN</span></li></ul></li>
...
4 changes: 4 additions & 0 deletions tests/data/test_regression_clusterer_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<li><label class='ee-shut'>Clusterer.wekaKMeans<input type='checkbox' class='ee-toggle'></label><ul><li><span
class='ee-k'>type:</span><span class='ee-v'>Clusterer.wekaKMeans</span></li><li><span
class='ee-k'>nClusters:</span><span class='ee-v'>2</span></li></ul></li>
...
6 changes: 6 additions & 0 deletions tests/data/test_regression_confusion_matrix_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'<li><label class=''ee-shut''>[[1, 2], [3, 4]]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: [1, 2]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>2</span></li></ul></li><li><label class=''ee-shut''>1: [3, 4]<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>3</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>4</span></li></ul></li></ul></li>'
16 changes: 16 additions & 0 deletions tests/data/test_regression_constant_image_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'<li><label class=''ee-shut''>Image foo (1 band)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>Image</span></li><li><span class=''ee-k''>id:</span><span
class=''ee-v''>foo</span></li><li><label class=''ee-shut''>bands: List (1 element)<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><label class=''ee-shut''>0:
"constant", int ∈ [0, 0], EPSG:4326<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>id:</span><span class=''ee-v''>constant</span></li><li><span class=''ee-k''>crs:</span><span
class=''ee-v''>EPSG:4326</span></li><li><label class=''ee-shut''>crs_transform:
[1, 0, 0, 0, 1, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>2:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>3:</span><span class=''ee-v''>0</span></li><li><span class=''ee-k''>4:</span><span
class=''ee-v''>1</span></li><li><span class=''ee-k''>5:</span><span class=''ee-v''>0</span></li></ul></li><li><label
class=''ee-shut''>data_type: int ∈ [0, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>PixelType</span></li><li><span class=''ee-k''>max:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>min:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>precision:</span><span class=''ee-v''>int</span></li></ul></li></ul></li></ul></li></ul></li>'
4 changes: 4 additions & 0 deletions tests/data/test_regression_date_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<li><label class='ee-shut'>Date (2021-03-27 14:01:07)<input type='checkbox' class='ee-toggle'></label><ul><li><span
class='ee-k'>type:</span><span class='ee-v'>Date</span></li><li><span class='ee-k'>value:</span><span
class='ee-v'>1616853667000</span></li></ul></li>
...
6 changes: 6 additions & 0 deletions tests/data/test_regression_daterange_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'<li><label class=''ee-shut''>DateRange [2020-01-01 21:01:10, 2022-03-01 14:32:11]<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>type:</span><span
class=''ee-v''>DateRange</span></li><li><label class=''ee-shut''>dates: [1577912470000,
1646145131000]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1577912470000</span></li><li><span
class=''ee-k''>1:</span><span class=''ee-v''>1646145131000</span></li></ul></li></ul></li>'
3 changes: 3 additions & 0 deletions tests/data/test_regression_dict_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<li><label class='ee-shut'>Object (1 property)<input type='checkbox' class='ee-toggle'></label><ul><li><span
class='ee-k'>foo:</span><span class='ee-v'>bar</span></li></ul></li>
...
8 changes: 8 additions & 0 deletions tests/data/test_regression_feature_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'<li><label class=''ee-shut''>Feature (Point, 1 property)<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>type:</span><span class=''ee-v''>Feature</span></li><li><label
class=''ee-shut''>geometry: Point (0.00, 0.00)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>Point</span></li><li><label class=''ee-shut''>coordinates:
[0, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>0</span></li></ul></li></ul></li><li><label
class=''ee-shut''>properties: Object (1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>foo:</span><span class=''ee-v''>bar</span></li></ul></li></ul></li>'
15 changes: 15 additions & 0 deletions tests/data/test_regression_feature_collection_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'<li><label class=''ee-shut''>FeatureCollection (1 element, 2 columns)<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>type:</span><span class=''ee-v''>FeatureCollection</span></li><li><label
class=''ee-shut''>columns: Object (2 properties)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>foo:</span><span class=''ee-v''>String</span></li><li><span class=''ee-k''>system:index:</span><span
class=''ee-v''>String</span></li></ul></li><li><label class=''ee-shut''>features:
List (1 element)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: Feature (Point, 1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>Feature</span></li><li><span class=''ee-k''>id:</span><span
class=''ee-v''>0</span></li><li><label class=''ee-shut''>geometry: Point (0.00,
0.00)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>type:</span><span
class=''ee-v''>Point</span></li><li><label class=''ee-shut''>coordinates: [0, 0]<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>0</span></li></ul></li></ul></li><li><label
class=''ee-shut''>properties: Object (1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>foo:</span><span class=''ee-v''>bar</span></li></ul></li></ul></li></ul></li></ul></li>'
4 changes: 4 additions & 0 deletions tests/data/test_regression_filter_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<li><label class='ee-shut'>Filter.eq<input type='checkbox' class='ee-toggle'></label><ul><li><span
class='ee-k'>type:</span><span class='ee-v'>Filter.eq</span></li><li><span class='ee-k'>leftField:</span><span
class='ee-v'>foo</span></li><li><span class='ee-k'>rightValue:</span><span class='ee-v'>bar</span></li></ul></li>
...
40 changes: 40 additions & 0 deletions tests/data/test_regression_image_collection_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'<li><label class=''ee-shut''>ImageCollection (2 elements)<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>type:</span><span class=''ee-v''>ImageCollection</span></li><li><label
class=''ee-shut''>bands: []<input type=''checkbox'' class=''ee-toggle''></label><ul></ul></li><li><label
class=''ee-shut''>properties: Object (1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>test_prop:</span><span class=''ee-v''>42</span></li></ul></li><li><label
class=''ee-shut''>features: List (2 elements)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: Image (1 band)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>Image</span></li><li><label class=''ee-shut''>bands:
List (1 element)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: "constant", int ∈ [0, 0], EPSG:4326<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>id:</span><span class=''ee-v''>constant</span></li><li><span
class=''ee-k''>crs:</span><span class=''ee-v''>EPSG:4326</span></li><li><label class=''ee-shut''>crs_transform:
[1, 0, 0, 0, 1, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>2:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>3:</span><span class=''ee-v''>0</span></li><li><span class=''ee-k''>4:</span><span
class=''ee-v''>1</span></li><li><span class=''ee-k''>5:</span><span class=''ee-v''>0</span></li></ul></li><li><label
class=''ee-shut''>data_type: int ∈ [0, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>PixelType</span></li><li><span class=''ee-k''>max:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>min:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>precision:</span><span class=''ee-v''>int</span></li></ul></li></ul></li></ul></li><li><label
class=''ee-shut''>properties: Object (1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>system:index:</span><span class=''ee-v''>0</span></li></ul></li></ul></li><li><label
class=''ee-shut''>1: Image (1 band)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>Image</span></li><li><label class=''ee-shut''>bands:
List (1 element)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><label
class=''ee-shut''>0: "constant", int ∈ [1, 1], EPSG:4326<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>id:</span><span class=''ee-v''>constant</span></li><li><span
class=''ee-k''>crs:</span><span class=''ee-v''>EPSG:4326</span></li><li><label class=''ee-shut''>crs_transform:
[1, 0, 0, 0, 1, 0]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>2:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>3:</span><span class=''ee-v''>0</span></li><li><span class=''ee-k''>4:</span><span
class=''ee-v''>1</span></li><li><span class=''ee-k''>5:</span><span class=''ee-v''>0</span></li></ul></li><li><label
class=''ee-shut''>data_type: int ∈ [1, 1]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>PixelType</span></li><li><span class=''ee-k''>max:</span><span
class=''ee-v''>1</span></li><li><span class=''ee-k''>min:</span><span class=''ee-v''>1</span></li><li><span
class=''ee-k''>precision:</span><span class=''ee-v''>int</span></li></ul></li></ul></li></ul></li><li><label
class=''ee-shut''>properties: Object (1 property)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>system:index:</span><span class=''ee-v''>1</span></li></ul></li></ul></li></ul></li></ul></li>'
19 changes: 19 additions & 0 deletions tests/data/test_regression_kernel_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"<li><label class='ee-shut'>Kernel.gaussian<input type='checkbox' class='ee-toggle'></label><ul><li><span\
\ class='ee-k'>type:</span><span class='ee-v'>Kernel.gaussian</span></li><li><label\
\ class='ee-shut'>center: [3, 3]<input type='checkbox' class='ee-toggle'></label><ul><li><span\
\ class='ee-k'>0:</span><span class='ee-v'>3</span></li><li><span class='ee-k'>1:</span><span\
\ class='ee-v'>3</span></li></ul></li><li><span class='ee-k'>radius:</span><span\
\ class='ee-v'>3</span></li><li><span class='ee-k'>weights:</span><span class='ee-v'>\n\
\ [1.9651916124031917E-5, 2.3940934949727E-4, 0.001072958264978661, 0.0017690091140438226,\
\ 0.001072958264978661, 2.3940934949727E-4, 1.9651916124031917E-5]\n [2.3940934949727E-4,\
\ 0.0029166029543864387, 0.013071307583189414, 0.02155094284826827, 0.013071307583189414,\
\ 0.0029166029543864387, 2.3940934949727E-4]\n [0.001072958264978661, 0.013071307583189414,\
\ 0.05858153633060706, 0.09658462501856419, 0.05858153633060706, 0.013071307583189414,\
\ 0.001072958264978661]\n [0.0017690091140438226, 0.02155094284826827, 0.09658462501856419,\
\ 0.15924112569070253, 0.09658462501856419, 0.02155094284826827, 0.0017690091140438226]\n\
\ [0.001072958264978661, 0.013071307583189414, 0.05858153633060706, 0.09658462501856419,\
\ 0.05858153633060706, 0.013071307583189414, 0.001072958264978661]\n [2.3940934949727E-4,\
\ 0.0029166029543864387, 0.013071307583189414, 0.02155094284826827, 0.013071307583189414,\
\ 0.0029166029543864387, 2.3940934949727E-4]\n [1.9651916124031917E-5, 2.3940934949727E-4,\
\ 0.001072958264978661, 0.0017690091140438226, 0.001072958264978661, 2.3940934949727E-4,\
\ 1.9651916124031917E-5]</span></li></ul></li>"
13 changes: 13 additions & 0 deletions tests/data/test_regression_linearring_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'<li><label class=''ee-shut''>LinearRing (4 vertices)<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>type:</span><span class=''ee-v''>LinearRing</span></li><li><label
class=''ee-shut''>coordinates: [[0, 0], [1, 1], [2, 2], [0, 0]]<input type=''checkbox''
class=''ee-toggle''></label><ul><li><label class=''ee-shut''>0: [0, 0]<input type=''checkbox''
class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span class=''ee-v''>0</span></li><li><span
class=''ee-k''>1:</span><span class=''ee-v''>0</span></li></ul></li><li><label class=''ee-shut''>1:
[1, 1]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>1</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>1</span></li></ul></li><li><label
class=''ee-shut''>2: [2, 2]<input type=''checkbox'' class=''ee-toggle''></label><ul><li><span
class=''ee-k''>0:</span><span class=''ee-v''>2</span></li><li><span class=''ee-k''>1:</span><span
class=''ee-v''>2</span></li></ul></li><li><label class=''ee-shut''>3: [0, 0]<input
type=''checkbox'' class=''ee-toggle''></label><ul><li><span class=''ee-k''>0:</span><span
class=''ee-v''>0</span></li><li><span class=''ee-k''>1:</span><span class=''ee-v''>0</span></li></ul></li></ul></li></ul></li>'
Loading

0 comments on commit 122be19

Please sign in to comment.