• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
16const testAppStorageArray = tsuite("AppStorage Array", () => {
17
18  class ArrayChangeSubscriber implements ISinglePropertyChangeSubscriber<number[]> {
19
20    private id_: number = SubscriberManager. MakeId();
21
22    constructor() {
23      AppStorage.SubscribeToChangesOf("arr", this);
24      SubscriberManager.Add(this);
25    }
26
27    // globally unique id
28    id__(): number {
29      return this.id_;
30    }
31
32    // inform the subscribed property
33    // that the subscriber is about to be deleted
34    // hence , unsubscribe
35    aboutToBeDeleted(owningView?: IPropertySubscriber): void {
36      AppStorage.UnsubscribeFromChangesOf("arr", this.id__());
37      SubscriberManager.Delete(this.id__());
38    }
39
40    // get informed after the property has changed.
41    hasChanged(newValue: number[]): void {
42      console.log(`ArrayChangeSubscriber.newValue ${newValue}.`)
43    }
44  }
45
46  class ClassPropertyChangeSubscriber<T extends Object>
47    implements ISinglePropertyChangeSubscriber<T>, IMultiPropertiesChangeSubscriber {
48
49    private id_: number = SubscriberManager.MakeId();
50    private classInfo_: string;
51
52    constructor(classInfo: string) {
53      this.classInfo_ = classInfo;
54      SubscriberManager.Add(this);
55    }
56
57    // globally unique id
58    id__(): number {
59      return this.id_;
60    }
61
62    // inform the subscribed property
63    // that the subscriber is about to be deleted
64    // hence , unsubscribe
65    aboutToBeDeleted(owningView?: IPropertySubscriber): void {
66      SubscriberManager.Delete(this.id__());
67    }
68
69    // get informed after the property has changed.
70    // implements: SinglePropertyChangeSubscriber<T>
71    hasChanged(newValue: T): void {
72      console.log(`Class ${this.classInfo_} object inside property has changed. newValue ${newValue}.`)
73    }
74
75    // implements IMultiPropertiesChangePublisher
76    propertyHasChanged(info?: PropertyInfo): void {
77      console.log(`Class ${this.classInfo_} object property ${info ? info : 'unknown'} has changed.`);
78    }
79  }
80
81  tcase("ObservedObject.IsObservedObject test", () => {
82
83    test("array", !ObservedObject.IsObservedObject([1, 2, 3]));
84    test("object", !ObservedObject.IsObservedObject({ a: 1 }));
85    test("number", !ObservedObject.IsObservedObject(1));
86    test("boolean", !ObservedObject.IsObservedObject(true));
87    test("undefined", !ObservedObject.IsObservedObject(undefined));
88    test("undefined", !ObservedObject.IsObservedObject(undefined));
89
90    let sub1 = new ClassPropertyChangeSubscriber<number[]>("number[] #1 sub");
91    let arr1 = ObservedObject.createNew([1, 2, 3], sub1);
92    let sub2 = new ClassPropertyChangeSubscriber<number[]>("number[] #2 sub");
93    let arr2 = ObservedObject.createNew({ a: 1 }, sub2);
94
95    test("observed array", ObservedObject.IsObservedObject(arr1));
96    test("observed object", ObservedObject.IsObservedObject(arr2));
97
98    ObservedObject.removeOwningProperty(arr1, sub1);
99    sub1.aboutToBeDeleted();
100
101    ObservedObject.removeOwningProperty(arr2, sub2);
102    sub2.aboutToBeDeleted();
103  });
104
105
106  tcase("create and read back", () => {
107    let arr: number[] = [1, 2, 3, 4];
108    AppStorage.SetOrCreate<number[]>("arr", arr);
109
110    test("AppStrorage has initial one ObservedProperties", AppStorage.Size() == 1);
111    test("Initial array value readback.", AppStorage.Get<number[]>("arr").toString() == arr.toString());
112    test(`Initial array value readback, check Array.isArray`, Array.isArray(AppStorage.Get<number[]>("arr")));
113    test(`Initial array value readback, check instance of ObservedObject`, ObservedObject.IsObservedObject(AppStorage.Get<number[]>("arr")));
114  });
115
116  tcase("push to array", () => {
117    let arrSub = new ArrayChangeSubscriber();
118    let spyArrayChange = spyOn(arrSub, "hasChanged");
119    AppStorage.Get<number[]>("arr").push(5);
120    test("Changed array value readback", AppStorage.Get<number[]>("arr").toString() == [1, 2, 3, 4, 5].toString());
121    test(`hasChanged was called`, spyArrayChange.called);
122    test(`hasChanged param is the correct changed array.`, spyArrayChange.args[0].toString() == [1, 2, 3, 4, 5].toString());
123    test(`Initial array value readback, check instance of ObservedObject`, ObservedObject.IsObservedObject(AppStorage.Get<number[]>("arr")));
124    arrSub.aboutToBeDeleted();
125  });
126
127  tcase("change property value gets observed #1", () => {
128    let arrSub = new ArrayChangeSubscriber();
129    let spyArrayChange = spyOn(arrSub, "hasChanged");
130
131    AppStorage.Set<number[]>("arr", [2, 3, 4]);
132
133    test("Changed array value readback", AppStorage.Get<number[]>("arr").toString() == [2, 3, 4].toString());
134    test(`hasChanged was called`, spyArrayChange.called);
135    test(`hasChanged param is the correct changed array.`, spyArrayChange.args[0].toString() == [2, 3, 4].toString());
136    test(`Initial array value readback, check instance of ObservedObject`, ObservedObject.IsObservedObject(AppStorage.Get<number[]>("arr")));
137
138    arrSub.aboutToBeDeleted();
139  });
140
141
142  tcase("change property value gets observed #2", () => {
143    let arrSub = new ArrayChangeSubscriber();
144    AppStorage.Set<number[]>("arr", [2, 3, 4]);
145    let spyArrayChange = spyOn(arrSub, "hasChanged");
146    AppStorage.Get<number[]>("arr")[1] = 7;
147
148    test("Changed array value readback", AppStorage.Get<number[]>("arr").toString() == [2, 7, 4].toString());
149    test(`hasChanged was called`, spyArrayChange.called);
150    test(`hasChanged param is the correct changed array.`, spyArrayChange.args[0].toString() == [2, 7, 4].toString());
151    arrSub.aboutToBeDeleted();
152  });
153
154  tcase("ObservedObject Array proxying is transparent", () => {
155    AppStorage.Set<number[]>("arr", [2, 3, 4]);
156    let link = AppStorage.Link<number[]>("arr");
157    test("link readback value OK", link.get().toString() == [2, 3, 4].toString());
158    test("link readback value OK", link.get().length == 3);
159    test("Array.isArray(link) OK", Array.isArray(link.get()));
160    test("link value is instance of ObservedObject OK", ObservedObject.IsObservedObject(link.get()));
161
162    const rawArray = ObservedObject.GetRawObject(link.get());
163    test("ObservedObject.GetRawObject value readback OK", rawArray.toString() == [2, 3, 4].toString());
164    test("GetRawObject on link value returns a raw", !ObservedObject.IsObservedObject(rawArray));
165
166    link.aboutToBeDeleted();
167  });
168
169
170  tcase("cleanup ok", () => {
171
172    // manual cleanup to see everything works as expected
173    const deleteOk = AppStorage.Delete("arr");
174    test(`Deletion of props form AppStrorage without isuses`, deleteOk);
175    test(`AppStrorage has ${AppStorage.Size()} ObservedProperties: >${Array.from(AppStorage.Keys())}<, should be none.`, AppStorage.Size() == 0);
176
177    test(`SubscriberManager num of subscribers us ${SubscriberManager.NumberOfSubscribers()} should be 0 .`,
178       SubscriberManager.NumberOfSubscribers() == 0);
179
180    // this will do nothing because manual cleanup was done already
181    AppStorage.AboutToBeDeleted();
182  });
183});
184