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