ソースを参照

Update tests for recent changes.

- replace device_state_attributes with extra_state_attributes
- add tests for recently added devices
- fix some types in function names
Jason Rumney 4 年 前
コミット
d5fbbc8462
69 ファイル変更374 行追加157 行削除
  1. 1 1
      custom_components/tuya_local/manifest.json
  2. 2 2
      tests/devices/test_andersson_gsh_heater.py
  3. 2 2
      tests/devices/test_anko_fan.py
  4. 2 2
      tests/devices/test_arlec_fan.py
  5. 3 3
      tests/devices/test_aspen_adv200_fan.py
  6. 2 2
      tests/devices/test_awow_th213_thermostat.py
  7. 2 2
      tests/devices/test_beca_bac002_thermostat.py
  8. 2 2
      tests/devices/test_beca_bhp6000_thermostat.py
  9. 2 2
      tests/devices/test_beca_bht002_thermostat.py
  10. 2 2
      tests/devices/test_beca_bht6000_thermostat.py
  11. 3 3
      tests/devices/test_bwt_heatpump.py
  12. 2 2
      tests/devices/test_carson_cb.py
  13. 3 3
      tests/devices/test_deta_fan.py
  14. 101 0
      tests/devices/test_digoo_dgsp202.py
  15. 5 5
      tests/devices/test_eanons_humidifier.py
  16. 2 2
      tests/devices/test_eberg_qubo_q40hd_heatpump.py
  17. 2 2
      tests/devices/test_electriq_12wminv_heatpump.py
  18. 2 2
      tests/devices/test_electriq_cd12_dehumidifier.py
  19. 3 3
      tests/devices/test_electriq_cd20_dehumidifier.py
  20. 3 3
      tests/devices/test_electriq_cd25_dehumidifier.py
  21. 2 2
      tests/devices/test_eurom_600_heater.py
  22. 2 2
      tests/devices/test_eurom_601_heater.py
  23. 2 2
      tests/devices/test_eurom_walldesignheat2000_heater.py
  24. 2 2
      tests/devices/test_fersk_vind_2_climate.py
  25. 2 2
      tests/devices/test_garage_door_opener.py
  26. 2 2
      tests/devices/test_gardenpac_heatpump.py
  27. 4 4
      tests/devices/test_goldair_dehumidifier.py
  28. 3 3
      tests/devices/test_goldair_fan.py
  29. 3 3
      tests/devices/test_goldair_geco_heater.py
  30. 3 3
      tests/devices/test_goldair_gpcv_heater.py
  31. 2 2
      tests/devices/test_goldair_gpph_heater.py
  32. 3 3
      tests/devices/test_grid_connect_double_power_point.py
  33. 2 2
      tests/devices/test_hellnar_heatpump.py
  34. 2 2
      tests/devices/test_inkbird_itc306a_thermostat.py
  35. 3 3
      tests/devices/test_kogan_dehumidifier.py
  36. 2 2
      tests/devices/test_kogan_kahtp_heater.py
  37. 4 4
      tests/devices/test_kogan_kashmfp20ba_heater.py
  38. 2 2
      tests/devices/test_kogan_kawfhtp_heater.py
  39. 2 2
      tests/devices/test_kogan_kawfpac09ya_airconditioner.py
  40. 2 2
      tests/devices/test_lexy_f501_fan.py
  41. 2 2
      tests/devices/test_madimack_elitev3_heatpump.py
  42. 2 2
      tests/devices/test_madimack_heatpump.py
  43. 2 2
      tests/devices/test_minco_mh1823d_thermostat.py
  44. 2 2
      tests/devices/test_moes_bht002_thermostat.py
  45. 2 2
      tests/devices/test_nedis_htpl20f_heater.py
  46. 3 3
      tests/devices/test_poolex_silverline_heatpump.py
  47. 3 3
      tests/devices/test_poolex_vertigo_heatpump.py
  48. 1 1
      tests/devices/test_purline_m100_heater.py
  49. 3 3
      tests/devices/test_remora_heatpump.py
  50. 3 2
      tests/devices/test_renpho_rp_ap001s.py
  51. 2 2
      tests/devices/test_saswell_c16_thermostat.py
  52. 2 2
      tests/devices/test_saswell_t29utk_thermostat.py
  53. 32 0
      tests/devices/test_simple_switch_with_timer.py
  54. 2 2
      tests/devices/test_smartplugv1.py
  55. 2 2
      tests/devices/test_smartplugv2.py
  56. 1 1
      tests/devices/test_smartplugv2_energy.py
  57. 3 3
      tests/devices/test_stirling_fs140dc_fan.py
  58. 2 2
      tests/devices/test_tadiran_wind_heatpump.py
  59. 2 2
      tests/devices/test_tmwf02_fan.py
  60. 2 2
      tests/devices/test_wetair_wawh1210lw_humidifier.py
  61. 2 2
      tests/devices/test_wetair_wch750_heater.py
  62. 83 0
      tests/devices/test_woox_r4028_powerstrip.py
  63. 4 4
      tests/mixins/binary_sensor.py
  64. 2 2
      tests/mixins/light.py
  65. 1 1
      tests/mixins/lock.py
  66. 4 4
      tests/mixins/number.py
  67. 4 4
      tests/mixins/select.py
  68. 2 2
      tests/mixins/sensor.py
  69. 4 4
      tests/mixins/switch.py

+ 1 - 1
custom_components/tuya_local/manifest.json

@@ -2,7 +2,7 @@
     "domain": "tuya_local",
     "iot_class": "local_polling",
     "name": "Tuya Local",
-    "version": "0.14.0",
+    "version": "0.14.1",
     "documentation": "https://github.com/make-all/tuya-local",
     "issue_tracker": "https://github.com/make-all/tuya-local/issues",
     "dependencies": [],

+ 2 - 2
tests/devices/test_andersson_gsh_heater.py

@@ -131,6 +131,6 @@ class TestAnderssonGSHHeater(TargetTemperatureTests, TuyaDeviceTestCase):
         # There are currently no known error states; update this as
         # they are discovered
         self.dps[ERROR_DPS] = "something"
-        self.assertEqual(self.subject.device_state_attributes, {"error": "something"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "something"})
         self.dps[ERROR_DPS] = "0"
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})

+ 2 - 2
tests/devices/test_anko_fan.py

@@ -111,6 +111,6 @@ class TestAnkoFan(SwitchableTests, BasicNumberTests, TuyaDeviceTestCase):
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 6}):
             await self.subject.async_set_percentage(80)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
-        self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
+        self.assertEqual(self.subject.extra_state_attributes, {"timer": 5})

+ 2 - 2
tests/devices/test_arlec_fan.py

@@ -117,6 +117,6 @@ class TestArlecFan(SwitchableTests, BasicSelectTests, TuyaDeviceTestCase):
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 5}):
             await self.subject.async_set_percentage(80)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "2hour"
-        self.assertEqual(self.subject.device_state_attributes, {"timer": "2hour"})
+        self.assertEqual(self.subject.extra_state_attributes, {"timer": "2hour"})

+ 3 - 3
tests/devices/test_aspen_adv200_fan.py

@@ -175,7 +175,7 @@ class TestAspenASP200Fan(
         ):
             await self.climate.async_set_hvac_mode(HVAC_MODE_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN8_DPS] = 8
-        self.assertDictEqual(self.subject.device_state_attributes, {"unknown_8": 8})
-        self.assertEqual(self.climate.device_state_attributes, {})
+        self.assertDictEqual(self.subject.extra_state_attributes, {"unknown_8": 8})
+        self.assertEqual(self.climate.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_awow_th213_thermostat.py

@@ -229,7 +229,7 @@ class TestAwowTH213Thermostat(
         self.dps[HVACMODE_DPS] = False
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = 8
         self.dps[EXTERNTEMP_DPS] = 27
         self.dps[SENSOR_DPS] = 1
@@ -240,7 +240,7 @@ class TestAwowTH213Thermostat(
         self.dps[UNKNOWN110_DPS] = 110
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "error": 8,
                 "external_temperature": 27,

+ 2 - 2
tests/devices/test_beca_bac002_thermostat.py

@@ -215,5 +215,5 @@ class TestBecaBAC002Thermostat(
         ):
             await self.subject.async_set_fan_mode(FAN_LOW)
 
-    def test_device_state_attribures(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
+    def test_extra_state_attribures(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_beca_bhp6000_thermostat.py

@@ -136,8 +136,8 @@ class TestBecaBHP6000Thermostat(
         ):
             await self.subject.async_set_fan_mode("on")
 
-    def test_device_state_attribures(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
+    def test_extra_state_attributes(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})
 
     def test_icons(self):
         self.dps[HVACMODE_DPS] = 1

+ 2 - 2
tests/devices/test_beca_bht002_thermostat.py

@@ -123,12 +123,12 @@ class TestBecaBHT002Thermostat(
             ],
         )
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[FLOOR_DPS] = 45
         self.dps[UNKNOWN104_DPS] = False
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"floor_temperature": 22.5, "unknown_104": False},
         )
 

+ 2 - 2
tests/devices/test_beca_bht6000_thermostat.py

@@ -119,13 +119,13 @@ class TestBecaBHT6000Thermostat(
             ],
         )
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[FLOOR_DPS] = 45
         self.dps[UNKNOWN103_DPS] = "103"
         self.dps[UNKNOWN104_DPS] = False
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"floor_temperature": 22.5, "unknown_103": "103", "unknown_104": False},
         )
 

+ 3 - 3
tests/devices/test_bwt_heatpump.py

@@ -194,15 +194,15 @@ class TestBWTHeatpump(
 
     def test_error_state(self):
         self.dps[ERROR_DPS] = 0
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})
 
         self.dps[ERROR_DPS] = 1
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "Water Flow Protection"},
         )
         self.dps[ERROR_DPS] = 2
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": 2},
         )

+ 2 - 2
tests/devices/test_carson_cb.py

@@ -182,14 +182,14 @@ class TestCarsonCBHeatpump(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_swing_mode("vertical")
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attribures(self):
         self.dps[UNKNOWN102_DPS] = True
         self.dps[TIMER_DPS] = 103
         self.dps[COUNTDOWN_DPS] = 105
         self.dps[UNKNOWN106_DPS] = 106
         self.dps[UNKNOWN110_DPS] = 110
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_102": True,
                 "timer": 103,

+ 3 - 3
tests/devices/test_deta_fan.py

@@ -55,10 +55,10 @@ class TestDetaFan(
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 2}):
             await self.subject.async_set_percentage(55)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
-        self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
+        self.assertEqual(self.subject.extra_state_attributes, {"timer": 5})
 
     def test_basic_light_state_attributes(self):
         self.dps[LIGHT_TIMER_DPS] = "6"
-        self.assertEqual(self.basicLight.device_state_attributes, {"timer": 6})
+        self.assertEqual(self.basicLight.extra_state_attributes, {"timer": 6})

+ 101 - 0
tests/devices/test_digoo_dgsp202.py

@@ -0,0 +1,101 @@
+"""Tests for Digoo DSSP202 dual switch with timers and energy monitoring"""
+from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.const import (
+    DEVICE_CLASS_CURRENT,
+    DEVICE_CLASS_POWER,
+    DEVICE_CLASS_VOLTAGE,
+    ELECTRIC_CURRENT_MILLIAMPERE,
+    ELECTRIC_POTENTIAL_VOLT,
+    POWER_WATT,
+)
+
+from ..const import DIGOO_DGSP202_SOCKET_PAYLOAD
+from ..mixins.number import MultiNumberTests
+from ..mixins.sensor import MultiSensorTests
+from ..mixins.switch import MultiSwitchTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH1_DPS = "1"
+SWITCH2_DPS = "2"
+TIMER1_DPS = "9"
+TIMER2_DPS = "10"
+CURRENT_DPS = "18"
+POWER_DPS = "19"
+VOLTAGE_DPS = "20"
+
+
+class TestDigooDGSP202Switch(
+    MultiNumberTests, MultiSensorTests, MultiSwitchTests, TuyaDeviceTestCase
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("digoo_dgsp202.yaml", DIGOO_DGSP202_SOCKET_PAYLOAD)
+        self.setUpMultiSwitch(
+            [
+                {
+                    "dps": SWITCH1_DPS,
+                    "name": "switch_outlet_1",
+                    "device_class": DEVICE_CLASS_OUTLET,
+                    "power_dps": POWER_DPS,
+                    "power_scale": 10,
+                },
+                {
+                    "dps": SWITCH2_DPS,
+                    "name": "switch_outlet_2",
+                    "device_class": DEVICE_CLASS_OUTLET,
+                },
+            ]
+        )
+        self.setUpMultiNumber(
+            [
+                {
+                    "dps": TIMER1_DPS,
+                    "name": "number_timer_1",
+                    "max": 1440,
+                    "scale": 60,
+                },
+                {
+                    "dps": TIMER2_DPS,
+                    "name": "number_timer_2",
+                    "max": 1440,
+                    "scale": 60,
+                },
+            ]
+        )
+        self.setUpMultiSensors(
+            [
+                {
+                    "name": "sensor_voltage",
+                    "dps": VOLTAGE_DPS,
+                    "unit": ELECTRIC_POTENTIAL_VOLT,
+                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "state_class": "measurement",
+                    "testdata": (2300, 230.0),
+                },
+                {
+                    "name": "sensor_current",
+                    "dps": CURRENT_DPS,
+                    "unit": ELECTRIC_CURRENT_MILLIAMPERE,
+                    "device_class": DEVICE_CLASS_CURRENT,
+                    "state_class": "measurement",
+                },
+                {
+                    "name": "sensor_power",
+                    "dps": POWER_DPS,
+                    "unit": POWER_WATT,
+                    "device_class": DEVICE_CLASS_POWER,
+                    "state_class": "measurement",
+                    "testdata": (1234, 123.4),
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "number_timer_1",
+                "number_timer_2",
+                "sensor_voltage",
+                "sensor_current",
+                "sensor_power",
+            ]
+        )

+ 5 - 5
tests/devices/test_eanons_humidifier.py

@@ -253,12 +253,12 @@ class TestEanonsHumidifier(
             await self.subject.async_set_mode(MODE_NORMAL)
             self.subject._device.anticipate_property_value.assert_not_called()
 
-    def test_climate_device_state_attributes(self):
+    def test_climate_extra_state_attributes(self):
         self.dps[ERROR_DPS] = 0
         self.dps[TIMERHR_DPS] = "cancel"
         self.dps[TIMER_DPS] = 0
         self.assertDictEqual(
-            self.climate.device_state_attributes,
+            self.climate.extra_state_attributes,
             {
                 "error": "OK",
                 "timer_hr": "cancel",
@@ -270,7 +270,7 @@ class TestEanonsHumidifier(
         self.dps[TIMERHR_DPS] = "1"
         self.dps[TIMER_DPS] = 60
         self.assertDictEqual(
-            self.climate.device_state_attributes,
+            self.climate.extra_state_attributes,
             {
                 "error": "Water Level Low",
                 "timer_hr": "1",
@@ -278,7 +278,7 @@ class TestEanonsHumidifier(
             },
         )
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = 0
         self.dps[TIMERHR_DPS] = "cancel"
         self.dps[TIMER_DPS] = 0
@@ -286,7 +286,7 @@ class TestEanonsHumidifier(
         self.dps[FANMODE_DPS] = "middle"
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "error": "OK",
                 "timer_hr": "cancel",

+ 2 - 2
tests/devices/test_eberg_qubo_q40hd_heatpump.py

@@ -286,10 +286,10 @@ class TestEbergQuboQ40HDHeatpump(
         self.dps[POWER_DPS] = False
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = 22
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "timer": 22,
             },

+ 2 - 2
tests/devices/test_electriq_12wminv_heatpump.py

@@ -250,7 +250,7 @@ class TestElectriq12WMINVHeatpump(
         ):
             await self.subject.async_set_swing_mode("vertical")
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attribures(self):
         self.dps[UNKNOWN8_DPS] = True
         self.dps[UNKNOWN12_DPS] = False
         self.dps[UNKNOWN102_DPS] = True
@@ -259,7 +259,7 @@ class TestElectriq12WMINVHeatpump(
         self.dps[UNKNOWN109_DPS] = 109
         self.dps[UNKNOWN110_DPS] = 110
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_8": True,
                 "unknown_12": False,

+ 2 - 2
tests/devices/test_electriq_cd12_dehumidifier.py

@@ -126,10 +126,10 @@ class TestElectriqCD20ProDehumidifier(
             await self.subject.async_set_mode("Air clean")
             self.subject._device.anticipate_property_value.assert_not_called()
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[CURRENTHUMID_DPS] = 50
         self.dps[CURRENTTEMP_DPS] = 21
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"current_humidity": 50, "current_temperature": 21},
         )

+ 3 - 3
tests/devices/test_electriq_cd20_dehumidifier.py

@@ -229,12 +229,12 @@ class TestElectriqCD20ProDehumidifier(
             await self.fan.async_set_preset_mode("Oscillate")
             self.subject._device.anticipate_property_value.assert_not_called()
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[CURRENTHUMID_DPS] = 50
         self.dps[CURRENTTEMP_DPS] = 21
         self.dps[ANION_DPS] = True
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"current_humidity": 50, "current_temperature": 21, "anion": True},
         )
-        self.assertEqual(self.fan.device_state_attributes, {})
+        self.assertEqual(self.fan.extra_state_attributes, {})

+ 3 - 3
tests/devices/test_electriq_cd25_dehumidifier.py

@@ -217,11 +217,11 @@ class TestElectriqCD25ProDehumidifier(
             await self.fan.async_set_preset_mode("Oscillate")
             self.subject._device.anticipate_property_value.assert_not_called()
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[CURRENTHUMID_DPS] = 50
         self.dps[CURRENTTEMP_DPS] = 21
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"current_humidity": 50, "current_temperature": 21},
         )
-        self.assertEqual(self.fan.device_state_attributes, {})
+        self.assertEqual(self.fan.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_eurom_600_heater.py

@@ -91,6 +91,6 @@ class TestEurom600Heater(
         # There are currently no known error states; update this as
         # they are discovered
         self.dps[ERROR_DPS] = "something"
-        self.assertEqual(self.subject.device_state_attributes, {"error": "something"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "something"})
         self.dps[ERROR_DPS] = "0"
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})

+ 2 - 2
tests/devices/test_eurom_601_heater.py

@@ -116,9 +116,9 @@ class TestEurom601Heater(
         ):
             await self.subject.async_set_preset_mode(PRESET_COMFORT)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = 13
         self.assertCountEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": 13},
         )

+ 2 - 2
tests/devices/test_eurom_walldesignheat2000_heater.py

@@ -173,5 +173,5 @@ class TestEuromWallDesignheat2000Heater(
         ):
             await self.subject.async_set_swing_mode(SWING_OFF)
 
-    def test_device_state_attributes(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
+    def test_extra_state_attributes(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_fersk_vind_2_climate.py

@@ -199,7 +199,7 @@ class TestFerskVind2Climate(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_swing_mode(SWING_OFF)
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN101_DPS] = True
         self.dps[UNKNOWN102_DPS] = False
         self.dps[TIMER_DPS] = 103
@@ -208,7 +208,7 @@ class TestFerskVind2Climate(TargetTemperatureTests, TuyaDeviceTestCase):
         self.dps[UNKNOWN109_DPS] = True
         self.dps[UNKNOWN110_DPS] = 110
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_101": True,
                 "unknown_102": False,

+ 2 - 2
tests/devices/test_garage_door_opener.py

@@ -85,5 +85,5 @@ class TestSimpleGarageOpener(TuyaDeviceTestCase):
         with self.assertRaises(NotImplementedError):
             await self.subject.async_stop_cover()
 
-    def test_device_state_attributes(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
+    def test_extra_state_attributes(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_gardenpac_heatpump.py

@@ -151,14 +151,14 @@ class TestGardenPACPoolHeatpump(
         self.dps[HVACMODE_DPS] = False
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[POWERLEVEL_DPS] = 50
         self.dps[UNKNOWN107_DPS] = 1
         self.dps[UNKNOWN108_DPS] = 2
         self.dps[UNKNOWN115_DPS] = 3
         self.dps[UNKNOWN116_DPS] = 4
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "power_level": 50,
                 "unknown_107": 1,

+ 4 - 4
tests/devices/test_goldair_dehumidifier.py

@@ -459,13 +459,13 @@ class TestGoldairDehumidifier(
         ):
             await self.fan.async_set_percentage(30)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = None
         self.dps[DEFROST_DPS] = False
         self.dps[AIRCLEAN_DPS] = False
         self.dps[UNKNOWN101_DPS] = False
         self.assertDictEqual(
-            self.climate.device_state_attributes,
+            self.climate.extra_state_attributes,
             {
                 "error": None,
                 "defrosting": False,
@@ -479,7 +479,7 @@ class TestGoldairDehumidifier(
         self.dps[AIRCLEAN_DPS] = True
         self.dps[UNKNOWN101_DPS] = True
         self.assertDictEqual(
-            self.climate.device_state_attributes,
+            self.climate.extra_state_attributes,
             {
                 "error": ERROR_TANK,
                 "defrosting": True,
@@ -512,7 +512,7 @@ class TestGoldairDehumidifier(
         self.assertEqual(self.light.is_on, False)
 
     def test_light_state_attributes(self):
-        self.assertEqual(self.light.device_state_attributes, {})
+        self.assertEqual(self.light.extra_state_attributes, {})
 
     async def test_light_turn_on(self):
         async with assert_device_properties_set(

+ 3 - 3
tests/devices/test_goldair_fan.py

@@ -318,10 +318,10 @@ class TestGoldairFan(BasicLightTests, SwitchableTests, TuyaDeviceTestCase):
         ):
             await self.climate.async_set_fan_mode("medium")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
-        self.assertEqual(self.climate.device_state_attributes, {"timer": "5"})
-        self.assertEqual(self.subject.device_state_attributes, {"timer": "5"})
+        self.assertEqual(self.climate.extra_state_attributes, {"timer": "5"})
+        self.assertEqual(self.subject.extra_state_attributes, {"timer": "5"})
 
     def test_light_icon(self):
         self.dps[LIGHT_DPS] = True

+ 3 - 3
tests/devices/test_goldair_geco_heater.py

@@ -103,17 +103,17 @@ class TestGoldairGECOHeater(
         ):
             await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         # There are currently no known error states; update this as
         # they are discovered
         self.dps[ERROR_DPS] = "something"
         self.dps[TIMER_DPS] = 10
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "something", "timer": 10},
         )
         self.dps[ERROR_DPS] = "0"
         self.dps[TIMER_DPS] = 0
         self.assertDictEqual(
-            self.subject.device_state_attributes, {"error": "OK", "timer": 0}
+            self.subject.extra_state_attributes, {"error": "OK", "timer": 0}
         )

+ 3 - 3
tests/devices/test_goldair_gpcv_heater.py

@@ -140,17 +140,17 @@ class TestGoldairGPCVHeater(
         ):
             await self.subject.async_set_preset_mode("High")
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         # There are currently no known error states; update this as
         # they are discovered
         self.dps[ERROR_DPS] = "something"
         self.dps[TIMER_DPS] = 10
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "something", "timer": 10},
         )
         self.dps[ERROR_DPS] = "0"
         self.dps[TIMER_DPS] = 0
         self.assertDictEqual(
-            self.subject.device_state_attributes, {"error": "OK", "timer": 0}
+            self.subject.extra_state_attributes, {"error": "OK", "timer": 0}
         )

+ 2 - 2
tests/devices/test_goldair_gpph_heater.py

@@ -307,14 +307,14 @@ class TestGoldairHeater(
         ):
             await self.subject.async_set_swing_mode("3")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = "something"
         self.dps[TIMER_DPS] = 5
         self.dps[TIMERACT_DPS] = True
         self.dps[POWERLEVEL_DPS] = 4
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "error": "something",
                 "timer": 5,

+ 3 - 3
tests/devices/test_grid_connect_double_power_point.py

@@ -170,7 +170,7 @@ class TestGridConnectDoubleSwitch(
         self.dps[CALIBW_DPS] = 24
         self.dps[CALIBE_DPS] = 25
         self.assertDictEqual(
-            self.multiSwitch["switch_master"].device_state_attributes,
+            self.multiSwitch["switch_master"].extra_state_attributes,
             {
                 "current_a": 1.234,
                 "voltage_v": 235.0,
@@ -183,13 +183,13 @@ class TestGridConnectDoubleSwitch(
             },
         )
         self.assertDictEqual(
-            self.multiSwitch["switch_outlet_1"].device_state_attributes,
+            self.multiSwitch["switch_outlet_1"].extra_state_attributes,
             {
                 "countdown": 9,
             },
         )
         self.assertDictEqual(
-            self.multiSwitch["switch_outlet_2"].device_state_attributes,
+            self.multiSwitch["switch_outlet_2"].extra_state_attributes,
             {
                 "countdown": 10,
             },

+ 2 - 2
tests/devices/test_hellnar_heatpump.py

@@ -129,7 +129,7 @@ class TestHellnarHeatpump(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps["5"] = "fan?"
         self.dps["18"] = 18
         self.dps["20"] = 20
@@ -150,7 +150,7 @@ class TestHellnarHeatpump(TargetTemperatureTests, TuyaDeviceTestCase):
         self.dps["134"] = "unknown134"
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "maybe_fan_mode": "fan?",
                 "unknown_18": 18,

+ 2 - 2
tests/devices/test_inkbird_itc306a_thermostat.py

@@ -280,7 +280,7 @@ class TestInkbirdThermostat(
         self.dps[SWITCH_DPS] = True
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[ERROR_DPS] = 1
         self.dps[CALIBRATE_DPS] = 1
         self.dps[TIME_THRES_DPS] = 5
@@ -296,7 +296,7 @@ class TestInkbirdThermostat(
         self.dps[UNKNOWN120_DPS] = False
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "error": 1,
                 "temperature_calibration_offset": 0.1,

+ 3 - 3
tests/devices/test_kogan_dehumidifier.py

@@ -222,13 +222,13 @@ class TestKoganDehumidifier(
             await self.fan.async_oscillate(False)
             self.subject._device.anticipate_property_value.assert_not_called()
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[CURRENTHUMID_DPS] = 55
         self.dps[ERROR_DPS] = 1
         self.dps[TIMER_DPS] = 3
         self.dps[COUNTDOWN_DPS] = 160
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "current_humidity": 55,
                 "error": "Tank full",
@@ -236,4 +236,4 @@ class TestKoganDehumidifier(
                 "timer": 160,
             },
         )
-        self.assertEqual(self.fan.device_state_attributes, {})
+        self.assertEqual(self.fan.extra_state_attributes, {})

+ 2 - 2
tests/devices/test_kogan_kahtp_heater.py

@@ -125,9 +125,9 @@ class TestGoldairKoganKAHTPHeater(
         ):
             await self.subject.async_set_preset_mode("High")
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = 10
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"timer": 10},
         )

+ 4 - 4
tests/devices/test_kogan_kashmfp20ba_heater.py

@@ -126,10 +126,10 @@ class TestKoganKASHMF20BAHeater(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_preset_mode("high")
 
-    def test_device_state_attribures(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
-        self.assertEqual(self.backlight.device_state_attributes, {})
-        self.assertEqual(self.flame.device_state_attributes, {})
+    def test_extra_state_attributes(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})
+        self.assertEqual(self.backlight.extra_state_attributes, {})
+        self.assertEqual(self.flame.extra_state_attributes, {})
 
     def test_lighting_supported_color_modes(self):
         self.assertCountEqual(self.backlight.supported_color_modes, [])

+ 2 - 2
tests/devices/test_kogan_kawfhtp_heater.py

@@ -128,6 +128,6 @@ class TestGoldairKoganKAHTPHeater(
         ):
             await self.subject.async_set_preset_mode("High")
 
-    def test_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = 10
-        self.assertDictEqual(self.subject.device_state_attributes, {"timer": 10})
+        self.assertDictEqual(self.subject.extra_state_attributes, {"timer": 10})

+ 2 - 2
tests/devices/test_kogan_kawfpac09ya_airconditioner.py

@@ -145,12 +145,12 @@ class TestKoganKAWFPAC09YA(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_fan_mode("high")
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[COUNTDOWN_DPS] = 105
         self.dps[UNKNOWN106_DPS] = 106
         self.dps[UNKNOWN107_DPS] = True
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "countdown": 105,
                 "unknown_106": 106,

+ 2 - 2
tests/devices/test_lexy_f501_fan.py

@@ -146,9 +146,9 @@ class TestLexyF501Fan(
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 12}):
             await self.subject.async_set_percentage(78)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
-        self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
+        self.assertEqual(self.subject.extra_state_attributes, {"timer": 5})
 
     def test_icons(self):
         self.dps[LIGHT_DPS] = True

+ 2 - 2
tests/devices/test_madimack_elitev3_heatpump.py

@@ -247,13 +247,13 @@ class TestMadimackEliteV3Heatpump(
         ):
             await self.subject.async_set_preset_mode("Power")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN15_DPS] = 15
         self.dps[UNKNOWN101_DPS] = 101
         self.dps[UNKNOWN107_DPS] = True
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_15": 15,
                 "unknown_101": 101,

+ 2 - 2
tests/devices/test_madimack_heatpump.py

@@ -165,7 +165,7 @@ class TestMadimackPoolHeatpump(
         self.dps[HVACMODE_DPS] = False
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[POWERLEVEL_DPS] = 50
         self.dps[UNKNOWN107_DPS] = 1
         self.dps[UNKNOWN108_DPS] = 2
@@ -187,7 +187,7 @@ class TestMadimackPoolHeatpump(
         self.dps[UNKNOWN139_DPS] = True
         self.dps[UNKNOWN140_DPS] = "test"
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "power_level": 50,
                 "unknown_107": 1,

+ 2 - 2
tests/devices/test_minco_mh1823d_thermostat.py

@@ -317,14 +317,14 @@ class TestMincoMH1823DThermostat(
         self.dps[HVACMODE_DPS] = False
         self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN12_DPS] = False
         self.dps[UNKNOWN32_DPS] = 32
         self.dps[UNKNOWN45_DPS] = 45
         self.dps[UNKNOWN105_DPS] = "unknown 105"
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_12": False,
                 "unknown_32": 32,

+ 2 - 2
tests/devices/test_moes_bht002_thermostat.py

@@ -103,11 +103,11 @@ class TestMoesBHT002Thermostat(
             ],
         )
 
-    def test_device_state_attribures(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN104_DPS] = False
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"unknown_104": False},
         )
 

+ 2 - 2
tests/devices/test_nedis_htpl20f_heater.py

@@ -128,11 +128,11 @@ class TestNedisHtpl20fHeater(
         ):
             await self.subject.async_set_preset_mode(PRESET_AWAY)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN11_DPS] = "11"
         self.dps[UNKNOWN101_DPS] = True
 
         self.assertCountEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"unknown_11": "11", "unknown_101": True},
         )

+ 3 - 3
tests/devices/test_poolex_silverline_heatpump.py

@@ -161,15 +161,15 @@ class TestPoolexSilverlineHeatpump(
 
     def test_error_state(self):
         self.dps[ERROR_DPS] = 0
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})
 
         self.dps[ERROR_DPS] = 256
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "Water Flow Protection"},
         )
         self.dps[ERROR_DPS] = 2
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": 2},
         )

+ 3 - 3
tests/devices/test_poolex_vertigo_heatpump.py

@@ -150,15 +150,15 @@ class TestPoolexVertigoHeatpump(
 
     def test_error_state(self):
         self.dps[ERROR_DPS] = 0
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})
 
         self.dps[ERROR_DPS] = 4
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "Water Flow Protection"},
         )
         self.dps[ERROR_DPS] = 2
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": 2},
         )

+ 1 - 1
tests/devices/test_purline_m100_heater.py

@@ -199,7 +199,7 @@ class TestPulineM100Heater(
         self.assertFalse(self.light.is_on)
 
     def test_light_state_attributes(self):
-        self.assertEqual(self.light.device_state_attributes, {})
+        self.assertEqual(self.light.extra_state_attributes, {})
 
     async def test_light_turn_on(self):
         async with assert_device_properties_set(

+ 3 - 3
tests/devices/test_remora_heatpump.py

@@ -181,15 +181,15 @@ class TestRemoraHeatpump(
 
     def test_error_state(self):
         self.dps[ERROR_DPS] = 0
-        self.assertEqual(self.subject.device_state_attributes, {"error": "OK"})
+        self.assertEqual(self.subject.extra_state_attributes, {"error": "OK"})
 
         self.dps[ERROR_DPS] = 1
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": "Water Flow Protection"},
         )
         self.dps[ERROR_DPS] = 2
         self.assertEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"error": 2},
         )

+ 3 - 2
tests/devices/test_renpho_rp_ap001s.py

@@ -123,7 +123,7 @@ class TestRenphoPurifier(
         ):
             await self.subject.async_set_preset_mode("auto")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "19"
         self.dps[QUALITY_DPS] = "22"
         self.dps[PREFILTER_DPS] = 102
@@ -132,7 +132,7 @@ class TestRenphoPurifier(
         self.dps[HEPA_DPS] = 105
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "timer": "19",
                 "air_quality": "22",
@@ -143,4 +143,5 @@ class TestRenphoPurifier(
             },
         )
 
+    def test_icons(self):
         self.assertEqual(self.basicSwitch.icon, "mdi:power-sleep")

+ 2 - 2
tests/devices/test_saswell_c16_thermostat.py

@@ -219,7 +219,7 @@ class TestSaswellC16Thermostat(
         ):
             await self.subject.async_set_preset_mode("manual")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN4_DPS] = 4
         self.dps[FLOORTEMPLIMIT_DPS] = 355
         self.dps[INSTALL_DPS] = True
@@ -235,7 +235,7 @@ class TestSaswellC16Thermostat(
         self.dps[UNKNOWN26_DPS] = 26
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_4": 4,
                 "floor_temp_limit": 35.5,

+ 2 - 2
tests/devices/test_saswell_t29utk_thermostat.py

@@ -247,7 +247,7 @@ class TestSaswellT29UTKThermostat(
         ):
             await self.subject.async_set_preset_mode("Program")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[POWER_DPS] = True
         self.dps[CONFIG_DPS] = "2"
         self.dps[UNKNOWN113_DPS] = 113
@@ -257,7 +257,7 @@ class TestSaswellT29UTKThermostat(
         self.dps[CURTEMPF_DPS] = 117
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "power": True,
                 "configuration": "heating",

+ 32 - 0
tests/devices/test_simple_switch_with_timer.py

@@ -0,0 +1,32 @@
+"""Tests for a simple switch with timer"""
+from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+
+from ..const import TIMED_SOCKET_PAYLOAD
+from ..mixins.number import BasicNumberTests
+from ..mixins.switch import SwitchableTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH_DPS = "1"
+TIMER_DPS = "11"
+
+
+class TestTimedSwitch(BasicNumberTests, SwitchableTests, TuyaDeviceTestCase):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("simple_switch_timer.yaml", TIMED_SOCKET_PAYLOAD)
+        self.subject = self.entities.get("switch")
+        self.setUpSwitchable(SWITCH_DPS, self.subject)
+        self.setUpBasicNumber(
+            TIMER_DPS, self.entities.get("number_timer"), max=1440, scale=60
+        )
+        self.mark_secondary(["number_timer"])
+
+    def test_device_class_is_outlet(self):
+        self.assertEqual(self.subject.device_class, DEVICE_CLASS_OUTLET)
+
+    def test_extra_state_attributes_set(self):
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {},
+        )

+ 2 - 2
tests/devices/test_smartplugv1.py

@@ -75,13 +75,13 @@ class TestKoganSwitch(
         self.dps[POWER_DPS] = 1234
         self.assertEqual(self.subject.current_power_w, 123.4)
 
-    def test_device_state_attributes_set(self):
+    def test_extra_state_attributes_set(self):
         self.dps[TIMER_DPS] = 1
         self.dps[VOLTAGE_DPS] = 2350
         self.dps[CURRENT_DPS] = 1234
         self.dps[POWER_DPS] = 5678
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "timer": 1,
                 "current_a": 1.234,

+ 2 - 2
tests/devices/test_smartplugv2.py

@@ -75,13 +75,13 @@ class TestSwitchV2(
         self.dps[POWER_DPS] = 1234
         self.assertEqual(self.subject.current_power_w, 123.4)
 
-    def test_device_state_attributes_set(self):
+    def test_extra_state_attributes_set(self):
         self.dps[TIMER_DPS] = 1
         self.dps[VOLTAGE_DPS] = 2350
         self.dps[CURRENT_DPS] = 1234
         self.dps[POWER_DPS] = 5678
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "timer": 1,
                 "current_a": 1.234,

+ 1 - 1
tests/devices/test_smartplugv2_energy.py

@@ -137,7 +137,7 @@ class TestSwitchV2Energy(
         self.dps[RANDOM_DPS] = "3C4D"
 
         self.assertDictEqual(
-            self.multiSwitch["switch"].device_state_attributes,
+            self.multiSwitch["switch"].extra_state_attributes,
             {
                 "test_bit": 21,
                 "voltage_calibration": 22,

+ 3 - 3
tests/devices/test_stirling_fs140dc_fan.py

@@ -110,9 +110,9 @@ class TestStirlingFS1Fan(SwitchableTests, TuyaDeviceTestCase):
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 10}):
             await self.subject.async_set_percentage(64)
 
-    def test_device_state_attributes(self):
-        self.assertEqual(self.subject.device_state_attributes, {})
-        self.assertEqual(self.timer.device_state_attributes, {})
+    def test_extra_state_attributes(self):
+        self.assertEqual(self.subject.extra_state_attributes, {})
+        self.assertEqual(self.timer.extra_state_attributes, {})
 
     def test_timer_options(self):
         self.assertCountEqual(

+ 2 - 2
tests/devices/test_tadiran_wind_heatpump.py

@@ -158,7 +158,7 @@ class TestTadiranWindHeatpump(TargetTemperatureTests, TuyaDeviceTestCase):
         ):
             await self.subject.async_set_fan_mode("auto")
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps["101"] = 101
         self.dps["102"] = 102
         self.dps["103"] = 103
@@ -169,7 +169,7 @@ class TestTadiranWindHeatpump(TargetTemperatureTests, TuyaDeviceTestCase):
         self.dps["108"] = False
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "unknown_101": 101,
                 "unknown_102": 102,

+ 2 - 2
tests/devices/test_tmwf02_fan.py

@@ -51,9 +51,9 @@ class TestTMWF02Fan(BasicNumberTests, SwitchableTests, TuyaDeviceTestCase):
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 25}):
             await self.subject.async_set_percentage(24.8)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[LEVEL_DPS] = "level_3"
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"fan_level": "level_3"},
         )

+ 2 - 2
tests/devices/test_wetair_wawh1210lw_humidifier.py

@@ -145,9 +145,9 @@ class TestWetairWAWH1210LWHumidifier(
         ):
             await self.subject.async_set_mode(MODE_SLEEP)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[UNKNOWN22_DPS] = 22
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {"unknown_22": 22},
         )

+ 2 - 2
tests/devices/test_wetair_wch750_heater.py

@@ -208,13 +208,13 @@ class TestWetairWCH750Heater(
         ):
             await self.subject.async_set_preset_mode(PRESET_AWAY)
 
-    def test_device_state_attributes(self):
+    def test_extra_state_attributes(self):
         self.dps[TIMER_DPS] = "1h"
         self.dps[COUNTDOWN_DPS] = 20
         self.dps[UNKNOWN21_DPS] = 21
 
         self.assertDictEqual(
-            self.subject.device_state_attributes,
+            self.subject.extra_state_attributes,
             {
                 "timer": "1h",
                 "countdown": 20,

+ 83 - 0
tests/devices/test_woox_r4028_powerstrip.py

@@ -0,0 +1,83 @@
+"""Tests for the Woox R4028 powerstrip."""
+from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+
+from ..const import WOOX_R4028_SOCKET_PAYLOAD
+from ..mixins.number import MultiNumberTests
+from ..mixins.switch import MultiSwitchTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH1_DPS = "1"
+SWITCH2_DPS = "2"
+SWITCH3_DPS = "3"
+SWITCHUSB_DPS = "7"
+TIMER1_DPS = "101"
+TIMER2_DPS = "102"
+TIMER3_DPS = "103"
+TIMERUSB_DPS = "105"
+
+
+class TestWooxR4028Powerstrip(
+    MultiNumberTests,
+    MultiSwitchTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("woox_r4028_powerstrip.yaml", WOOX_R4028_SOCKET_PAYLOAD)
+        self.setUpMultiSwitch(
+            [
+                {
+                    "dps": SWITCH1_DPS,
+                    "name": "switch_outlet_1",
+                    "device_class": DEVICE_CLASS_OUTLET,
+                },
+                {
+                    "dps": SWITCH2_DPS,
+                    "name": "switch_outlet_2",
+                    "device_class": DEVICE_CLASS_OUTLET,
+                },
+                {
+                    "dps": SWITCH3_DPS,
+                    "name": "switch_outlet_3",
+                    "device_class": DEVICE_CLASS_OUTLET,
+                },
+                {"dps": SWITCHUSB_DPS, "name": "switch_usb_switch"},
+            ]
+        )
+        self.setUpMultiNumber(
+            [
+                {
+                    "dps": TIMER1_DPS,
+                    "name": "number_timer_1",
+                    "max": 1440,
+                    "scale": 60,
+                },
+                {
+                    "dps": TIMER2_DPS,
+                    "name": "number_timer_2",
+                    "max": 1440,
+                    "scale": 60,
+                },
+                {
+                    "dps": TIMER3_DPS,
+                    "name": "number_timer_3",
+                    "max": 1440,
+                    "scale": 60,
+                },
+                {
+                    "dps": TIMERUSB_DPS,
+                    "name": "number_usb_timer",
+                    "max": 1440,
+                    "scale": 60,
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "number_timer_1",
+                "number_timer_2",
+                "number_timer_3",
+                "number_usb_timer",
+            ]
+        )

+ 4 - 4
tests/mixins/binary_sensor.py

@@ -24,8 +24,8 @@ class BasicBinarySensorTests:
         self.dps[self.basicBSensorDps] = offval
         self.assertFalse(self.basicBSensor.is_on)
 
-    def test_basic_bsensor_device_state_attributes(self):
-        self.assertEqual(self.basicBSensor.device_state_attributes, {})
+    def test_basic_bsensor_extra_state_attributes(self):
+        self.assertEqual(self.basicBSensor.extra_state_attributes, {})
 
 
 class MultiBinarySensorTests:
@@ -59,7 +59,7 @@ class MultiBinarySensorTests:
                 self.dps[dps] = offval
                 self.assertFalse(subject.is_on)
 
-    def test_multi_bsensor_device_state_attributes(self):
+    def test_multi_bsensor_extra_state_attributes(self):
         for key, subject in self.multiBSensor.items():
             with self.subTest(key):
-                self.assertEqual(subject.device_state_attributes, {})
+                self.assertEqual(subject.extra_state_attributes, {})

+ 2 - 2
tests/mixins/light.py

@@ -66,7 +66,7 @@ class BasicLightTests:
             await self.basicLight.async_toggle()
 
     def test_basic_light_state_attributes(self):
-        self.assertEqual(self.basicLight.device_state_attributes, {})
+        self.assertEqual(self.basicLight.extra_state_attributes, {})
 
 
 class DimmableLightTests:
@@ -92,7 +92,7 @@ class DimmableLightTests:
             self.assertEqual(self.dimmableLight.brightness, val)
 
     def test_dimmable_light_state_attributes(self):
-        self.assertEqual(self.dimmableLight.device_state_attributes, {})
+        self.assertEqual(self.dimmableLight.extra_state_attributes, {})
 
     async def test_dimmable_light_turn_off(self):
         async with assert_device_properties_set(

+ 1 - 1
tests/mixins/lock.py

@@ -45,4 +45,4 @@ class BasicLockTests:
             await self.basicLock.async_unlock()
 
     def test_basic_lock_state_attributes(self):
-        self.assertEqual(self.basicLock.device_state_attributes, {})
+        self.assertEqual(self.basicLock.extra_state_attributes, {})

+ 4 - 4
tests/mixins/number.py

@@ -38,8 +38,8 @@ class BasicNumberTests:
         ):
             await self.basicNumber.async_set_value(val)
 
-    def test_number_device_state_attributes(self):
-        self.assertEqual(self.basicNumber.device_state_attributes, {})
+    def test_number_extra_state_attributes(self):
+        self.assertEqual(self.basicNumber.extra_state_attributes, {})
 
 
 class MultiNumberTests:
@@ -109,7 +109,7 @@ class MultiNumberTests:
                 ):
                     await subject.async_set_value(val)
 
-    def test_multi_number_device_state_attributes(self):
+    def test_multi_number_extra_state_attributes(self):
         for key, subject in self.multiNumber.items():
             with self.subTest(key):
-                self.assertEqual(subject.device_state_attributes, {})
+                self.assertEqual(subject.extra_state_attributes, {})

+ 4 - 4
tests/mixins/select.py

@@ -26,8 +26,8 @@ class BasicSelectTests:
             ):
                 await self.basicSelect.async_select_option(val)
 
-    def test_basicSelect_device_state_attributes(self):
-        self.assertEqual(self.basicSelect.device_state_attributes, {})
+    def test_basicSelect_extra_state_attributes(self):
+        self.assertEqual(self.basicSelect.extra_state_attributes, {})
 
 
 class MultiSelectTests:
@@ -68,7 +68,7 @@ class MultiSelectTests:
                     ):
                         await subject.async_select_option(val)
 
-    def test_multiSelect_device_state_attributes(self):
+    def test_multiSelect_extra_state_attributes(self):
         for key, subject in self.multiSelect.items():
             with self.subTest(key):
-                self.assertEqual(subject.device_state_attributes, {})
+                self.assertEqual(subject.extra_state_attributes, {})

+ 2 - 2
tests/mixins/sensor.py

@@ -79,7 +79,7 @@ class MultiSensorTests:
                 self.dps[self.multiSensorDps[key]] = dpsval
                 self.assertEqual(subject.native_value, val)
 
-    def test_multi_sensor_device_state_attributes(self):
+    def test_multi_sensor_extra_state_attributes(self):
         for key, subject in self.multiSensor.items():
             with self.subTest(key):
-                self.assertEqual(subject.device_state_attributes, {})
+                self.assertEqual(subject.extra_state_attributes, {})

+ 4 - 4
tests/mixins/switch.py

@@ -109,11 +109,11 @@ class BasicSwitchTests:
 
     def test_basic_switch_state_attributes(self):
         if self.basicSwitchPowerDps is None:
-            self.assertEqual(self.basicSwitch.device_state_attributes, {})
+            self.assertEqual(self.basicSwitch.extra_state_attributes, {})
         else:
             self.dps[self.basicSwitchPowerDps] = 99 * self.basicSwitchPowerScale
             self.assertDictEqual(
-                self.basicSwitch.device_state_attributes, {"current_power_w": 99.0}
+                self.basicSwitch.extra_state_attributes, {"current_power_w": 99.0}
             )
 
 
@@ -203,10 +203,10 @@ class MultiSwitchTests:
             with self.subTest(key):
                 dp = self.multiSwitchPowerDps.get(key)
                 if dp is None:
-                    self.assertEqual(subject.device_state_attributes, {})
+                    self.assertEqual(subject.extra_state_attributes, {})
                 else:
                     self.dps[dp] = 987 * self.multiSwitchPowerScale.get(key, 1)
                     self.assertDictEqual(
-                        subject.device_state_attributes,
+                        subject.extra_state_attributes,
                         {"current_power_w": 987.0},
                     )