1/* 2 * Copyright (c) 2022 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 nestedObsObjPropsPU = tsuite("Partial update: Nested Observed Object and Properties", () => { 17 18 @Observed 19 class ClassA { 20 public c: number; 21 22 constructor(c: number) { 23 this.c = c; 24 } 25 } 26 27 @Observed 28 class ClassB { 29 public a: ClassA; 30 31 constructor(a: ClassA) { 32 this.a = a; 33 } 34 } 35 36 class SubscribingView implements IMultiPropertiesChangeSubscriber { 37 38 private id_: number = SubscriberManager.MakeId(); 39 private label_: string; 40 41 constructor(label: string) { 42 SubscriberManager.Add(this); 43 this.label_ = label; 44 } 45 46 // globally unique id 47 id__(): number { 48 return this.id_; 49 } 50 51 // inform the subscribed property 52 // that the subscriber is about to be deleted 53 // hence , unsubscribe 54 aboutToBeDeleted(): void { 55 SubscriberManager.Delete(this.id__()); 56 } 57 58 // implements IMultiPropertiesChangePublisher 59 propertyHasChanged(info?: PropertyInfo): void { 60 console.log(`SubscribingView '${this.label_}' object property ${info ? info : 'unknown'} has changed.`); 61 } 62 } 63 64 tcase("Two views having a property referring to a1: ClassA", () => { 65 66 // View of property class B, has a property v1b1 67 let v1p1b1 = new SubscribingView("v1p1b1"); 68 let p1b1: ObservedPropertyObjectAbstractPU<ClassB> = new ObservedPropertyObjectPU<ClassB>(new ClassB(new ClassA(47)), v1p1b1, "p1-b1"); 69 let v1p1b1Spy = spyOn(v1p1b1, "propertyHasChanged"); 70 71 72 // 1. child view v1p1a1 of above View has a property 'a' 73 let v1p1a1 = new SubscribingView("v1p1a1"); 74 let p1a1: ObservedPropertyObjectAbstractPU<ClassA> = 75 new SynchedPropertyNesedObjectPU<ClassA>(p1b1.get().a, v1p1a1, "a"); 76 let v1p1a1Spy = spyOn(v1p1a1, "propertyHasChanged"); 77 78 test("readback p1a1", p1a1.get().c == 47); 79 80 // 2. child view v2p2a1 of above View has a property 'a' 81 let v2p2a1 = new SubscribingView("v2p2a1"); 82 let p2a1: ObservedPropertyObjectAbstractPU<ClassA> = 83 new SynchedPropertyNesedObjectPU<ClassA>(p1b1.get().a, v2p2a1, "a"); 84 let v2p2a1Spy = spyOn(v2p2a1, "propertyHasChanged"); 85 86 test("readback p2a1", p2a1.get().c == 47); 87 88 p1b1.get().a.c = 48; 89 90 test("readback p1a1", p1a1.get().c == 48); 91 test("readback p2a1", p2a1.get().c == 48) 92 test("readback p2b1", JSON.stringify(p1b1.get().a) == JSON.stringify({ "c": 48 })) 93 94 test("owning view of p1a1 (v1p1a1): propertyHasChanged called", v1p1a1Spy.called); 95 test("owning view of v2p2a1 (v2p2a1): propertyHasChanged called", v2p2a1Spy.called); 96 97 p1a1.aboutToBeDeleted(); 98 v1p1a1.aboutToBeDeleted(); 99 p2a1.aboutToBeDeleted(); 100 v2p2a1.aboutToBeDeleted(); 101 p1b1.aboutToBeDeleted(); 102 v1p1b1.aboutToBeDeleted(); 103 104 test(`After cleanup: SubscriberManager num of subscribers is ${SubscriberManager.NumberOfSubscribers()} should be 0 .`, 105 SubscriberManager.NumberOfSubscribers() == 0); 106 107 }); 108 109}); 110