1/* 2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16const testAppStorage = tsuite("AppStorage", () => { 17 18 tcase("size", () => { 19 AppStorage.createSingleton({say: "Hello", name: "Gudio"}); 20 test("AppStrorage has initial two ObservedProperties", AppStorage.size() == 2); 21 }); 22 23 tcase("AppStorage has self set value", () => { 24 test("added 'say' is in AppStrorage", AppStorage.has("say")); 25 }); 26 27 tcase("AppStorage remembers self set value", () => { 28 test("added 'say' wrong value", AppStorage.get<string>("say") == "Hello"); 29 test("added 'name' wrong value", AppStorage.get<string>("name") == "Gudio"); 30 }); 31 32 tcase("AppStorage remembers self set boolean value", () => { 33 AppStorage.setOrCreate<boolean>("true", true); 34 test("added 'true' wrong boolean value", AppStorage.get<boolean>("true")); 35 }); 36 37 tcase("AppStorage remembers self set number value", () => { 38 AppStorage.setOrCreate<number>("favorite", 47); 39 40 test("added 'favorite', has correct number value", AppStorage.get<number>("favorite") == 47); 41 test("added 'favorite' converted to string is '47'", AppStorage.get<string>("favorite") == "47"); 42 }); 43 44 45 var link1: SubscribedAbstractProperty<string> = AppStorage.link<string>("say"); 46 var link2: SubscribedAbstractProperty<string> = AppStorage.link<string>("say"); 47 48 tcase("AppStorage and link1 update from link1.set", 49 () => { 50 link1.set("Anton"); 51 test("AppStorage: 'say' expected updated value is `Anton`.", AppStorage.get<string>("say") == "Anton"); 52 test("SyncedPropertyTwoWay#1: 'say' expected updated value is `Anton`.", link2.get() == "Anton"); 53 }); 54 55 tcase("AppStorage and link2 update from link1.set", () => { 56 link1.set("Hanna"); 57 test("AppStorage: 'say' expected updated value is `Hanna`.", AppStorage.get<string>("say") == "Hanna"); 58 test("SyncedPropertyTwoWay#2: 'say' expected updated value is `Hanna`.", link2.get() == "Hanna"); 59 }); 60 61 tcase("link1 and link2 update from AppStorage.set", () => { 62 AppStorage.set<string>("say", "Paul"); 63 test("SyncedPropertyTwoWay#1: 'say' expected updated value is `Paul`.", link1.get() == "Paul"); 64 test("SyncedPropertyTwoWay#2: 'say' expected updated value is `Paul`.", link2.get() == "Paul"); 65 }); 66 67 AppStorage.set("say", "Guido"); 68 let prop = AppStorage.prop("say"); 69 70 tcase("prop.get", () => { 71 test("prop value expected `Guido`.", prop.get() == "Guido"); 72 }); 73 74 75 tcase("prop.set change value only locally.", () => { 76 prop.set("Hanna"); 77 test("prop changed value expected `Hanna`.", prop.get() == "Hanna"); 78 test("link1 unchanged value expected `Guido`.", link1.get() == "Guido"); 79 test("app unchanged value expected `Guido`.", AppStorage.get("say") == "Guido"); 80 }) 81 82 tcase("appstorage set changes prop values", () => { 83 AppStorage.set("say", "Anton"); 84 test("prop changed value expected `Anton`.", prop.get() == "Anton"); 85 }) 86 87 tcase("unsubscribe proptoLink1, linkToLink2", () => { 88 const asSubscribers = AppStorage.numberOfSubscribersTo("say"); 89 link2.aboutToBeDeleted(); 90 test("link2 subscriber has been unsubscribed from as", AppStorage.numberOfSubscribersTo("say") == asSubscribers - 1); 91 }) 92 93 class TestAClass { 94 public a: number; 95 public b: number; 96 } 97 98 let objAClass1: TestAClass = { a: 1, b: 2 }; 99 let objAClass2: TestAClass = { a: 101, b: 201 }; 100 101 tcase("ObservedObject create, get, set", () => { 102 AppStorage.setOrCreate<TestAClass>("objAClass", objAClass1); 103 test("ObservedObject create, value read back prop 'a'", (AppStorage.get<TestAClass>("objAClass").a == 1 && AppStorage.get<TestAClass>("objAClass").b == 2)); 104 105 AppStorage.get<TestAClass>("objAClass").a = 47; 106 test("ObservedObject property value change, value read back", AppStorage.get<TestAClass>("objAClass").a == 47); 107 108 AppStorage.set<TestAClass>("objAClass", objAClass2); 109 test("ObservedProperty of type ObservedObject set new ObservedObject, value read back", 110 AppStorage.get<TestAClass>("objAClass").a == 101 && AppStorage.get<TestAClass>("objAClass").b == 201); 111 112 AppStorage.get<TestAClass>("objAClass").a = 102; 113 test("Followed by prop value change, value read back", 114 AppStorage.get<TestAClass>("objAClass").a == 102 && AppStorage.get<TestAClass>("objAClass").b == 201); 115 }) 116 117 let linktoObsObj = AppStorage.link<TestAClass>("objAClass"); 118 119 tcase("ObservedObject Link create, get, set", () => { 120 121 test("link to ObservedObject, get value", linktoObsObj.get().b == 201); 122 123 linktoObsObj.get().b = 203; 124 test("link to ObservedObject, set value, read back link value", linktoObsObj.get().b == 203); 125 test("link to ObservedObject, set value, read back value from AppStorage", 126 AppStorage.get<TestAClass>("objAClass").b == 203); 127 }) 128 129 tcase("ObservedObject Prop to Link create, get, set", () => { 130 let propToLinktoObsObj = linktoObsObj.createProp(undefined, "propToLinkObj"); 131 132 test("prop to link to ObservedObject, get value", propToLinktoObsObj.get().b == 203); 133 134 propToLinktoObsObj.get().b = 204; 135 test("prop to link to ObservedObject, set value locally, read back prop value", propToLinktoObsObj.get().b == 204); 136 test("prop to link to ObservedObject, set value locally, read back link value", linktoObsObj.get().b == 203); 137 test("prop to link to ObservedObject, set value locally, read back value from AppStorage", 138 AppStorage.get<TestAClass>("objAClass").b == 203); 139 linktoObsObj.aboutToBeDeleted(); 140 propToLinktoObsObj.aboutToBeDeleted(); 141 }) 142 let proptoObsObj = AppStorage.prop<TestAClass>("objAClass"); 143 144 tcase("ObservedObject Prop create, get, set", () => { 145 146 test("prop to ObservedObject, get value", proptoObsObj.get().b == 203); 147 148 proptoObsObj.get().b = 201; 149 test("prop to ObservedObject, set value locally, read back prop value", proptoObsObj.get().b == 201); 150 test("prop to ObservedObject, set value locally, read back original prop value from AppStorage", 151 AppStorage.get<TestAClass>("objAClass").b == 203); 152 153 AppStorage.set<TestAClass>("objAClass", { a: 42, b: 84 }); 154 test("prop to ObservedObject, set value to AppStorage, read back from AppStorage", 155 AppStorage.get<TestAClass>("objAClass").b == 84); 156 test("prop to ObservedObject, set value to AppStorage, read back from prop", proptoObsObj.get().b == 84); 157 }) 158 159 tcase("ObservedObject Prop to Prop create, get, set", () => { 160 let propToPropObsObj = proptoObsObj.createProp(undefined, "propToProp"); 161 162 test("prop to prop to ObservedObject, get value", propToPropObsObj.get().a == 42); 163 164 propToPropObsObj.get().a = 201; 165 test("prop to prop to ObservedObject, set value locally, read back prop value", propToPropObsObj.get().a == 201); 166 test("prop to prop to ObservedObject, set value locally, read back value from parent prop", proptoObsObj.get().a == 42); 167 test("prop to prop to ObservedObject, set value locally, read back original prop value from AppStorage", 168 AppStorage.get<TestAClass>("objAClass").a == 42); 169 170 AppStorage.set<TestAClass>("objAClass", { a: 421, b: 842 }); 171 test("prop to prop to ObservedObject, set value to AppStorage, read back from AppStorage", 172 AppStorage.get<TestAClass>("objAClass").b == 842); 173 test("prop to prop toObservedObject, set value to AppStorage, read back from prop", propToPropObsObj.get().b == 842); 174 test("prop to prop toObservedObject, set value to AppStorage, read back from parent prop", proptoObsObj.get().b == 842); 175 176 propToPropObsObj.aboutToBeDeleted(); 177 proptoObsObj.aboutToBeDeleted(); 178 }) 179 180 tcase("ObservedObject Prop create, get, set", () => { 181 182 test("prop to ObservedObject, get value", proptoObsObj.get().b == 203); 183 184 proptoObsObj.get().b = 201; 185 test("prop to ObservedObject, set value locally, read back prop value", proptoObsObj.get().b == 201); 186 test("prop to ObservedObject, set value locally, read back original prop value from AppStorage", 187 AppStorage.get<TestAClass>("objAClass").b == 203); 188 189 AppStorage.set<TestAClass>("objAClass", { a: 42, b: 84 }); 190 test("prop to ObservedObject, set value to AppStorage, read back from AppStorage", 191 AppStorage.get<TestAClass>("objAClass").b == 84); 192 test("prop to ObservedObject, set value to AppStorage, read back from prop", proptoObsObj.get().b == 84); 193 }) 194 195 tcase("ObservedObject Prop to Prop create, get, set", () => { 196 let propToPropObsObj = proptoObsObj.createProp(undefined, "propToProp"); 197 198 test("prop to prop to ObservedObject, get value", propToPropObsObj.get().a == 42); 199 200 propToPropObsObj.get().a = 201; 201 test("prop to prop to ObservedObject, set value locally, read back prop value", propToPropObsObj.get().a == 201); 202 test("prop to prop to ObservedObject, set value locally, read back value from parent prop", proptoObsObj.get().a == 42); 203 test("prop to prop to ObservedObject, set value locally, read back original prop value from AppStorage", 204 AppStorage.get<TestAClass>("objAClass").a == 42); 205 206 AppStorage.Set<TestAClass>("objAClass", { a: 421, b: 842 }); 207 test("prop to prop to ObservedObject, set value to AppStorage, read back from AppStorage", 208 AppStorage.get<TestAClass>("objAClass").b == 842); 209 test("prop to prop toObservedObject, set value to AppStorage, read back from prop", propToPropObsObj.get().b == 842); 210 test("prop to prop toObservedObject, set value to AppStorage, read back from parent prop", proptoObsObj.get().b == 842); 211 212 propToPropObsObj.aboutToBeDeleted(); 213 proptoObsObj.aboutToBeDeleted(); 214 }) 215 216 tcase("cleanup ok", () => { 217 link1.aboutToBeDeleted(); 218 prop.aboutToBeDeleted(); 219 // note link2 and linktoLink2 have been deleted already earlier in this test suite! 220 221 const deleteOk = AppStorage.delete("name") && AppStorage.delete("say") && AppStorage.delete("true") && AppStorage.delete("favorite") && AppStorage.delete("objAClass"); 222 test(`Deletion of props form AppStrorage without isuses`, deleteOk) 223 224 // test that manual cleanup has been complete, before calling AppStorage.NboutToBeDeleted(); 225 test(`AppStrorage has ${AppStorage.size()} ObservedProperties: >${Array.from(AppStorage.keys())}<, should be none.`, AppStorage.size() == 0); 226 227 AppStorage.aboutToBeDeleted(); 228 229 test(`SubscriberManager num of subscribers is ${SubscriberManager.NumberOfSubscribers()} should be 0 .`, 230 SubscriberManager.NumberOfSubscribers() == 0); 231 232 233 }); 234 235}); 236