diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py
index ab53c3669cb7224145e4e87c2f15bc9ae602902b..c30745239ea05c7e0d633cbeeee539005b96f725 100644
--- a/homeassistant/components/light/tradfri.py
+++ b/homeassistant/components/light/tradfri.py
@@ -19,12 +19,16 @@ import homeassistant.util.color as color_util
 
 _LOGGER = logging.getLogger(__name__)
 
+ATTR_DIMMER = 'dimmer'
+ATTR_HUE = 'hue'
+ATTR_SAT = 'saturation'
 ATTR_TRANSITION_TIME = 'transition_time'
 DEPENDENCIES = ['tradfri']
 PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA
 IKEA = 'IKEA of Sweden'
 TRADFRI_LIGHT_MANAGER = 'Tradfri Light Manager'
-SUPPORTED_FEATURES = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION)
+SUPPORTED_FEATURES = SUPPORT_TRANSITION
+SUPPORTED_GROUP_FEATURES = SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION
 
 
 async def async_setup_platform(hass, config,
@@ -79,7 +83,7 @@ class TradfriGroup(Light):
     @property
     def supported_features(self):
         """Flag supported features."""
-        return SUPPORTED_FEATURES
+        return SUPPORTED_GROUP_FEATURES
 
     @property
     def name(self):
@@ -225,75 +229,97 @@ class TradfriLight(Light):
         """HS color of the light."""
         if self._light_control.can_set_color:
             hsbxy = self._light_data.hsb_xy_color
-            hue = hsbxy[0] / (65535 / 360)
-            sat = hsbxy[1] / (65279 / 100)
+            hue = hsbxy[0] / (self._light_control.max_hue / 360)
+            sat = hsbxy[1] / (self._light_control.max_saturation / 100)
             if hue is not None and sat is not None:
                 return hue, sat
 
     async def async_turn_off(self, **kwargs):
         """Instruct the light to turn off."""
-        await self._api(self._light_control.set_state(False))
+        # This allows transitioning to off, but resets the brightness
+        # to 1 for the next set_state(True) command
+        transition_time = None
+        if ATTR_TRANSITION in kwargs:
+            transition_time = int(kwargs[ATTR_TRANSITION]) * 10
+
+            dimmer_data = {ATTR_DIMMER: 0, ATTR_TRANSITION_TIME:
+                           transition_time}
+            await self._api(self._light_control.set_dimmer(**dimmer_data))
+        else:
+            await self._api(self._light_control.set_state(False))
 
     async def async_turn_on(self, **kwargs):
         """Instruct the light to turn on."""
-        params = {}
         transition_time = None
         if ATTR_TRANSITION in kwargs:
             transition_time = int(kwargs[ATTR_TRANSITION]) * 10
 
-        brightness = kwargs.get(ATTR_BRIGHTNESS)
-
-        if brightness is not None:
+        dimmer_command = None
+        if ATTR_BRIGHTNESS in kwargs:
+            brightness = kwargs[ATTR_BRIGHTNESS]
             if brightness > 254:
                 brightness = 254
             elif brightness < 0:
                 brightness = 0
+            dimmer_data = {ATTR_DIMMER: brightness, ATTR_TRANSITION_TIME:
+                           transition_time}
+            dimmer_command = self._light_control.set_dimmer(**dimmer_data)
+            transition_time = None
+        else:
+            dimmer_command = self._light_control.set_state(True)
 
+        color_command = None
         if ATTR_HS_COLOR in kwargs and self._light_control.can_set_color:
-            params[ATTR_BRIGHTNESS] = brightness
-            hue = int(kwargs[ATTR_HS_COLOR][0] * (65535 / 360))
-            sat = int(kwargs[ATTR_HS_COLOR][1] * (65279 / 100))
-            if brightness is None:
-                params[ATTR_TRANSITION_TIME] = transition_time
-            await self._api(
-                self._light_control.set_hsb(hue, sat, **params))
-            return
-
+            hue = int(kwargs[ATTR_HS_COLOR][0] *
+                      (self._light_control.max_hue / 360))
+            sat = int(kwargs[ATTR_HS_COLOR][1] *
+                      (self._light_control.max_saturation / 100))
+            color_data = {ATTR_HUE: hue, ATTR_SAT: sat, ATTR_TRANSITION_TIME:
+                          transition_time}
+            color_command = self._light_control.set_hsb(**color_data)
+            transition_time = None
+
+        temp_command = None
         if ATTR_COLOR_TEMP in kwargs and (self._light_control.can_set_temp or
                                           self._light_control.can_set_color):
             temp = kwargs[ATTR_COLOR_TEMP]
-            if temp > self.max_mireds:
-                temp = self.max_mireds
-            elif temp < self.min_mireds:
-                temp = self.min_mireds
-
-            if brightness is None:
-                params[ATTR_TRANSITION_TIME] = transition_time
             # White Spectrum bulb
-            if (self._light_control.can_set_temp and
-                    not self._light_control.can_set_color):
-                await self._api(
-                    self._light_control.set_color_temp(temp, **params))
+            if self._light_control.can_set_temp:
+                if temp > self.max_mireds:
+                    temp = self.max_mireds
+                elif temp < self.min_mireds:
+                    temp = self.min_mireds
+                temp_data = {ATTR_COLOR_TEMP: temp, ATTR_TRANSITION_TIME:
+                             transition_time}
+                temp_command = self._light_control.set_color_temp(**temp_data)
+                transition_time = None
             # Color bulb (CWS)
             # color_temp needs to be set with hue/saturation
-            if self._light_control.can_set_color:
-                params[ATTR_BRIGHTNESS] = brightness
+            elif self._light_control.can_set_color:
                 temp_k = color_util.color_temperature_mired_to_kelvin(temp)
                 hs_color = color_util.color_temperature_to_hs(temp_k)
-                hue = int(hs_color[0] * (65535 / 360))
-                sat = int(hs_color[1] * (65279 / 100))
-                await self._api(
-                    self._light_control.set_hsb(hue, sat,
-                                                **params))
-
-        if brightness is not None:
-            params[ATTR_TRANSITION_TIME] = transition_time
-            await self._api(
-                self._light_control.set_dimmer(brightness,
-                                               **params))
+                hue = int(hs_color[0] * (self._light_control.max_hue / 360))
+                sat = int(hs_color[1] *
+                          (self._light_control.max_saturation / 100))
+                color_data = {ATTR_HUE: hue, ATTR_SAT: sat,
+                              ATTR_TRANSITION_TIME: transition_time}
+                color_command = self._light_control.set_hsb(**color_data)
+                transition_time = None
+
+        # HSB can always be set, but color temp + brightness is bulb dependant
+        command = dimmer_command
+        if command is not None:
+            command += color_command
         else:
-            await self._api(
-                self._light_control.set_state(True))
+            command = color_command
+
+        if self._light_control.can_combine_commands:
+            await self._api(command + temp_command)
+        else:
+            if temp_command is not None:
+                await self._api(temp_command)
+            if command is not None:
+                await self._api(command)
 
     @callback
     def _async_start_observe(self, exc=None):
@@ -324,6 +350,8 @@ class TradfriLight(Light):
         self._name = light.name
         self._features = SUPPORTED_FEATURES
 
+        if light.light_control.can_set_dimmer:
+            self._features |= SUPPORT_BRIGHTNESS
         if light.light_control.can_set_color:
             self._features |= SUPPORT_COLOR
         if light.light_control.can_set_temp:
diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py
index 72d1b4c769f1f6b5ce8647c5e6dd361dafbf5ab4..9ed613abde04ea50b09ebea26e62c047f6fa051d 100644
--- a/homeassistant/components/tradfri.py
+++ b/homeassistant/components/tradfri.py
@@ -15,7 +15,7 @@ from homeassistant.const import CONF_HOST
 from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI
 from homeassistant.util.json import load_json, save_json
 
-REQUIREMENTS = ['pytradfri[async]==5.4.2']
+REQUIREMENTS = ['pytradfri[async]==5.5.1']
 
 DOMAIN = 'tradfri'
 GATEWAY_IDENTITY = 'homeassistant'
diff --git a/requirements_all.txt b/requirements_all.txt
index b6bb426a437a0fea087f1e294930f17fb6815799..3b1096d36eb41a437db879cb5533bdf6429025d4 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -1117,7 +1117,7 @@ pytouchline==0.7
 pytrackr==0.0.5
 
 # homeassistant.components.tradfri
-pytradfri[async]==5.4.2
+pytradfri[async]==5.5.1
 
 # homeassistant.components.device_tracker.unifi
 pyunifi==2.13
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 732aa85a37a43fe35c0e68a86397170b0efd58fe..9334d63042943209644422dce0b4a7c75bf4e915 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -158,6 +158,9 @@ python-forecastio==1.4.0
 # homeassistant.components.sensor.whois
 pythonwhois==2.4.3
 
+# homeassistant.components.tradfri
+pytradfri[async]==5.5.1
+
 # homeassistant.components.device_tracker.unifi
 pyunifi==2.13
 
diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py
index b5b636dc8745d13b2c6dc6107d0378af9228d564..e770d90266986a82023ab6248787aaa39ed53a8b 100755
--- a/script/gen_requirements_all.py
+++ b/script/gen_requirements_all.py
@@ -77,6 +77,7 @@ TEST_REQUIREMENTS = (
     'pynx584',
     'pyqwikswitch',
     'python-forecastio',
+    'pytradfri\[async\]',
     'pyunifi',
     'pyupnp-async',
     'pywebpush',
diff --git a/tests/components/light/test_tradfri.py b/tests/components/light/test_tradfri.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ef5d17452a639bfdce9e660c288fc27d7131903
--- /dev/null
+++ b/tests/components/light/test_tradfri.py
@@ -0,0 +1,548 @@
+"""Tradfri lights platform tests."""
+
+from copy import deepcopy
+from unittest.mock import Mock, MagicMock, patch, PropertyMock
+
+import pytest
+from pytradfri.device import Device, LightControl, Light
+from pytradfri import RequestError
+
+from homeassistant.components import tradfri
+from homeassistant.setup import async_setup_component
+
+
+DEFAULT_TEST_FEATURES = {'can_set_dimmer': False,
+                         'can_set_color': False,
+                         'can_set_temp': False}
+# [
+#     {bulb features},
+#     {turn_on arguments},
+#     {expected result}
+# ]
+TURN_ON_TEST_CASES = [
+    # Turn On
+    [
+        {},
+        {},
+        {'state': 'on'},
+    ],
+    # Brightness > 0
+    [
+        {'can_set_dimmer': True},
+        {'brightness': 100},
+        {
+            'state': 'on',
+            'brightness': 100
+        }
+    ],
+    # Brightness == 0
+    [
+        {'can_set_dimmer': True},
+        {'brightness': 0},
+        {
+            'brightness': 0
+        }
+    ],
+    # Brightness < 0
+    [
+        {'can_set_dimmer': True},
+        {'brightness': -1},
+        {
+            'brightness': 0
+        }
+    ],
+    # Brightness > 254
+    [
+        {'can_set_dimmer': True},
+        {'brightness': 1000},
+        {
+            'brightness': 254
+        }
+    ],
+    # color_temp
+    [
+        {'can_set_temp': True},
+        {'color_temp': 250},
+        {'color_temp': 250},
+    ],
+    # color_temp < 250
+    [
+        {'can_set_temp': True},
+        {'color_temp': 1},
+        {'color_temp': 250},
+    ],
+    # color_temp > 454
+    [
+        {'can_set_temp': True},
+        {'color_temp': 1000},
+        {'color_temp': 454},
+    ],
+    # hs color
+    [
+        {'can_set_color': True},
+        {'hs_color': [300, 100]},
+        {
+            'state': 'on',
+            'hs_color': [300, 100]
+        }
+    ],
+    # ct + brightness
+    [
+        {
+            'can_set_dimmer': True,
+            'can_set_temp': True
+        },
+        {
+            'color_temp': 250,
+            'brightness': 200
+        },
+        {
+            'state': 'on',
+            'color_temp': 250,
+            'brightness': 200
+        }
+    ],
+    # ct + brightness (no temp support)
+    [
+        {
+            'can_set_dimmer': True,
+            'can_set_temp': False,
+            'can_set_color': True
+        },
+        {
+            'color_temp': 250,
+            'brightness': 200
+        },
+        {
+            'state': 'on',
+            'hs_color': [26.807, 34.869],
+            'brightness': 200
+        }
+    ],
+    # ct + brightness (no temp or color support)
+    [
+        {
+            'can_set_dimmer': True,
+            'can_set_temp': False,
+            'can_set_color': False
+        },
+        {
+            'color_temp': 250,
+            'brightness': 200
+        },
+        {
+            'state': 'on',
+            'brightness': 200
+        }
+    ],
+    # hs + brightness
+    [
+        {
+            'can_set_dimmer': True,
+            'can_set_color': True
+        },
+        {
+            'hs_color': [300, 100],
+            'brightness': 200
+        },
+        {
+            'state': 'on',
+            'hs_color': [300, 100],
+            'brightness': 200
+        }
+    ]
+]
+
+# Result of transition is not tested, but data is passed to turn on service.
+TRANSITION_CASES_FOR_TESTS = [None, 0, 1]
+
+
+@pytest.fixture(autouse=True, scope='module')
+def setup(request):
+    """Set up patches for pytradfri methods."""
+    p_1 = patch('pytradfri.device.LightControl.raw',
+                new_callable=PropertyMock,
+                return_value=[{'mock': 'mock'}])
+    p_2 = patch('pytradfri.device.LightControl.lights')
+    p_1.start()
+    p_2.start()
+
+    def teardown():
+        """Remove patches for pytradfri methods."""
+        p_1.stop()
+        p_2.stop()
+
+    request.addfinalizer(teardown)
+
+
+@pytest.fixture
+def mock_gateway():
+    """Mock a Tradfri gateway."""
+    def get_devices():
+        """Return mock devices."""
+        return gateway.mock_devices
+
+    def get_groups():
+        """Return mock groups."""
+        return gateway.mock_groups
+
+    gateway = Mock(
+        get_devices=get_devices,
+        get_groups=get_groups,
+        mock_devices=[],
+        mock_groups=[],
+        mock_responses=[]
+    )
+    return gateway
+
+
+@pytest.fixture
+def mock_api(mock_gateway):
+    """Mock api."""
+    async def api(self, command):
+        """Mock api function."""
+        # Store the data for "real" command objects.
+        if(hasattr(command, '_data') and not isinstance(command, Mock)):
+            mock_gateway.mock_responses.append(command._data)
+        return command
+    return api
+
+
+async def generate_psk(self, code):
+    """Mock psk."""
+    return "mock"
+
+
+async def setup_gateway(hass, mock_gateway, mock_api,
+                        generate_psk=generate_psk,
+                        known_hosts=None):
+    """Load the Tradfri platform with a mock gateway."""
+    def request_config(_, callback, description, submit_caption, fields):
+        """Mock request_config."""
+        hass.async_add_job(callback, {'security_code': 'mock'})
+
+    if known_hosts is None:
+        known_hosts = {}
+
+    with patch('pytradfri.api.aiocoap_api.APIFactory.generate_psk',
+               generate_psk), \
+            patch('pytradfri.api.aiocoap_api.APIFactory.request', mock_api), \
+            patch('pytradfri.Gateway', return_value=mock_gateway), \
+            patch.object(tradfri, 'load_json', return_value=known_hosts), \
+            patch.object(hass.components.configurator, 'request_config',
+                         request_config):
+
+        await async_setup_component(hass, tradfri.DOMAIN,
+                                    {
+                                        tradfri.DOMAIN: {
+                                            'host': 'mock-host',
+                                            'allow_tradfri_groups': True
+                                        }
+                                    })
+        await hass.async_block_till_done()
+
+
+async def test_setup_gateway(hass, mock_gateway, mock_api):
+    """Test that the gateway can be setup without errors."""
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+
+async def test_setup_gateway_known_host(hass, mock_gateway, mock_api):
+    """Test gateway setup with a known host."""
+    await setup_gateway(hass, mock_gateway, mock_api,
+                        known_hosts={
+                            'mock-host': {
+                                'identity': 'mock',
+                                'key': 'mock-key'
+                                }
+                            })
+
+
+async def test_incorrect_security_code(hass, mock_gateway, mock_api):
+    """Test that an error is shown if the security code is incorrect."""
+    async def psk_error(self, code):
+        """Raise RequestError when called."""
+        raise RequestError
+
+    with patch.object(hass.components.configurator, 'async_notify_errors') \
+            as notify_error:
+        await setup_gateway(hass, mock_gateway, mock_api,
+                            generate_psk=psk_error)
+        assert len(notify_error.mock_calls) > 0
+
+
+def mock_light(test_features={}, test_state={}, n=0):
+    """Mock a tradfri light."""
+    mock_light_data = Mock(
+        **test_state
+    )
+
+    mock_light = Mock(
+        id='mock-light-id-{}'.format(n),
+        reachable=True,
+        observe=Mock(),
+        device_info=MagicMock()
+    )
+    mock_light.name = 'tradfri_light_{}'.format(n)
+
+    # Set supported features for the light.
+    features = {**DEFAULT_TEST_FEATURES, **test_features}
+    lc = LightControl(mock_light)
+    for k, v in features.items():
+        setattr(lc, k, v)
+    # Store the initial state.
+    setattr(lc, 'lights', [mock_light_data])
+    mock_light.light_control = lc
+    return mock_light
+
+
+async def test_light(hass, mock_gateway, mock_api):
+    """Test that lights are correctly added."""
+    features = {
+        'can_set_dimmer': True,
+        'can_set_color': True,
+        'can_set_temp': True
+    }
+
+    state = {
+        'state': True,
+        'dimmer': 100,
+        'color_temp': 250,
+        'hsb_xy_color': (100, 100, 100, 100, 100)
+    }
+
+    mock_gateway.mock_devices.append(
+        mock_light(test_features=features, test_state=state)
+    )
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    lamp_1 = hass.states.get('light.tradfri_light_0')
+    assert lamp_1 is not None
+    assert lamp_1.state == 'on'
+    assert lamp_1.attributes['brightness'] == 100
+    assert lamp_1.attributes['hs_color'] == (0.549, 0.153)
+
+
+async def test_light_observed(hass, mock_gateway, mock_api):
+    """Test that lights are correctly observed."""
+    light = mock_light()
+    mock_gateway.mock_devices.append(light)
+    await setup_gateway(hass, mock_gateway, mock_api)
+    assert len(light.observe.mock_calls) > 0
+
+
+async def test_light_available(hass, mock_gateway, mock_api):
+    """Test light available property."""
+    light = mock_light({'state': True}, n=1)
+    light.reachable = True
+
+    light2 = mock_light({'state': True}, n=2)
+    light2.reachable = False
+
+    mock_gateway.mock_devices.append(light)
+    mock_gateway.mock_devices.append(light2)
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    assert (hass.states.get('light.tradfri_light_1')
+            .state == 'on')
+
+    assert (hass.states.get('light.tradfri_light_2')
+            .state == 'unavailable')
+
+
+# Combine TURN_ON_TEST_CASES and TRANSITION_CASES_FOR_TESTS
+ALL_TURN_ON_TEST_CASES = [
+    ["test_features", "test_data", "expected_result", "id"],
+    []
+]
+
+idx = 1
+for tc in TURN_ON_TEST_CASES:
+    for trans in TRANSITION_CASES_FOR_TESTS:
+        case = deepcopy(tc)
+        if trans is not None:
+            case[1]['transition'] = trans
+        case.append(idx)
+        idx = idx + 1
+        ALL_TURN_ON_TEST_CASES[1].append(case)
+
+
+@pytest.mark.parametrize(*ALL_TURN_ON_TEST_CASES)
+async def test_turn_on(hass,
+                       mock_gateway,
+                       mock_api,
+                       test_features,
+                       test_data,
+                       expected_result,
+                       id):
+    """Test turning on a light."""
+    # Note pytradfri style, not hass. Values not really important.
+    initial_state = {
+        'state': False,
+        'dimmer': 0,
+        'color_temp': 250,
+        'hsb_xy_color': (100, 100, 100, 100, 100)
+    }
+
+    # Setup the gateway with a mock light.
+    light = mock_light(test_features=test_features,
+                       test_state=initial_state,
+                       n=id)
+    mock_gateway.mock_devices.append(light)
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    # Use the turn_on service call to change the light state.
+    await hass.services.async_call('light', 'turn_on', {
+        'entity_id': 'light.tradfri_light_{}'.format(id),
+        **test_data
+    }, blocking=True)
+    await hass.async_block_till_done()
+
+    # Check that the light is observed.
+    mock_func = light.observe
+    assert len(mock_func.mock_calls) > 0
+    _, callkwargs = mock_func.call_args
+    assert 'callback' in callkwargs
+    # Callback function to refresh light state.
+    cb = callkwargs['callback']
+
+    responses = mock_gateway.mock_responses
+    # State on command data.
+    data = {'3311': [{'5850': 1}]}
+    # Add data for all sent commands.
+    for r in responses:
+        data['3311'][0] = {**data['3311'][0], **r['3311'][0]}
+
+    # Use the callback function to update the light state.
+    dev = Device(data)
+    light_data = Light(dev, 0)
+    light.light_control.lights[0] = light_data
+    cb(light)
+    await hass.async_block_till_done()
+
+    # Check that the state is correct.
+    states = hass.states.get('light.tradfri_light_{}'.format(id))
+    for k, v in expected_result.items():
+        if k == 'state':
+            assert states.state == v
+        else:
+            # Allow some rounding error in color conversions.
+            assert states.attributes[k] == pytest.approx(v, abs=0.01)
+
+
+async def test_turn_off(hass, mock_gateway, mock_api):
+    """Test turning off a light."""
+    state = {
+        'state': True,
+        'dimmer': 100,
+    }
+
+    light = mock_light(test_state=state)
+    mock_gateway.mock_devices.append(light)
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    # Use the turn_off service call to change the light state.
+    await hass.services.async_call('light', 'turn_off', {
+        'entity_id': 'light.tradfri_light_0'}, blocking=True)
+    await hass.async_block_till_done()
+
+    # Check that the light is observed.
+    mock_func = light.observe
+    assert len(mock_func.mock_calls) > 0
+    _, callkwargs = mock_func.call_args
+    assert 'callback' in callkwargs
+    # Callback function to refresh light state.
+    cb = callkwargs['callback']
+
+    responses = mock_gateway.mock_responses
+    data = {'3311': [{}]}
+    # Add data for all sent commands.
+    for r in responses:
+        data['3311'][0] = {**data['3311'][0], **r['3311'][0]}
+
+    # Use the callback function to update the light state.
+    dev = Device(data)
+    light_data = Light(dev, 0)
+    light.light_control.lights[0] = light_data
+    cb(light)
+    await hass.async_block_till_done()
+
+    # Check that the state is correct.
+    states = hass.states.get('light.tradfri_light_0')
+    assert states.state == 'off'
+
+
+def mock_group(test_state={}, n=0):
+    """Mock a Tradfri group."""
+    default_state = {
+        'state': False,
+        'dimmer': 0,
+    }
+
+    state = {**default_state, **test_state}
+
+    mock_group = Mock(
+        member_ids=[],
+        observe=Mock(),
+        **state
+    )
+    mock_group.name = 'tradfri_group_{}'.format(n)
+    return mock_group
+
+
+async def test_group(hass, mock_gateway, mock_api):
+    """Test that groups are correctly added."""
+    mock_gateway.mock_groups.append(mock_group())
+    state = {'state': True, 'dimmer': 100}
+    mock_gateway.mock_groups.append(mock_group(state, 1))
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    group = hass.states.get('light.tradfri_group_0')
+    assert group is not None
+    assert group.state == 'off'
+
+    group = hass.states.get('light.tradfri_group_1')
+    assert group is not None
+    assert group.state == 'on'
+    assert group.attributes['brightness'] == 100
+
+
+async def test_group_turn_on(hass, mock_gateway, mock_api):
+    """Test turning on a group."""
+    group = mock_group()
+    group2 = mock_group(n=1)
+    group3 = mock_group(n=2)
+    mock_gateway.mock_groups.append(group)
+    mock_gateway.mock_groups.append(group2)
+    mock_gateway.mock_groups.append(group3)
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    # Use the turn_off service call to change the light state.
+    await hass.services.async_call('light', 'turn_on', {
+        'entity_id': 'light.tradfri_group_0'}, blocking=True)
+    await hass.services.async_call('light', 'turn_on', {
+        'entity_id': 'light.tradfri_group_1',
+        'brightness': 100}, blocking=True)
+    await hass.services.async_call('light', 'turn_on', {
+        'entity_id': 'light.tradfri_group_2',
+        'brightness': 100,
+        'transition': 1}, blocking=True)
+    await hass.async_block_till_done()
+
+    group.set_state.assert_called_with(1)
+    group2.set_dimmer.assert_called_with(100)
+    group3.set_dimmer.assert_called_with(100, transition_time=10)
+
+
+async def test_group_turn_off(hass, mock_gateway, mock_api):
+    """Test turning off a group."""
+    group = mock_group({'state': True})
+    mock_gateway.mock_groups.append(group)
+    await setup_gateway(hass, mock_gateway, mock_api)
+
+    # Use the turn_off service call to change the light state.
+    await hass.services.async_call('light', 'turn_off', {
+        'entity_id': 'light.tradfri_group_0'}, blocking=True)
+    await hass.async_block_till_done()
+
+    group.set_state.assert_called_with(0)