1/* 2 * Copyright (c) 2021 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 16 17const testLocalStorage = tsuite("LocalStorage Tests", () => { 18 19 class TestSubscriber<C> implements ISinglePropertyChangeSubscriber<C> { 20 21 private id_: number = SubscriberManager.MakeId(); 22 private label_: string; 23 24 constructor(label: string) { 25 SubscriberManager.Add(this); 26 this.label_ = label; 27 } 28 29 // globally unique id 30 id__(): number { 31 return this.id_; 32 } 33 34 // inform the subscribed property 35 // that the subscriber is about to be deleted 36 // hence , unsubscribe 37 aboutToBeDeleted(): void { 38 SubscriberManager.Delete(this.id__()); 39 } 40 41 // implements IMultiPropertiesChangePublisher 42 hasChanged(newValue: C): void { 43 console.log(`TestSubscriber '${this.label_}' property changed value (shown stringified): '${ JSON.stringify(newValue) }' `); 44 } 45 } 46 47 localStorageInstance = new LocalStorage({ say: "Hello", name: "Gudio" }); 48 49 tcase("size", () => { 50 test("LocalStorage has initial two ObservedProperties", NativeLocalStorage.GetShared().size() == 2); 51 }); 52 53 tcase("LocalStorage has been init with value", () => { 54 test("added 'say'is in LocalStorage", NativeLocalStorage.GetShared().has("say")); 55 test("added 'name'is in LocalStorage", NativeLocalStorage.GetShared().has("name")); 56 57 test("added 'say' correct value", NativeLocalStorage.GetShared().get<string>("say") == "Hello"); 58 test("added 'name' wrong value", NativeLocalStorage.GetShared().get<string>("name") == "Gudio"); 59 }); 60 61 tcase("LocalStorage remembers self set boolean value", () => { 62 NativeLocalStorage.GetShared().setOrCreate<boolean>("aBool", true); 63 test("added 'aBool' correct boolean value", NativeLocalStorage.GetShared().get<boolean>("aBool")); 64 }); 65 66 tcase("LocalStorage remembers self set number value", () => { 67 NativeLocalStorage.GetShared().setOrCreate<number>("favorite", 47); 68 69 test("added 'favorite', has correct number value", NativeLocalStorage.GetShared().get<number>("favorite") == 47); 70 test("added 'favorite' converted to string is '47'", NativeLocalStorage.GetShared().get<string>("favorite") == "47"); 71 }); 72 73 let boolChangeListener = new TestSubscriber<boolean>("boolChangeListener"); 74 NativeLocalStorage.GetShared().subscribeToChangesOf("aBool", boolChangeListener); 75 let childboolChangeListenerSpy = spyOn(boolChangeListener, "hasChanged"); 76 77 tcase("Notifies listener on property value change", () => { 78 NativeLocalStorage.GetShared().set<boolean>("aBool", false); 79 test("boolean value readback correct", NativeLocalStorage.GetShared().get<boolean>("aBool") == false); 80 test("subscribing listener's 'hasChanged' called, param is newValue", childboolChangeListenerSpy.called && childboolChangeListenerSpy.args[0] == false); 81 }); 82 83 84 class TestAClass { 85 public a: number; 86 public b: number; 87 } 88 89 let objAClass1: TestAClass = { a: 1, b: 2 }; 90 let objAClass2: TestAClass = { a: 101, b: 201 }; 91 92 tcase("ObservedObject create, get, set", () => { 93 NativeLocalStorage.GetShared().setOrCreate<TestAClass>("objAClass", objAClass1); 94 test("ObservedObject create, value read back prop 'a'", (NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a == 1 && NativeLocalStorage.GetShared().get<TestAClass>("objAClass").b == 2)); 95 96 NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a = 47; 97 test("ObservedObject property value change, value read back", NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a == 47); 98 99 NativeLocalStorage.GetShared().set<TestAClass>("objAClass", objAClass2); 100 test("ObservedProperty of type ObservedObject set new ObservedObject, value read back", 101 NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a == 101 && NativeLocalStorage.GetShared().get<TestAClass>("objAClass").b == 201); 102 103 NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a = 102; 104 test("Followed by prop value change, value read back", 105 NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a == 102 && NativeLocalStorage.GetShared().get<TestAClass>("objAClass").b == 201); 106 }) 107 108 let objAChangeListener = new TestSubscriber<TestAClass>("objAChangeListener"); 109 NativeLocalStorage.GetShared().subscribeToChangesOf("objAClass", objAChangeListener); 110 let objAChangeListenerSpy1 = spyOn(objAChangeListener, "hasChanged"); 111 let objAClass3: TestAClass = { a: 101, b: 102 }; 112 113 114 tcase("Notifies listener on 'objAClass' property value change", () => { 115 NativeLocalStorage.GetShared().set<TestAClass>("objAClass", objAClass3); 116 test("ObservedObject property value change, value read back", NativeLocalStorage.GetShared().get<TestAClass>("objAClass").a == 101); 117 test("subscribing listener's 'hasChanged' called with correct param", objAChangeListenerSpy1.called && objAChangeListenerSpy1.args[0].b == 102); 118 }); 119 120 let objAChangeListenerSpy2 = spyOn(objAChangeListener, "hasChanged"); 121 122 tcase("Notifies listener on 'objAClass' property's property value change", () => { 123 NativeLocalStorage.GetShared().get<TestAClass>("objAClass").b = 103; 124 test("ObservedObject property value change, value read back", NativeLocalStorage.GetShared().get<TestAClass>("objAClass").b == 103); 125 test("subscribing listener's 'hasChanged' called with correct param", objAChangeListenerSpy2.called && objAChangeListenerSpy2.args[0].b == 103); 126 }); 127 128 tcase("cleanup ok", () => { 129 NativeLocalStorage.GetShared().unsubscribeFromChangesOf("aBool", boolChangeListener.id__()); 130 boolChangeListener.aboutToBeDeleted(); 131 132 NativeLocalStorage.GetShared().unsubscribeFromChangesOf("objAClass", objAChangeListener.id__()); 133 objAChangeListener.aboutToBeDeleted(); 134 135 const deleteOk = NativeLocalStorage.GetShared().delete("name") && NativeLocalStorage.GetShared().delete("say") && NativeLocalStorage.GetShared().delete("aBool") && NativeLocalStorage.GetShared().delete("favorite") && NativeLocalStorage.GetShared().delete("objAClass"); 136 test(`Deletion of props form AppStrorage without isuses`, deleteOk) 137 138 // test that manual cleanup has been complete, before calling NativeLocalStorage.GetShared().boutToBeDeleted(); 139 test(`AppStrorage has ${NativeLocalStorage.GetShared().size()} ObservedProperties: >${Array.from(NativeLocalStorage.GetShared().keys())}<, should be none.`, NativeLocalStorage.GetShared().size() == 0); 140 141 NativeLocalStorage.GetShared().aboutToBeDeleted(); 142 143 test(`SubscriberManager num of subscribers is ${SubscriberManager.NumberOfSubscribers()} should be 0 .`, 144 SubscriberManager.NumberOfSubscribers() == 0); 145 }); 146 147}); 148