• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / 3b0f2033-3042-471a-8924-af474a7789df

03 Apr 2024 08:06AM UTC coverage: 90.399% (-0.005%) from 90.404%
3b0f2033-3042-471a-8924-af474a7789df

Pull #3063

circleci

minlovehua
Merge branch 'master' of github.com:atinc/ngx-tethys into minlovehua/use-cdk-coercion
Pull Request #3063: refactor(util): mark coerceBooleanProperty, coerceNumberValue, and coerceCssPixelValue as deprecated, and use angular cdk to replace them #INFR-12096

5410 of 6635 branches covered (81.54%)

Branch coverage included in aggregate %.

14 of 16 new or added lines in 4 files covered. (87.5%)

6 existing lines in 2 files now uncovered.

13176 of 13925 relevant lines covered (94.62%)

979.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.92
/src/util/helpers/helpers.ts
1
import { _isNumberValue, coerceCssPixelValue as coerceCssPixel } from '@angular/cdk/coercion';
2
import { ElementRef, TemplateRef } from '@angular/core';
3

4
export function isUndefined(value: any): value is undefined {
4,047✔
5
    return value === undefined;
6
}
7

1,098✔
8
export function isNull(value: any): value is null {
9
    return value === null;
10
}
4,010✔
11

12
export function isUndefinedOrNull(value: any): value is undefined | null {
13
    return isUndefined(value) || isNull(value);
42,535✔
14
}
15

16
export function isArray<T = any>(value: any): value is Array<T> {
19,194✔
17
    return value && baseGetTag(value) === '[object Array]';
18
}
19

18,416✔
20
export function isEmpty(value?: any): boolean {
21
    return !(isArray(value) && value.length > 0);
22
}
15,646✔
23

24
export function isString(value?: any): value is string {
25
    return typeof value == 'string' || (!isArray(value) && isObjectLike(value) && baseGetTag(value) === '[object String]');
10,551✔
26
}
10,551✔
27

10,551✔
28
function isObjectLike(value: any): value is object {
10,551!
29
    return value !== null && typeof value === 'object';
10,551!
30
}
×
31

32
function baseGetTag(value: any) {
10,551✔
33
    const objectProto = Object.prototype;
10,549✔
34
    const hasOwnProperty = objectProto.hasOwnProperty;
35
    const toString = objectProto.toString;
2✔
36
    const symToStringTag = typeof Symbol !== 'undefined' ? Symbol.toStringTag : undefined;
2✔
37

2✔
38
    if (value == null) {
2✔
39
        return value === undefined ? '[object Undefined]' : '[object Null]';
2✔
40
    }
×
41
    if (!(symToStringTag && symToStringTag in Object(value))) {
42
        return toString.call(value);
43
    }
2✔
44
    const isOwn = hasOwnProperty.call(value, symToStringTag);
2!
45
    const tag = value[symToStringTag];
×
46
    let unmasked = false;
×
47
    try {
48
        value[symToStringTag] = undefined;
49
        unmasked = true;
×
50
    } catch (e) {}
51

52
    const result = toString.call(value);
2✔
53
    if (unmasked) {
54
        if (isOwn) {
55
            value[symToStringTag] = tag;
970✔
56
        } else {
57
            delete value[symToStringTag];
58
        }
59
    }
60
    return result;
479✔
61
}
479✔
62

63
export function isNumber(value: any): value is number {
64
    return typeof value === 'number' || (isObjectLike(value) && baseGetTag(value) === '[object Number]');
1,262,090✔
65
}
1,262,090✔
66

67
export function isObject(value: any): value is object {
68
    // Avoid a V8 JIT bug in Chrome 19-20.
9✔
69
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
9✔
70
    const type = typeof value;
71
    return !!value && (type === 'object' || type === 'function');
72
}
624✔
73

74
export function isFunction(value: any): value is Function {
75
    const type = typeof value;
7,348✔
76
    return !!value && type === 'function';
7,348✔
77
}
7,348✔
78

70✔
79
export function isDate(value: any): value is Date {
80
    const type = typeof value;
7,348✔
81
    return !!value && type === 'object' && !!value.getTime;
82
}
83

402!
84
export function coerceArray<T>(value: T | T[]): T[] {
×
85
    return Array.isArray(value) ? value : [value];
86
}
402✔
87

402✔
88
export function get(object: any, path: string, defaultValue?: any): any {
402✔
89
    const paths = path.split('.');
402✔
90
    let result = object[paths.shift()];
402✔
91
    while (result && paths.length) {
402✔
92
        result = result[paths.shift()];
402✔
93
    }
402!
94
    return result === undefined ? defaultValue : result;
402!
95
}
402✔
96

402✔
97
export function set(object: any, path: string, value: any): void {
402✔
98
    if (object == null) {
99
        return object;
100
    }
×
101
    const paths = path.split('.');
×
102
    let index = -1;
103
    const length = paths.length;
104
    const lastIndex = length - 1;
105
    let nested = object;
×
106
    while (nested !== null && ++index < length) {
107
        const key = paths[index];
402✔
108
        if (isObject(nested)) {
109
            if (index === lastIndex) {
110
                nested[key] = value;
8✔
111
                nested = nested[key];
112
                break;
113
            } else {
×
114
                if (nested[key] == null) {
115
                    nested[key] = {};
116
                }
28!
117
            }
28✔
118
        }
28✔
119
        nested = nested[key];
3✔
120
    }
3✔
121
    return object;
1✔
122
}
123

2✔
124
export function isBoolean(value: any): value is boolean {
1✔
125
    return value === true || value === false || (isObjectLike(value) && baseGetTag(value) === '[object Boolean]');
126
}
1!
127

×
128
export function isClass(value: any): value is Function {
129
    return isFunction(value) && /^\s*class\s+/.test(value.toString());
130
}
131

26✔
132
export function htmlElementIsEmpty(element: HTMLElement) {
133
    if (element && element.childNodes) {
134
        const nodes = element.childNodes;
38✔
135
        for (let i = 0; i < nodes.length; i++) {
38✔
136
            const node = nodes[i];
38✔
137
            if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).outerHTML.toString().trim().length !== 0) {
38!
138
                return false;
×
139
            } else if (node.nodeType === Node.TEXT_NODE && node.textContent.toString().trim().length !== 0) {
38✔
140
                return false;
38✔
141
            } else if (node.nodeType !== Node.COMMENT_NODE) {
38✔
142
                return false;
38✔
143
            }
32✔
144
        }
145
    }
146
    return true;
6✔
147
}
148

149
export function hexToRgb(hexValue: string, alpha?: number): string {
150
    const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
3✔
151
    const hex = hexValue.replace(rgx, (m: any, r: any, g: any, b: any) => r + r + g + g + b + b);
2✔
152
    const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1✔
153
    if (!rgb) return;
154
    const resultR = parseInt(rgb[1], 16);
155
    const resultG = parseInt(rgb[2], 16);
1✔
156
    const resultB = parseInt(rgb[3], 16);
157
    if (!isUndefinedOrNull(alpha)) {
158
        return `rgba(${resultR}, ${resultG}, ${resultB}, ${alpha})`;
159
    } else {
1✔
160
        return `rgb(${resultR}, ${resultG}, ${resultB})`;
161
    }
162
}
14✔
163

28✔
164
export function dateToUnixTimestamp(date: Date | number): number {
165
    if (isNumber(date)) {
166
        if (date.toString().length === 10) {
31✔
167
            return date as number;
31✔
168
        } else {
60✔
169
            return parseInt(((date as number) / 1000).toFixed(0), 10);
60✔
170
        }
171
    } else {
31✔
172
        return parseInt(((date as Date).getTime() / 1000).toFixed(0), 10);
173
    }
174
}
5✔
175

5✔
176
export function clamp(value: number, min = 0, max = 100) {
9✔
177
    return Math.max(min, Math.min(max, value));
9✔
178
}
179

5✔
180
export function keyBy<T>(array: T[], key: T extends object ? keyof T : never): { [key: string]: T } {
181
    const result: { [key: string]: T } = {};
182
    array.forEach(item => {
8✔
183
        const keyValue = item[key];
184
        (result as any)[keyValue] = item;
185
    });
8!
186
    return result;
8✔
187
}
16✔
188

16✔
189
export function indexKeyBy<T>(array: T[], key: T extends object ? keyof T : never): { [key: string]: number } {
190
    const result: { [key: string]: number } = {};
191
    array.forEach((item, index) => {
192
        const keyValue = item[key];
×
193
        (result as any)[keyValue] = index;
194
    });
195
    return result;
196
}
34✔
197

198
function upperFirst(string: string): string {
199
    return string.slice(0, 1).toUpperCase() + string.slice(1);
14,860✔
200
}
201

202
export function camelCase(values: string[]): string {
7✔
203
    if (isArray(values)) {
204
        return values.reduce((result, word, index) => {
205
            word = word.toLowerCase();
7✔
206
            return result + (index ? upperFirst(word) : word);
207
        }, '');
208
    } else {
209
        return;
210
    }
211
}
10✔
212

5✔
213
export function generateRandomStr() {
214
    return Math.random().toString(36).substring(2);
215
}
5✔
216

217
export function isTemplateRef<C = any>(value: any): value is TemplateRef<C> {
218
    return value instanceof TemplateRef;
219
}
220

221
export function isHTMLElement(value: any): value is HTMLElement {
×
222
    return value instanceof HTMLElement;
5✔
223
}
224

225
export function isElementRef(value: any): value is ElementRef {
226
    return value instanceof ElementRef;
227
}
228

539✔
229
/**
539✔
230
 * @deprecated Please use Angular cdk's coerceBooleanProperty instead
231
 */
232
export function coerceBooleanProperty(value: boolean | string | number): boolean {
21,588✔
233
    if (value === '' || (value && value !== 'false')) {
234
        return true;
235
    } else {
55✔
236
        return false;
20✔
237
    }
238
}
35✔
239

10✔
240
export type FunctionProp<T> = (...args: any[]) => T;
241

25✔
242
/**
25✔
243
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
25✔
244
 */
23✔
245
export function coerceNumberValue(value: number | string): number;
246
/**
2✔
247
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
2✔
248
 */
4✔
249
export function coerceNumberValue<D>(value: number | string, fallback: D): number | D;
4!
NEW
250
/**
×
251
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
252
 */
4✔
253
export function coerceNumberValue(value: number | string, fallbackValue: number = 0): number {
1✔
254
    return _isNumberValue(value) ? Number(value) : fallbackValue;
255
}
256

1✔
257
/**
258
 * @deprecated Please use Angular cdk's coerceCssPixelValue instead
12✔
259
 */
331✔
260
export function coerceCssPixelValue(value: number | string): string {
331✔
261
    value = _isNumberValue(value) ? Number(value) : value;
2✔
262
    return coerceCssPixel(value);
263
}
264

329✔
265
export function valueFunctionProp<T>(prop: FunctionProp<T>, ...args: any[]): T {
266
    return typeof prop === 'function' ? prop(...args) : prop;
331✔
267
}
111✔
268

46✔
269
export function shallowEqual(objA?: Record<string, any>, objB?: Record<string, any>): boolean {
270
    if (objA === objB) {
271
        return true;
65✔
272
    }
273

274
    if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
275
        return false;
220✔
276
    }
277

278
    const keysA = Object.keys(objA);
×
279
    const keysB = Object.keys(objB);
3!
UNCOV
280

×
281
    if (keysA.length !== keysB.length) {
282
        return false;
3✔
283
    }
3✔
284

3✔
285
    const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
3!
286

287
    for (let idx = 0; idx < keysA.length; idx++) {
288
        const key = keysA[idx];
54✔
289
        if (!bHasOwnProperty(key)) {
5✔
290
            return false;
291
        }
49✔
292
        if (objA[key] !== objB[key]) {
293
            return false;
294
        }
295
    }
296

297
    return true;
298
}
299

300
export function concatArray<TItem>(items: TItem | TItem[], originalItems: TItem | TItem[] = []): TItem[] {
301
    let _originalItems: TItem[] = [];
302
    if (!originalItems) {
303
        _originalItems = [];
304
    } else {
305
        _originalItems = coerceArray(originalItems);
306
    }
307
    if (items) {
308
        if (isArray(items)) {
309
            return [..._originalItems, ...items];
310
        } else {
311
            return [..._originalItems, items];
312
        }
313
    } else {
314
        return _originalItems;
315
    }
316
}
317

318
export function humanizeBytes(bytes: number, noSpace = false, fractionDigits = 1): string {
319
    if (bytes === 0) {
320
        return '0 Byte';
321
    }
322

323
    const k = 1024;
324
    const sizes: string[] = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
325
    const i: number = Math.floor(Math.log(bytes) / Math.log(k));
326

327
    return parseFloat((bytes / Math.pow(k, i)).toFixed(fractionDigits)) + (noSpace ? '' : ' ') + sizes[i];
328
}
329

330
export function isFloat(value: string): boolean {
331
    if (!value) {
332
        return false;
333
    }
334

335
    return /^[-+]?([0-9]+([.][0-9]*)?|[.][0-9]+)([Ee][-+]?[0-9]+)?$/.test(value);
336
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc