diff --git a/.coveragerc b/.coveragerc
index c05cab27f79ca19b1e80d4ebbe14d56dd39f39d9..e20b26ff182d4600cd19798df666688f5203f95c 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1371,11 +1371,6 @@ omit =
     homeassistant/components/telnet/switch.py
     homeassistant/components/temper/sensor.py
     homeassistant/components/tensorflow/image_processing.py
-    homeassistant/components/teslemetry/__init__.py
-    homeassistant/components/teslemetry/climate.py
-    homeassistant/components/teslemetry/coordinator.py
-    homeassistant/components/teslemetry/entity.py
-    homeassistant/components/teslemetry/context.py
     homeassistant/components/tfiac/climate.py
     homeassistant/components/thermoworks_smoke/sensor.py
     homeassistant/components/thethingsnetwork/*
diff --git a/homeassistant/components/teslemetry/__init__.py b/homeassistant/components/teslemetry/__init__.py
index 0c2a16fa15b855b161b8914e5845fd21a3c578bf..fb74e905181dc7342ef81c9888f1832a7683aced 100644
--- a/homeassistant/components/teslemetry/__init__.py
+++ b/homeassistant/components/teslemetry/__init__.py
@@ -2,7 +2,7 @@
 import asyncio
 from typing import Final
 
-from tesla_fleet_api import Teslemetry
+from tesla_fleet_api import Teslemetry, VehicleSpecific
 from tesla_fleet_api.exceptions import InvalidToken, PaymentRequired, TeslaFleetError
 
 from homeassistant.config_entries import ConfigEntry
@@ -48,7 +48,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
             continue
         vin = product["vin"]
 
-        api = teslemetry.vehicle.specific(vin)
+        api = VehicleSpecific(teslemetry.vehicle, vin)
         coordinator = TeslemetryVehicleDataCoordinator(hass, api)
         data.append(
             TeslemetryVehicleData(
diff --git a/homeassistant/components/teslemetry/context.py b/homeassistant/components/teslemetry/context.py
index c2c9317f671fd14fff0a51bbc3e66a2bf11242f1..942f1ccdd4bdcfbb2f6f6c22c881c677df3a2551 100644
--- a/homeassistant/components/teslemetry/context.py
+++ b/homeassistant/components/teslemetry/context.py
@@ -13,4 +13,4 @@ def handle_command():
     try:
         yield
     except TeslaFleetError as e:
-        raise HomeAssistantError from e
+        raise HomeAssistantError("Teslemetry command failed") from e
diff --git a/tests/components/teslemetry/__init__.py b/tests/components/teslemetry/__init__.py
index 422a2ecaac97ea7618d7d8f3552136cba10e2ba6..eae58127d1d0d1bdaaf7109c40d28b008a65bd7e 100644
--- a/tests/components/teslemetry/__init__.py
+++ b/tests/components/teslemetry/__init__.py
@@ -1 +1,50 @@
 """Tests for the Teslemetry integration."""
+
+from unittest.mock import patch
+
+from syrupy import SnapshotAssertion
+
+from homeassistant.components.teslemetry.const import DOMAIN
+from homeassistant.const import Platform
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers import entity_registry as er
+
+from .const import CONFIG
+
+from tests.common import MockConfigEntry
+
+
+async def setup_platform(hass: HomeAssistant, platforms: list[Platform] | None = None):
+    """Set up the Teslemetry platform."""
+
+    mock_entry = MockConfigEntry(
+        domain=DOMAIN,
+        data=CONFIG,
+    )
+    mock_entry.add_to_hass(hass)
+
+    if platforms is None:
+        await hass.config_entries.async_setup(mock_entry.entry_id)
+        await hass.async_block_till_done()
+    else:
+        with patch("homeassistant.components.teslemetry.PLATFORMS", platforms):
+            await hass.config_entries.async_setup(mock_entry.entry_id)
+            await hass.async_block_till_done()
+
+    return mock_entry
+
+
+def assert_entities(
+    hass: HomeAssistant,
+    entry_id: str,
+    entity_registry: er.EntityRegistry,
+    snapshot: SnapshotAssertion,
+) -> None:
+    """Test that all entities match their snapshot."""
+    entity_entries = er.async_entries_for_config_entry(entity_registry, entry_id)
+
+    assert entity_entries
+    for entity_entry in entity_entries:
+        assert entity_entry == snapshot(name=f"{entity_entry.entity_id}-entry")
+        assert (state := hass.states.get(entity_entry.entity_id))
+        assert state == snapshot(name=f"{entity_entry.entity_id}-state")
diff --git a/tests/components/teslemetry/conftest.py b/tests/components/teslemetry/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fc279eaa215a023edc4848d98db94b371746f77
--- /dev/null
+++ b/tests/components/teslemetry/conftest.py
@@ -0,0 +1,47 @@
+"""Fixtures for Tessie."""
+from __future__ import annotations
+
+from unittest.mock import patch
+
+import pytest
+
+from .const import PRODUCTS, RESPONSE_OK, VEHICLE_DATA, WAKE_UP_ONLINE
+
+
+@pytest.fixture(autouse=True)
+def mock_products():
+    """Mock Tesla Fleet Api products method."""
+    with patch(
+        "homeassistant.components.teslemetry.Teslemetry.products", return_value=PRODUCTS
+    ) as mock_products:
+        yield mock_products
+
+
+@pytest.fixture(autouse=True)
+def mock_vehicle_data():
+    """Mock Tesla Fleet API Vehicle Specific vehicle_data method."""
+    with patch(
+        "homeassistant.components.teslemetry.VehicleSpecific.vehicle_data",
+        return_value=VEHICLE_DATA,
+    ) as mock_vehicle_data:
+        yield mock_vehicle_data
+
+
+@pytest.fixture(autouse=True)
+def mock_wake_up():
+    """Mock Tesla Fleet API Vehicle Specific wake_up method."""
+    with patch(
+        "homeassistant.components.teslemetry.VehicleSpecific.wake_up",
+        return_value=WAKE_UP_ONLINE,
+    ) as mock_wake_up:
+        yield mock_wake_up
+
+
+@pytest.fixture(autouse=True)
+def mock_request():
+    """Mock Tesla Fleet API Vehicle Specific class."""
+    with patch(
+        "homeassistant.components.teslemetry.Teslemetry._request",
+        return_value=RESPONSE_OK,
+    ) as mock_request:
+        yield mock_request
diff --git a/tests/components/teslemetry/const.py b/tests/components/teslemetry/const.py
index 527ef98efcadc09fc66808934fffc569671596a8..0feb056fa7235408ddfb672e88b94ac49cc82187 100644
--- a/tests/components/teslemetry/const.py
+++ b/tests/components/teslemetry/const.py
@@ -1,5 +1,16 @@
 """Constants for the teslemetry tests."""
 
+from homeassistant.components.teslemetry.const import DOMAIN, TeslemetryState
 from homeassistant.const import CONF_ACCESS_TOKEN
 
+from tests.common import load_json_object_fixture
+
 CONFIG = {CONF_ACCESS_TOKEN: "1234567890"}
+
+WAKE_UP_ONLINE = {"response": {"state": TeslemetryState.ONLINE}, "error": None}
+WAKE_UP_ASLEEP = {"response": {"state": TeslemetryState.ASLEEP}, "error": None}
+
+PRODUCTS = load_json_object_fixture("products.json", DOMAIN)
+VEHICLE_DATA = load_json_object_fixture("vehicle_data.json", DOMAIN)
+
+RESPONSE_OK = {"response": {}, "error": None}
diff --git a/tests/components/teslemetry/fixtures/products.json b/tests/components/teslemetry/fixtures/products.json
new file mode 100644
index 0000000000000000000000000000000000000000..430c3b39dc8f38511a87145970621ac461f5b37d
--- /dev/null
+++ b/tests/components/teslemetry/fixtures/products.json
@@ -0,0 +1,99 @@
+{
+  "response": [
+    {
+      "id": 1234,
+      "user_id": 1234,
+      "vehicle_id": 1234,
+      "vin": "VINVINVIN",
+      "color": null,
+      "access_type": "OWNER",
+      "display_name": "Test",
+      "option_codes": null,
+      "cached_data": null,
+      "granular_access": { "hide_private": false },
+      "tokens": ["abc", "def"],
+      "state": "asleep",
+      "in_service": false,
+      "id_s": "1234",
+      "calendar_enabled": true,
+      "api_version": 71,
+      "backseat_token": null,
+      "backseat_token_updated_at": null,
+      "ble_autopair_enrolled": false,
+      "vehicle_config": {
+        "aux_park_lamps": "Eu",
+        "badge_version": 1,
+        "can_accept_navigation_requests": true,
+        "can_actuate_trunks": true,
+        "car_special_type": "base",
+        "car_type": "model3",
+        "charge_port_type": "CCS",
+        "cop_user_set_temp_supported": false,
+        "dashcam_clip_save_supported": true,
+        "default_charge_to_max": false,
+        "driver_assist": "TeslaAP3",
+        "ece_restrictions": false,
+        "efficiency_package": "M32021",
+        "eu_vehicle": true,
+        "exterior_color": "DeepBlue",
+        "exterior_trim": "Black",
+        "exterior_trim_override": "",
+        "has_air_suspension": false,
+        "has_ludicrous_mode": false,
+        "has_seat_cooling": false,
+        "headlamp_type": "Global",
+        "interior_trim_type": "White2",
+        "key_version": 2,
+        "motorized_charge_port": true,
+        "paint_color_override": "0,9,25,0.7,0.04",
+        "performance_package": "Base",
+        "plg": true,
+        "pws": true,
+        "rear_drive_unit": "PM216MOSFET",
+        "rear_seat_heaters": 1,
+        "rear_seat_type": 0,
+        "rhd": true,
+        "roof_color": "RoofColorGlass",
+        "seat_type": null,
+        "spoiler_type": "None",
+        "sun_roof_installed": null,
+        "supports_qr_pairing": false,
+        "third_row_seats": "None",
+        "timestamp": 1705701487912,
+        "trim_badging": "74d",
+        "use_range_badging": true,
+        "utc_offset": 36000,
+        "webcam_selfie_supported": true,
+        "webcam_supported": true,
+        "wheel_type": "Pinwheel18CapKit"
+      },
+      "command_signing": "allowed",
+      "release_notes_supported": true
+    },
+    {
+      "energy_site_id": 2345,
+      "resource_type": "wall_connector",
+      "id": "ID1234",
+      "asset_site_id": "abcdef",
+      "warp_site_number": "ID1234",
+      "go_off_grid_test_banner_enabled": null,
+      "storm_mode_enabled": null,
+      "powerwall_onboarding_settings_set": null,
+      "powerwall_tesla_electric_interested_in": null,
+      "vpp_tour_enabled": null,
+      "sync_grid_alert_enabled": false,
+      "breaker_alert_enabled": false,
+      "components": {
+        "battery": false,
+        "solar": false,
+        "grid": false,
+        "load_meter": false,
+        "wall_connectors": [
+          { "device_id": "abcdef", "din": "12345", "is_active": true }
+        ]
+      },
+      "features": {}
+    }
+  ],
+  "count": 2
+}
diff --git a/tests/components/teslemetry/fixtures/vehicle_data.json b/tests/components/teslemetry/fixtures/vehicle_data.json
new file mode 100644
index 0000000000000000000000000000000000000000..44556c1c8df509a7c3c4708384e1818bd733605d
--- /dev/null
+++ b/tests/components/teslemetry/fixtures/vehicle_data.json
@@ -0,0 +1,269 @@
+{
+  "response": {
+    "id": 1234,
+    "user_id": 1234,
+    "vehicle_id": 1234,
+    "vin": "VINVINVIN",
+    "color": null,
+    "access_type": "OWNER",
+    "granular_access": {
+      "hide_private": false
+    },
+    "tokens": ["abc", "def"],
+    "state": "online",
+    "in_service": false,
+    "id_s": "1234",
+    "calendar_enabled": true,
+    "api_version": 71,
+    "backseat_token": null,
+    "backseat_token_updated_at": null,
+    "ble_autopair_enrolled": false,
+    "charge_state": {
+      "battery_heater_on": false,
+      "battery_level": 77,
+      "battery_range": 266.87,
+      "charge_amps": 16,
+      "charge_current_request": 16,
+      "charge_current_request_max": 16,
+      "charge_enable_request": true,
+      "charge_energy_added": 0,
+      "charge_limit_soc": 80,
+      "charge_limit_soc_max": 100,
+      "charge_limit_soc_min": 50,
+      "charge_limit_soc_std": 80,
+      "charge_miles_added_ideal": 0,
+      "charge_miles_added_rated": 0,
+      "charge_port_cold_weather_mode": false,
+      "charge_port_color": "<invalid>",
+      "charge_port_door_open": true,
+      "charge_port_latch": "Engaged",
+      "charge_rate": 0,
+      "charger_actual_current": 0,
+      "charger_phases": null,
+      "charger_pilot_current": 16,
+      "charger_power": 0,
+      "charger_voltage": 2,
+      "charging_state": "Stopped",
+      "conn_charge_cable": "IEC",
+      "est_battery_range": 275.04,
+      "fast_charger_brand": "<invalid>",
+      "fast_charger_present": false,
+      "fast_charger_type": "ACSingleWireCAN",
+      "ideal_battery_range": 266.87,
+      "max_range_charge_counter": 0,
+      "minutes_to_full_charge": 0,
+      "not_enough_power_to_heat": null,
+      "off_peak_charging_enabled": false,
+      "off_peak_charging_times": "all_week",
+      "off_peak_hours_end_time": 900,
+      "preconditioning_enabled": false,
+      "preconditioning_times": "all_week",
+      "scheduled_charging_mode": "Off",
+      "scheduled_charging_pending": false,
+      "scheduled_charging_start_time": null,
+      "scheduled_charging_start_time_app": 600,
+      "scheduled_departure_time": 1704837600,
+      "scheduled_departure_time_minutes": 480,
+      "supercharger_session_trip_planner": false,
+      "time_to_full_charge": 0,
+      "timestamp": 1705707520649,
+      "trip_charging": false,
+      "usable_battery_level": 77,
+      "user_charge_enable_request": null
+    },
+    "climate_state": {
+      "allow_cabin_overheat_protection": true,
+      "auto_seat_climate_left": false,
+      "auto_seat_climate_right": true,
+      "auto_steering_wheel_heat": false,
+      "battery_heater": false,
+      "battery_heater_no_power": null,
+      "cabin_overheat_protection": "On",
+      "cabin_overheat_protection_actively_cooling": false,
+      "climate_keeper_mode": "off",
+      "cop_activation_temperature": "High",
+      "defrost_mode": 0,
+      "driver_temp_setting": 22,
+      "fan_status": 0,
+      "hvac_auto_request": "On",
+      "inside_temp": 29.8,
+      "is_auto_conditioning_on": false,
+      "is_climate_on": false,
+      "is_front_defroster_on": false,
+      "is_preconditioning": false,
+      "is_rear_defroster_on": false,
+      "left_temp_direction": 251,
+      "max_avail_temp": 28,
+      "min_avail_temp": 15,
+      "outside_temp": 30,
+      "passenger_temp_setting": 22,
+      "remote_heater_control_enabled": false,
+      "right_temp_direction": 251,
+      "seat_heater_left": 0,
+      "seat_heater_rear_center": 0,
+      "seat_heater_rear_left": 0,
+      "seat_heater_rear_right": 0,
+      "seat_heater_right": 0,
+      "side_mirror_heaters": false,
+      "steering_wheel_heat_level": 0,
+      "steering_wheel_heater": false,
+      "supports_fan_only_cabin_overheat_protection": true,
+      "timestamp": 1705707520649,
+      "wiper_blade_heater": false
+    },
+    "drive_state": {
+      "active_route_latitude": -27.855946,
+      "active_route_longitude": 153.345056,
+      "active_route_traffic_minutes_delay": 0,
+      "power": 0,
+      "shift_state": null,
+      "speed": null,
+      "timestamp": 1705707520649
+    },
+    "gui_settings": {
+      "gui_24_hour_time": false,
+      "gui_charge_rate_units": "kW",
+      "gui_distance_units": "km/hr",
+      "gui_range_display": "Rated",
+      "gui_temperature_units": "C",
+      "gui_tirepressure_units": "Psi",
+      "show_range_units": false,
+      "timestamp": 1705707520649
+    },
+    "vehicle_config": {
+      "aux_park_lamps": "Eu",
+      "badge_version": 1,
+      "can_accept_navigation_requests": true,
+      "can_actuate_trunks": true,
+      "car_special_type": "base",
+      "car_type": "model3",
+      "charge_port_type": "CCS",
+      "cop_user_set_temp_supported": false,
+      "dashcam_clip_save_supported": true,
+      "default_charge_to_max": false,
+      "driver_assist": "TeslaAP3",
+      "ece_restrictions": false,
+      "efficiency_package": "M32021",
+      "eu_vehicle": true,
+      "exterior_color": "DeepBlue",
+      "exterior_trim": "Black",
+      "exterior_trim_override": "",
+      "has_air_suspension": false,
+      "has_ludicrous_mode": false,
+      "has_seat_cooling": false,
+      "headlamp_type": "Global",
+      "interior_trim_type": "White2",
+      "key_version": 2,
+      "motorized_charge_port": true,
+      "paint_color_override": "0,9,25,0.7,0.04",
+      "performance_package": "Base",
+      "plg": true,
+      "pws": true,
+      "rear_drive_unit": "PM216MOSFET",
+      "rear_seat_heaters": 1,
+      "rear_seat_type": 0,
+      "rhd": true,
+      "roof_color": "RoofColorGlass",
+      "seat_type": null,
+      "spoiler_type": "None",
+      "sun_roof_installed": null,
+      "supports_qr_pairing": false,
+      "third_row_seats": "None",
+      "timestamp": 1705707520649,
+      "trim_badging": "74d",
+      "use_range_badging": true,
+      "utc_offset": 36000,
+      "webcam_selfie_supported": true,
+      "webcam_supported": true,
+      "wheel_type": "Pinwheel18CapKit"
+    },
+    "vehicle_state": {
+      "api_version": 71,
+      "autopark_state_v2": "unavailable",
+      "calendar_supported": true,
+      "car_version": "2023.44.30.8 06f534d46010",
+      "center_display_state": 0,
+      "dashcam_clip_save_available": true,
+      "dashcam_state": "Recording",
+      "df": 0,
+      "dr": 0,
+      "fd_window": 0,
+      "feature_bitmask": "fbdffbff,187f",
+      "fp_window": 0,
+      "ft": 0,
+      "is_user_present": false,
+      "locked": false,
+      "media_info": {
+        "audio_volume": 2.6667,
+        "audio_volume_increment": 0.333333,
+        "audio_volume_max": 10.333333,
+        "media_playback_status": "Stopped",
+        "now_playing_album": "",
+        "now_playing_artist": "",
+        "now_playing_duration": 0,
+        "now_playing_elapsed": 0,
+        "now_playing_source": "Spotify",
+        "now_playing_station": "",
+        "now_playing_title": ""
+      },
+      "media_state": {
+        "remote_control_enabled": true
+      },
+      "notifications_supported": true,
+      "odometer": 6481.019282,
+      "parsed_calendar_supported": true,
+      "pf": 0,
+      "pr": 0,
+      "rd_window": 0,
+      "remote_start": false,
+      "remote_start_enabled": true,
+      "remote_start_supported": true,
+      "rp_window": 0,
+      "rt": 0,
+      "santa_mode": 0,
+      "sentry_mode": false,
+      "sentry_mode_available": true,
+      "service_mode": false,
+      "service_mode_plus": false,
+      "software_update": {
+        "download_perc": 0,
+        "expected_duration_sec": 2700,
+        "install_perc": 1,
+        "status": "",
+        "version": " "
+      },
+      "speed_limit_mode": {
+        "active": false,
+        "current_limit_mph": 69,
+        "max_limit_mph": 120,
+        "min_limit_mph": 50,
+        "pin_code_set": true
+      },
+      "timestamp": 1705707520649,
+      "tpms_hard_warning_fl": false,
+      "tpms_hard_warning_fr": false,
+      "tpms_hard_warning_rl": false,
+      "tpms_hard_warning_rr": false,
+      "tpms_last_seen_pressure_time_fl": 1705700812,
+      "tpms_last_seen_pressure_time_fr": 1705700793,
+      "tpms_last_seen_pressure_time_rl": 1705700794,
+      "tpms_last_seen_pressure_time_rr": 1705700823,
+      "tpms_pressure_fl": 2.775,
+      "tpms_pressure_fr": 2.8,
+      "tpms_pressure_rl": 2.775,
+      "tpms_pressure_rr": 2.775,
+      "tpms_rcp_front_value": 2.9,
+      "tpms_rcp_rear_value": 2.9,
+      "tpms_soft_warning_fl": false,
+      "tpms_soft_warning_fr": false,
+      "tpms_soft_warning_rl": false,
+      "tpms_soft_warning_rr": false,
+      "valet_mode": false,
+      "valet_pin_needed": false,
+      "vehicle_name": "Test",
+      "vehicle_self_test_progress": 0,
+      "vehicle_self_test_requested": false,
+      "webcam_available": true
+    }
+  }
+}
diff --git a/tests/components/teslemetry/snapshots/test_climate.ambr b/tests/components/teslemetry/snapshots/test_climate.ambr
new file mode 100644
index 0000000000000000000000000000000000000000..f0f6f1b0140e327b931bc05fe9c971c552671d31
--- /dev/null
+++ b/tests/components/teslemetry/snapshots/test_climate.ambr
@@ -0,0 +1,73 @@
+# serializer version: 1
+# name: test_climate[climate.test_climate-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': dict({
+      'hvac_modes': list([
+        <HVACMode.HEAT_COOL: 'heat_cool'>,
+        <HVACMode.OFF: 'off'>,
+      ]),
+      'max_temp': 28.0,
+      'min_temp': 15.0,
+      'preset_modes': list([
+        'off',
+        'keep',
+        'dog',
+        'camp',
+      ]),
+    }),
+    'config_entry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'climate',
+    'entity_category': None,
+    'entity_id': 'climate.test_climate',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Climate',
+    'platform': 'teslemetry',
+    'previous_unique_id': None,
+    'supported_features': <ClimateEntityFeature: 17>,
+    'translation_key': <TeslemetryClimateSide.DRIVER: 'driver_temp'>,
+    'unique_id': 'VINVINVIN-driver_temp',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_climate[climate.test_climate-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'current_temperature': 30.0,
+      'friendly_name': 'Test Climate',
+      'hvac_modes': list([
+        <HVACMode.HEAT_COOL: 'heat_cool'>,
+        <HVACMode.OFF: 'off'>,
+      ]),
+      'max_temp': 28.0,
+      'min_temp': 15.0,
+      'preset_mode': 'off',
+      'preset_modes': list([
+        'off',
+        'keep',
+        'dog',
+        'camp',
+      ]),
+      'supported_features': <ClimateEntityFeature: 17>,
+      'temperature': 22.0,
+    }),
+    'context': <ANY>,
+    'entity_id': 'climate.test_climate',
+    'last_changed': <ANY>,
+    'last_updated': <ANY>,
+    'state': 'off',
+  })
+# ---
diff --git a/tests/components/teslemetry/test_climate.py b/tests/components/teslemetry/test_climate.py
new file mode 100644
index 0000000000000000000000000000000000000000..ede38a695e20de418d0bc6183074bc97731855d5
--- /dev/null
+++ b/tests/components/teslemetry/test_climate.py
@@ -0,0 +1,131 @@
+"""Test the Teslemetry climate platform."""
+
+from datetime import timedelta
+from unittest.mock import patch
+
+from freezegun.api import FrozenDateTimeFactory
+import pytest
+from syrupy import SnapshotAssertion
+from tesla_fleet_api.exceptions import InvalidCommand, VehicleOffline
+
+from homeassistant.components.climate import (
+    ATTR_HVAC_MODE,
+    ATTR_PRESET_MODE,
+    ATTR_TEMPERATURE,
+    DOMAIN as CLIMATE_DOMAIN,
+    SERVICE_SET_HVAC_MODE,
+    SERVICE_SET_PRESET_MODE,
+    SERVICE_SET_TEMPERATURE,
+    SERVICE_TURN_ON,
+    HVACMode,
+)
+from homeassistant.components.teslemetry.coordinator import SYNC_INTERVAL
+from homeassistant.const import ATTR_ENTITY_ID, Platform
+from homeassistant.core import HomeAssistant
+from homeassistant.exceptions import HomeAssistantError
+from homeassistant.helpers import entity_registry as er
+
+from . import assert_entities, setup_platform
+
+from tests.common import async_fire_time_changed
+
+
+async def test_climate(
+    hass: HomeAssistant,
+    snapshot: SnapshotAssertion,
+    entity_registry: er.EntityRegistry,
+) -> None:
+    """Tests that the climate entity is correct."""
+
+    entry = await setup_platform(hass, [Platform.CLIMATE])
+
+    assert_entities(hass, entry.entry_id, entity_registry, snapshot)
+
+    entity_id = "climate.test_climate"
+    state = hass.states.get(entity_id)
+
+    # Turn On
+    await hass.services.async_call(
+        CLIMATE_DOMAIN,
+        SERVICE_SET_HVAC_MODE,
+        {ATTR_ENTITY_ID: [entity_id], ATTR_HVAC_MODE: HVACMode.HEAT_COOL},
+        blocking=True,
+    )
+    state = hass.states.get(entity_id)
+    assert state.state == HVACMode.HEAT_COOL
+
+    # Set Temp
+    await hass.services.async_call(
+        CLIMATE_DOMAIN,
+        SERVICE_SET_TEMPERATURE,
+        {ATTR_ENTITY_ID: [entity_id], ATTR_TEMPERATURE: 20},
+        blocking=True,
+    )
+    state = hass.states.get(entity_id)
+    assert state.attributes[ATTR_TEMPERATURE] == 20
+
+    # Set Preset
+    await hass.services.async_call(
+        CLIMATE_DOMAIN,
+        SERVICE_SET_PRESET_MODE,
+        {ATTR_ENTITY_ID: [entity_id], ATTR_PRESET_MODE: "keep"},
+        blocking=True,
+    )
+    state = hass.states.get(entity_id)
+    assert state.attributes[ATTR_PRESET_MODE] == "keep"
+
+    # Turn Off
+    await hass.services.async_call(
+        CLIMATE_DOMAIN,
+        SERVICE_SET_HVAC_MODE,
+        {ATTR_ENTITY_ID: [entity_id], ATTR_HVAC_MODE: HVACMode.OFF},
+        blocking=True,
+    )
+    state = hass.states.get(entity_id)
+    assert state.state == HVACMode.OFF
+
+
+async def test_errors(
+    hass: HomeAssistant,
+) -> None:
+    """Tests service error is handled."""
+
+    await setup_platform(hass, platforms=[Platform.CLIMATE])
+    entity_id = "climate.test_climate"
+
+    with patch(
+        "homeassistant.components.teslemetry.VehicleSpecific.auto_conditioning_start",
+        side_effect=InvalidCommand,
+    ) as mock_on, pytest.raises(HomeAssistantError) as error:
+        await hass.services.async_call(
+            CLIMATE_DOMAIN,
+            SERVICE_TURN_ON,
+            {ATTR_ENTITY_ID: [entity_id]},
+            blocking=True,
+        )
+        mock_on.assert_called_once()
+        assert error.from_exception == InvalidCommand
+
+
+async def test_asleep_or_offline(
+    hass: HomeAssistant, mock_vehicle_data, freezer: FrozenDateTimeFactory
+) -> None:
+    """Tests asleep is handled."""
+
+    await setup_platform(hass, [Platform.CLIMATE])
+    entity_id = "climate.test_climate"
+    mock_vehicle_data.assert_called_once()
+
+    # Put the vehicle alseep
+    mock_vehicle_data.reset_mock()
+    mock_vehicle_data.side_effect = VehicleOffline
+    freezer.tick(timedelta(seconds=SYNC_INTERVAL))
+    async_fire_time_changed(hass)
+    await hass.async_block_till_done()
+    mock_vehicle_data.assert_called_once()
+
+    # Run a command that will wake up the vehicle, but not immediately
+    await hass.services.async_call(
+        CLIMATE_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: [entity_id]}, blocking=True
+    )
+    await hass.async_block_till_done()
diff --git a/tests/components/teslemetry/test_config_flow.py b/tests/components/teslemetry/test_config_flow.py
index ca9b89bedb34287d0cbc7577bf730a7fb8a2849f..b89967bfa35582701e1618522dc8d511f0136a33 100644
--- a/tests/components/teslemetry/test_config_flow.py
+++ b/tests/components/teslemetry/test_config_flow.py
@@ -1,6 +1,6 @@
 """Test the Teslemetry config flow."""
 
-from unittest.mock import AsyncMock, patch
+from unittest.mock import patch
 
 from aiohttp import ClientConnectionError
 import pytest
@@ -16,13 +16,12 @@ from .const import CONFIG
 
 
 @pytest.fixture(autouse=True)
-def teslemetry_config_entry_mock():
+def mock_test():
     """Mock Teslemetry api class."""
     with patch(
-        "homeassistant.components.teslemetry.config_flow.Teslemetry",
-    ) as teslemetry_config_entry_mock:
-        teslemetry_config_entry_mock.return_value.test = AsyncMock()
-        yield teslemetry_config_entry_mock
+        "homeassistant.components.teslemetry.Teslemetry.test", return_value=True
+    ) as mock_test:
+        yield mock_test
 
 
 async def test_form(
@@ -60,16 +59,14 @@ async def test_form(
         (TeslaFleetError, {"base": "unknown"}),
     ],
 )
-async def test_form_errors(
-    hass: HomeAssistant, side_effect, error, teslemetry_config_entry_mock
-) -> None:
+async def test_form_errors(hass: HomeAssistant, side_effect, error, mock_test) -> None:
     """Test errors are handled."""
 
     result1 = await hass.config_entries.flow.async_init(
         DOMAIN, context={"source": config_entries.SOURCE_USER}
     )
 
-    teslemetry_config_entry_mock.return_value.test.side_effect = side_effect
+    mock_test.side_effect = side_effect
     result2 = await hass.config_entries.flow.async_configure(
         result1["flow_id"],
         CONFIG,
@@ -79,7 +76,7 @@ async def test_form_errors(
     assert result2["errors"] == error
 
     # Complete the flow
-    teslemetry_config_entry_mock.return_value.test.side_effect = None
+    mock_test.side_effect = None
     result3 = await hass.config_entries.flow.async_configure(
         result2["flow_id"],
         CONFIG,
diff --git a/tests/components/teslemetry/test_init.py b/tests/components/teslemetry/test_init.py
new file mode 100644
index 0000000000000000000000000000000000000000..28440094becf59d7d9baf41b0126bd2d6c0f720e
--- /dev/null
+++ b/tests/components/teslemetry/test_init.py
@@ -0,0 +1,118 @@
+"""Test the Tessie init."""
+
+from datetime import timedelta
+
+from freezegun.api import FrozenDateTimeFactory
+from tesla_fleet_api.exceptions import (
+    InvalidToken,
+    PaymentRequired,
+    TeslaFleetError,
+    VehicleOffline,
+)
+
+from homeassistant.components.teslemetry.coordinator import SYNC_INTERVAL
+from homeassistant.config_entries import ConfigEntryState
+from homeassistant.const import Platform
+from homeassistant.core import HomeAssistant
+
+from . import setup_platform
+from .const import WAKE_UP_ASLEEP, WAKE_UP_ONLINE
+
+from tests.common import async_fire_time_changed
+
+
+async def test_load_unload(hass: HomeAssistant) -> None:
+    """Test load and unload."""
+
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.LOADED
+    assert await hass.config_entries.async_unload(entry.entry_id)
+    await hass.async_block_till_done()
+    assert entry.state is ConfigEntryState.NOT_LOADED
+
+
+async def test_auth_failure(hass: HomeAssistant, mock_products) -> None:
+    """Test init with an authentication error."""
+
+    mock_products.side_effect = InvalidToken
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_ERROR
+
+
+async def test_subscription_failure(hass: HomeAssistant, mock_products) -> None:
+    """Test init with an client response error."""
+
+    mock_products.side_effect = PaymentRequired
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_ERROR
+
+
+async def test_other_failure(hass: HomeAssistant, mock_products) -> None:
+    """Test init with an client response error."""
+
+    mock_products.side_effect = TeslaFleetError
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_RETRY
+
+
+# Coordinator
+
+
+async def test_first_refresh(
+    hass: HomeAssistant,
+    mock_wake_up,
+    mock_vehicle_data,
+    mock_products,
+    freezer: FrozenDateTimeFactory,
+) -> None:
+    """Test first coordinator refresh but vehicle is asleep."""
+
+    # Mock vehicle is asleep
+    mock_wake_up.return_value = WAKE_UP_ASLEEP
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_RETRY
+    mock_wake_up.assert_called_once()
+
+    # Reset mock and set vehicle to online
+    mock_wake_up.reset_mock()
+    mock_wake_up.return_value = WAKE_UP_ONLINE
+
+    # Wait for the retry
+    freezer.tick(timedelta(seconds=60))
+    async_fire_time_changed(hass)
+    await hass.async_block_till_done()
+
+    # Verify we have loaded
+    assert entry.state is ConfigEntryState.LOADED
+    mock_wake_up.assert_called_once()
+    mock_vehicle_data.assert_called_once()
+
+
+async def test_first_refresh_error(hass: HomeAssistant, mock_wake_up) -> None:
+    """Test first coordinator refresh with an error."""
+    mock_wake_up.side_effect = TeslaFleetError
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_RETRY
+
+
+async def test_refresh_offline(
+    hass: HomeAssistant, mock_vehicle_data, freezer: FrozenDateTimeFactory
+) -> None:
+    """Test coordinator refresh with an error."""
+    entry = await setup_platform(hass, [Platform.CLIMATE])
+    assert entry.state is ConfigEntryState.LOADED
+    mock_vehicle_data.assert_called_once()
+    mock_vehicle_data.reset_mock()
+
+    mock_vehicle_data.side_effect = VehicleOffline
+    freezer.tick(timedelta(seconds=SYNC_INTERVAL))
+    async_fire_time_changed(hass)
+    await hass.async_block_till_done()
+    mock_vehicle_data.assert_called_once()
+
+
+async def test_refresh_error(hass: HomeAssistant, mock_vehicle_data) -> None:
+    """Test coordinator refresh with an error."""
+    mock_vehicle_data.side_effect = TeslaFleetError
+    entry = await setup_platform(hass)
+    assert entry.state is ConfigEntryState.SETUP_RETRY