@@ -202,8 +202,32 @@ async def test_reterminal_e1003_creates_entry(
202202 opts = result ["options" ]
203203 assert opts ["optimize" ] is False
204204 assert opts ["display_levels" ] == 16
205+ # Panel is native landscape (OpenDisplay firmware), so portrait
206+ # orientation is achieved by rotating the rendered canvas.
205207 assert opts ["width" ] == 1404
206208 assert opts ["height" ] == 1872
209+ assert opts ["rotation" ] == 90
210+
211+ async def test_reterminal_e1003_landscape_creates_entry (
212+ self , hass : HomeAssistant
213+ ) -> None :
214+ # Native landscape device in landscape orientation (the
215+ # default): no rotation, and dimensions match the panel's
216+ # native landscape buffer.
217+ flow = await _make_config_flow (hass )
218+ result = await flow .async_step_user (
219+ {
220+ "name" : "Office" ,
221+ "device_model" : "reterminal_e1003" ,
222+ "orientation" : "landscape" ,
223+ "update_interval" : 60 ,
224+ }
225+ )
226+
227+ assert result ["type" ] is FlowResultType .CREATE_ENTRY
228+ opts = result ["options" ]
229+ assert opts ["width" ] == 1872
230+ assert opts ["height" ] == 1404
207231 assert opts ["rotation" ] == 0
208232
209233 async def test_screen_portion_shows_form_for_trmnl (
@@ -1808,7 +1832,7 @@ async def test_migration_removes_sharpness_contrast(
18081832 ) -> None :
18091833 # Migration from minor_version<2 removes sharpness/contrast and
18101834 # adds exposure/saturation with their defaults. The entry then
1811- # cascades through the 2->3 migration too, ending at 3 .
1835+ # cascades through the 2->3 and 3->4 migrations too, ending at 4 .
18121836 from custom_components .eink_dashboard import async_migrate_entry
18131837
18141838 entry = MockConfigEntry (
@@ -1827,7 +1851,7 @@ async def test_migration_removes_sharpness_contrast(
18271851 result = await async_migrate_entry (hass , entry )
18281852
18291853 assert result is True
1830- assert entry .minor_version == 3
1854+ assert entry .minor_version == 4
18311855 assert "sharpness" not in entry .options
18321856 assert "contrast" not in entry .options
18331857 assert entry .options ["exposure" ] == 1.0
@@ -1863,7 +1887,8 @@ async def test_migration_renames_grayscale_levels(
18631887 self , hass : HomeAssistant
18641888 ) -> None :
18651889 # Migration from minor_version<3 renames the stored
1866- # grayscale_levels option key to display_levels.
1890+ # grayscale_levels option key to display_levels. The entry
1891+ # then cascades through the 3->4 migration too, ending at 4.
18671892 from custom_components .eink_dashboard import async_migrate_entry
18681893
18691894 entry = MockConfigEntry (
@@ -1882,21 +1907,113 @@ async def test_migration_renames_grayscale_levels(
18821907 result = await async_migrate_entry (hass , entry )
18831908
18841909 assert result is True
1885- assert entry .minor_version == 3
1910+ assert entry .minor_version == 4
18861911 assert "grayscale_levels" not in entry .options
18871912 assert entry .options ["display_levels" ] == 4
18881913
1889- async def test_migration_skipped_when_already_at_minor_version_3 (
1914+ async def test_migration_fixes_reterminal_e1003_landscape_rotation (
18901915 self ,
18911916 hass : HomeAssistant ,
18921917 ) -> None :
1893- # Entries already at minor_version=3 are not migrated again.
1918+ # Migration from minor_version<4 recomputes width/height/
1919+ # rotation for reterminal_e1003 entries created under the old,
1920+ # buggy preset. A landscape entry had a stale rotation=90
1921+ # baked in; the fix clears it to 0.
18941922 from custom_components .eink_dashboard import async_migrate_entry
18951923
18961924 entry = MockConfigEntry (
18971925 domain = DOMAIN ,
18981926 minor_version = 3 ,
18991927 entry_id = "test-entry" ,
1928+ options = {
1929+ "device_model" : "reterminal_e1003" ,
1930+ "orientation" : "landscape" ,
1931+ "width" : 1872 ,
1932+ "height" : 1404 ,
1933+ "rotation" : 90 ,
1934+ },
1935+ )
1936+ entry .add_to_hass (hass )
1937+
1938+ result = await async_migrate_entry (hass , entry )
1939+
1940+ assert result is True
1941+ assert entry .minor_version == 4
1942+ assert entry .options ["width" ] == 1872
1943+ assert entry .options ["height" ] == 1404
1944+ assert entry .options ["rotation" ] == 0
1945+
1946+ async def test_migration_fixes_reterminal_e1003_portrait_rotation (
1947+ self ,
1948+ hass : HomeAssistant ,
1949+ ) -> None :
1950+ # A portrait reterminal_e1003 entry had a stale rotation=0
1951+ # baked in under the old preset; the fix sets it to 90.
1952+ from custom_components .eink_dashboard import async_migrate_entry
1953+
1954+ entry = MockConfigEntry (
1955+ domain = DOMAIN ,
1956+ minor_version = 3 ,
1957+ entry_id = "test-entry" ,
1958+ options = {
1959+ "device_model" : "reterminal_e1003" ,
1960+ "orientation" : "portrait" ,
1961+ "width" : 1404 ,
1962+ "height" : 1872 ,
1963+ "rotation" : 0 ,
1964+ },
1965+ )
1966+ entry .add_to_hass (hass )
1967+
1968+ result = await async_migrate_entry (hass , entry )
1969+
1970+ assert result is True
1971+ assert entry .minor_version == 4
1972+ assert entry .options ["width" ] == 1404
1973+ assert entry .options ["height" ] == 1872
1974+ assert entry .options ["rotation" ] == 90
1975+
1976+ async def test_migration_skips_non_e1003_devices (
1977+ self ,
1978+ hass : HomeAssistant ,
1979+ ) -> None :
1980+ # Entries for other device models must not have their
1981+ # width/height/rotation touched by the 3->4 migration.
1982+ from custom_components .eink_dashboard import async_migrate_entry
1983+
1984+ entry = MockConfigEntry (
1985+ domain = DOMAIN ,
1986+ minor_version = 3 ,
1987+ entry_id = "test-entry" ,
1988+ options = {
1989+ "device_model" : "kindle_pw" ,
1990+ "orientation" : "portrait" ,
1991+ "width" : 758 ,
1992+ "height" : 1024 ,
1993+ "rotation" : 0 ,
1994+ },
1995+ )
1996+ entry .add_to_hass (hass )
1997+
1998+ result = await async_migrate_entry (hass , entry )
1999+
2000+ assert result is True
2001+ assert entry .minor_version == 4
2002+ assert entry .options ["width" ] == 758
2003+ assert entry .options ["height" ] == 1024
2004+ assert entry .options ["rotation" ] == 0
2005+
2006+ async def test_migration_skipped_when_already_at_minor_version_4 (
2007+ self ,
2008+ hass : HomeAssistant ,
2009+ ) -> None :
2010+ # Entries already at minor_version=4 are not migrated again.
2011+ from custom_components .eink_dashboard import async_migrate_entry
2012+
2013+ entry = MockConfigEntry (
2014+ domain = DOMAIN ,
2015+ minor_version = 4 ,
2016+ entry_id = "test-entry" ,
19002017 options = {
19012018 "update_interval" : 60 ,
19022019 "exposure" : 1.0 ,
0 commit comments