2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.io.hueemulation.internal.rest;
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.junit.Assert.*;
18 import java.io.IOException;
19 import java.lang.reflect.Type;
21 import java.util.Map.Entry;
23 import javax.ws.rs.client.Entity;
24 import javax.ws.rs.core.Response;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.openhab.core.items.GenericItem;
28 import org.openhab.core.items.GroupItem;
29 import org.openhab.core.items.ItemRegistry;
30 import org.openhab.core.library.items.ColorItem;
31 import org.openhab.core.library.items.DimmerItem;
32 import org.openhab.core.library.items.RollershutterItem;
33 import org.openhab.core.library.items.SwitchItem;
34 import org.openhab.core.library.types.HSBType;
35 import org.openhab.core.library.types.OnOffType;
36 import org.openhab.core.library.types.PercentType;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.State;
39 import org.glassfish.jersey.server.ResourceConfig;
40 import org.hamcrest.CoreMatchers;
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.openhab.core.automation.Rule;
45 import org.openhab.core.automation.RuleRegistry;
46 import org.openhab.core.automation.util.RuleBuilder;
47 import org.openhab.io.hueemulation.internal.ConfigStore;
48 import org.openhab.io.hueemulation.internal.dto.HueSceneEntry;
49 import org.openhab.io.hueemulation.internal.rest.mocks.DummyItemRegistry;
50 import org.openhab.io.hueemulation.internal.rest.mocks.DummyRuleRegistry;
52 import com.google.gson.Gson;
53 import com.google.gson.reflect.TypeToken;
56 * Tests for various scene API endpoints.
58 * @author David Graeff - Initial contribution
61 public class SceneTests {
62 protected @NonNullByDefault({}) CommonSetup commonSetup;
63 protected @NonNullByDefault({}) ConfigStore cs;
64 protected @NonNullByDefault({}) ItemRegistry itemRegistry;
65 protected @NonNullByDefault({}) RuleRegistry ruleRegistry;
67 Scenes subject = new Scenes();
69 private void addItemToReg(GenericItem item, State state, String tag) {
72 itemRegistry.add(item);
76 public void setUp() throws IOException {
77 commonSetup = new CommonSetup(false);
78 this.cs = commonSetup.cs;
80 itemRegistry = new DummyItemRegistry();
81 ruleRegistry = new DummyRuleRegistry();
83 subject.cs = commonSetup.cs;
84 subject.userManagement = commonSetup.userManagement;
85 subject.itemRegistry = itemRegistry;
86 subject.ruleRegistry = ruleRegistry;
89 // Add simulated lights
90 addItemToReg(new SwitchItem("switch1"), OnOffType.ON, "Switchable");
91 addItemToReg(new ColorItem("color1"), HSBType.BLUE, "ColorLighting");
92 addItemToReg(new DimmerItem("white1"), new PercentType(12), "Lighting");
93 addItemToReg(new RollershutterItem("roller1"), new PercentType(12), "Lighting");
94 addItemToReg(new DimmerItem("white1"), new PercentType(12), "Lighting");
95 addItemToReg(new GroupItem("group1"), OnOffType.ON, "Switchable");
97 commonSetup.start(new ResourceConfig().registerInstances(subject));
101 public void tearDown() {
102 commonSetup.dispose();
105 @SuppressWarnings("null")
107 public void addUpdateRemoveSceneToRegistry() {
108 Rule rule = RuleBuilder.create("demo1").withTags("scene") //
109 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
111 ruleRegistry.add(rule);
113 HueSceneEntry sceneEntry = cs.ds.scenes.get("demo1");
114 assertThat(sceneEntry.lights.get(0), CoreMatchers.is("switch1"));
117 rule = RuleBuilder.create("demo1").withTags("scene") //
118 .withActions(Scenes.actionFromState("white1", (Command) OnOffType.ON)).build();
119 ruleRegistry.update(rule);
121 sceneEntry = cs.ds.scenes.get("demo1");
122 assertThat(sceneEntry.lights.get(0), CoreMatchers.is("white1"));
126 ruleRegistry.remove("demo1");
127 sceneEntry = cs.ds.scenes.get("demo1");
128 assertThat(sceneEntry, CoreMatchers.nullValue());
131 @SuppressWarnings("null")
133 public void addGetRemoveSceneViaRest() {
135 String body = "{ 'name':'Cozy dinner', 'recycle':false, 'lights':['switch1','white1'], 'type':'LightScene'}";
136 Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes").request()
137 .post(Entity.json(body));
138 assertEquals(200, response.getStatus());
139 assertThat(response.readEntity(String.class), containsString("success"));
141 // 1.1 Check for scene entry
142 Entry<String, HueSceneEntry> entry = cs.ds.scenes.entrySet().stream().findAny().get();
143 assertThat(entry.getValue().name, is("Cozy dinner"));
144 assertThat(entry.getValue().lights.get(0), is("switch1"));
145 assertThat(entry.getValue().lights.get(1), is("white1"));
147 // 1.2 Check for rule
148 Rule rule = ruleRegistry.get(entry.getKey());
149 assertThat(rule.getName(), is("Cozy dinner"));
150 assertThat(rule.getActions().get(0).getId(), is("switch1"));
151 assertThat(rule.getActions().get(1).getId(), is("white1"));
154 response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/" + entry.getKey()).request()
156 assertEquals(200, response.getStatus());
157 HueSceneEntry fromJson = new Gson().fromJson(response.readEntity(String.class), HueSceneEntry.class);
158 assertThat(fromJson.name, is(entry.getValue().name));
161 response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/" + entry.getKey()).request()
163 assertEquals(200, response.getStatus());
164 assertTrue(cs.ds.scenes.isEmpty());
167 @SuppressWarnings("null")
169 public void updateSceneViaRest() {
170 Rule rule = RuleBuilder.create("demo1").withTags("scene").withName("Some name") //
171 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
173 ruleRegistry.add(rule);
175 // 3. Modify (just the name)
176 String body = "{ 'name':'A new name'}";
177 Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
178 .put(Entity.json(body));
179 assertEquals(200, response.getStatus());
180 assertThat(response.readEntity(String.class), containsString("name"));
182 Entry<String, HueSceneEntry> sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
183 assertThat(sceneEntry.getValue().name, is("A new name"));
184 assertThat(sceneEntry.getValue().lights.get(0), is("switch1")); // nothing else should have changed
186 // 3. Modify (just the lights)
187 rule = RuleBuilder.create("demo1").withTags("scene").withName("Some name") //
188 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
190 ruleRegistry.update(rule); // Reset rule
192 sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
193 String uid = sceneEntry.getKey();
195 // Without store lights
196 body = "{ 'lights':['white1']}";
197 response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
198 .put(Entity.json(body));
199 assertEquals(200, response.getStatus());
200 assertThat(response.readEntity(String.class), containsString("lights"));
202 sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
203 assertThat(sceneEntry.getValue().name, is("Some name")); // should not have changed
204 assertThat(sceneEntry.getKey(), is(uid));
205 assertThat(sceneEntry.getValue().lights.get(0), is("switch1")); // storelightstate not set, lights not changed
208 body = "{ 'lights':['white1'], 'storelightstate':true }";
209 response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
210 .put(Entity.json(body));
211 assertEquals(200, response.getStatus());
212 assertThat(response.readEntity(String.class), containsString("lights"));
214 sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
215 assertThat(sceneEntry.getValue().lights.get(0), is("white1"));
219 public void getAll() {
220 Rule rule = RuleBuilder.create("demo1").withTags("scene") //
221 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
223 ruleRegistry.add(rule);
225 Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes").request().get();
226 Type type = new TypeToken<Map<String, HueSceneEntry>>() {
228 Map<String, HueSceneEntry> fromJson = new Gson().fromJson(response.readEntity(String.class), type);
229 assertTrue(fromJson.containsKey("demo1"));