]> git.basschouten.com Git - openhab-addons.git/blob
4928e519d91ceee6d19340f9637a295830ff5bb3
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.io.hueemulation.internal.rest;
14
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.*;
18
19 import java.io.IOException;
20 import java.lang.reflect.Type;
21 import java.util.Map;
22 import java.util.Map.Entry;
23
24 import javax.ws.rs.client.Entity;
25 import javax.ws.rs.core.Response;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.glassfish.jersey.server.ResourceConfig;
29 import org.hamcrest.CoreMatchers;
30 import org.junit.jupiter.api.AfterEach;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.openhab.core.automation.Rule;
34 import org.openhab.core.automation.RuleRegistry;
35 import org.openhab.core.automation.util.RuleBuilder;
36 import org.openhab.core.items.GenericItem;
37 import org.openhab.core.items.GroupItem;
38 import org.openhab.core.items.ItemRegistry;
39 import org.openhab.core.library.items.ColorItem;
40 import org.openhab.core.library.items.DimmerItem;
41 import org.openhab.core.library.items.RollershutterItem;
42 import org.openhab.core.library.items.SwitchItem;
43 import org.openhab.core.library.types.HSBType;
44 import org.openhab.core.library.types.OnOffType;
45 import org.openhab.core.library.types.PercentType;
46 import org.openhab.core.types.Command;
47 import org.openhab.core.types.State;
48 import org.openhab.io.hueemulation.internal.ConfigStore;
49 import org.openhab.io.hueemulation.internal.dto.HueSceneEntry;
50 import org.openhab.io.hueemulation.internal.rest.mocks.DummyItemRegistry;
51 import org.openhab.io.hueemulation.internal.rest.mocks.DummyRuleRegistry;
52
53 import com.google.gson.Gson;
54 import com.google.gson.reflect.TypeToken;
55
56 /**
57  * Tests for various scene API endpoints.
58  *
59  * @author David Graeff - Initial contribution
60  */
61 @NonNullByDefault
62 public class SceneTests {
63     protected @NonNullByDefault({}) CommonSetup commonSetup;
64     protected @NonNullByDefault({}) ConfigStore cs;
65     protected @NonNullByDefault({}) ItemRegistry itemRegistry;
66     protected @NonNullByDefault({}) RuleRegistry ruleRegistry;
67
68     Scenes subject = new Scenes();
69
70     private void addItemToReg(GenericItem item, State state, String tag) {
71         item.setState(state);
72         item.addTag(tag);
73         itemRegistry.add(item);
74     }
75
76     @BeforeEach
77     public void setUp() throws IOException {
78         commonSetup = new CommonSetup(false);
79         this.cs = commonSetup.cs;
80
81         itemRegistry = new DummyItemRegistry();
82         ruleRegistry = new DummyRuleRegistry();
83
84         subject.cs = commonSetup.cs;
85         subject.userManagement = commonSetup.userManagement;
86         subject.itemRegistry = itemRegistry;
87         subject.ruleRegistry = ruleRegistry;
88         subject.activate();
89
90         // Add simulated lights
91         addItemToReg(new SwitchItem("switch1"), OnOffType.ON, "Switchable");
92         addItemToReg(new ColorItem("color1"), HSBType.BLUE, "ColorLighting");
93         addItemToReg(new DimmerItem("white1"), new PercentType(12), "Lighting");
94         addItemToReg(new RollershutterItem("roller1"), new PercentType(12), "Lighting");
95         addItemToReg(new DimmerItem("white1"), new PercentType(12), "Lighting");
96         addItemToReg(new GroupItem("group1"), OnOffType.ON, "Switchable");
97
98         commonSetup.start(new ResourceConfig().registerInstances(subject));
99     }
100
101     @AfterEach
102     public void tearDown() throws Exception {
103         commonSetup.dispose();
104     }
105
106     @SuppressWarnings("null")
107     @Test
108     public void addUpdateRemoveSceneToRegistry() {
109         Rule rule = RuleBuilder.create("demo1").withTags("scene") //
110                 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
111
112         ruleRegistry.add(rule);
113
114         HueSceneEntry sceneEntry = cs.ds.scenes.get("demo1");
115         assertThat(sceneEntry.lights.get(0), CoreMatchers.is("switch1"));
116
117         // Update
118         rule = RuleBuilder.create("demo1").withTags("scene") //
119                 .withActions(Scenes.actionFromState("white1", (Command) OnOffType.ON)).build();
120         ruleRegistry.update(rule);
121
122         sceneEntry = cs.ds.scenes.get("demo1");
123         assertThat(sceneEntry.lights.get(0), CoreMatchers.is("white1"));
124
125         // Remove
126
127         ruleRegistry.remove("demo1");
128         sceneEntry = cs.ds.scenes.get("demo1");
129         assertThat(sceneEntry, CoreMatchers.nullValue());
130     }
131
132     @SuppressWarnings("null")
133     @Test
134     public void addGetRemoveSceneViaRest() {
135         // 1. Create
136         String body = "{ 'name':'Cozy dinner', 'recycle':false, 'lights':['switch1','white1'], 'type':'LightScene'}";
137         Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes").request()
138                 .post(Entity.json(body));
139         assertEquals(200, response.getStatus());
140         assertThat(response.readEntity(String.class), containsString("success"));
141
142         // 1.1 Check for scene entry
143         Entry<String, HueSceneEntry> entry = cs.ds.scenes.entrySet().stream().findAny().get();
144         assertThat(entry.getValue().name, is("Cozy dinner"));
145         assertThat(entry.getValue().lights.get(0), is("switch1"));
146         assertThat(entry.getValue().lights.get(1), is("white1"));
147
148         // 1.2 Check for rule
149         Rule rule = ruleRegistry.get(entry.getKey());
150         assertThat(rule.getName(), is("Cozy dinner"));
151         assertThat(rule.getActions().get(0).getId(), is("switch1"));
152         assertThat(rule.getActions().get(1).getId(), is("white1"));
153
154         // 2. Get
155         response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/" + entry.getKey()).request()
156                 .get();
157         assertEquals(200, response.getStatus());
158         HueSceneEntry fromJson = new Gson().fromJson(response.readEntity(String.class), HueSceneEntry.class);
159         assertThat(fromJson.name, is(entry.getValue().name));
160
161         // 3. Remove
162         response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/" + entry.getKey()).request()
163                 .delete();
164         assertEquals(200, response.getStatus());
165         assertTrue(cs.ds.scenes.isEmpty());
166     }
167
168     @SuppressWarnings("null")
169     @Test
170     public void updateSceneViaRest() {
171         Rule rule = RuleBuilder.create("demo1").withTags("scene").withName("Some name") //
172                 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
173
174         ruleRegistry.add(rule);
175
176         // 3. Modify (just the name)
177         String body = "{ 'name':'A new name'}";
178         Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
179                 .put(Entity.json(body));
180         assertEquals(200, response.getStatus());
181         assertThat(response.readEntity(String.class), containsString("name"));
182
183         Entry<String, HueSceneEntry> sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
184         assertThat(sceneEntry.getValue().name, is("A new name"));
185         assertThat(sceneEntry.getValue().lights.get(0), is("switch1")); // nothing else should have changed
186
187         // 3. Modify (just the lights)
188         rule = RuleBuilder.create("demo1").withTags("scene").withName("Some name") //
189                 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
190
191         ruleRegistry.update(rule); // Reset rule
192
193         sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
194         String uid = sceneEntry.getKey();
195
196         // Without store lights
197         body = "{ 'lights':['white1']}";
198         response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
199                 .put(Entity.json(body));
200         assertEquals(200, response.getStatus());
201         assertThat(response.readEntity(String.class), containsString("lights"));
202
203         sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
204         assertThat(sceneEntry.getValue().name, is("Some name")); // should not have changed
205         assertThat(sceneEntry.getKey(), is(uid));
206         assertThat(sceneEntry.getValue().lights.get(0), is("switch1")); // storelightstate not set, lights not changed
207
208         // With store lights
209         body = "{ 'lights':['white1'], 'storelightstate':true }";
210         response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes/demo1").request()
211                 .put(Entity.json(body));
212         assertEquals(200, response.getStatus());
213         assertThat(response.readEntity(String.class), containsString("lights"));
214
215         sceneEntry = cs.ds.scenes.entrySet().stream().findAny().get();
216         assertThat(sceneEntry.getValue().lights.get(0), is("white1"));
217     }
218
219     @Test
220     public void getAll() {
221         Rule rule = RuleBuilder.create("demo1").withTags("scene") //
222                 .withActions(Scenes.actionFromState("switch1", (Command) OnOffType.ON)).build();
223
224         ruleRegistry.add(rule);
225
226         Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/scenes").request().get();
227         Type type = new TypeToken<Map<String, HueSceneEntry>>() {
228         }.getType();
229         Map<String, HueSceneEntry> fromJson = new Gson().fromJson(response.readEntity(String.class), type);
230         assertTrue(fromJson.containsKey("demo1"));
231     }
232 }