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

atinc / ngx-tethys / bccfbe82-aca8-4d24-b68f-0f535ef31f93

09 Jun 2025 07:26AM UTC coverage: 90.31% (+0.005%) from 90.305%
bccfbe82-aca8-4d24-b68f-0f535ef31f93

push

circleci

minlovehua
refactor: the TransormT type specified in input should be consistent with the transform function parameter type

5550 of 6819 branches covered (81.39%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 3 files covered. (100.0%)

20 existing lines in 3 files now uncovered.

13732 of 14532 relevant lines covered (94.49%)

903.3 hits per line

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

86.46
/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 type ThyBooleanInput = boolean | string | number | unknown;
5,460✔
5

6
export function isUndefined(value: any): value is undefined {
7
    return value === undefined;
1,450✔
8
}
9

10
export function isNull(value: any): value is null {
5,401✔
11
    return value === null;
12
}
13

46,525✔
14
export function isUndefinedOrNull(value: any): value is undefined | null {
15
    return isUndefined(value) || isNull(value);
16
}
20,186✔
17

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

22
export function isEmpty(value?: any): boolean {
16,256✔
23
    return !(isArray(value) && value.length > 0);
24
}
25

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

13,002!
UNCOV
30
function isObjectLike(value: any): value is object {
×
31
    return value !== null && typeof value === 'object';
32
}
13,002✔
33

13,000✔
34
function baseGetTag(value: any) {
35
    const objectProto = Object.prototype;
2✔
36
    const hasOwnProperty = objectProto.hasOwnProperty;
2✔
37
    const toString = objectProto.toString;
2✔
38
    const symToStringTag = typeof Symbol !== 'undefined' ? Symbol.toStringTag : undefined;
2✔
39

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

54
    const result = toString.call(value);
55
    if (unmasked) {
1,061✔
56
        if (isOwn) {
57
            value[symToStringTag] = tag;
58
        } else {
59
            delete value[symToStringTag];
60
        }
540✔
61
    }
540✔
62
    return result;
63
}
64

1,261,004✔
65
export function isNumber(value: any): value is number {
1,261,004✔
66
    return typeof value === 'number' || (isObjectLike(value) && baseGetTag(value) === '[object Number]');
67
}
68

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

7,668✔
76
export function isFunction(value: any): value is Function {
7,668✔
77
    const type = typeof value;
7,668✔
78
    return !!value && type === 'function';
460✔
79
}
80

7,668✔
81
export function isDate(value: any): value is Date {
82
    const type = typeof value;
83
    return !!value && type === 'object' && !!value.getTime;
463!
UNCOV
84
}
×
85

86
export function coerceArray<T>(value: T | T[]): T[] {
463✔
87
    return Array.isArray(value) ? value : [value];
463✔
88
}
463✔
89

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

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

126
export function isBoolean(value: any): value is boolean {
1!
UNCOV
127
    return value === true || value === false || (isObjectLike(value) && baseGetTag(value) === '[object Boolean]');
×
128
}
129

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

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

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

166
export function dateToUnixTimestamp(date: Date | number): number {
268✔
167
    if (isNumber(date)) {
268✔
168
        if (date.toString().length === 10) {
1,257✔
169
            return date as number;
1,257✔
170
        } else {
171
            return parseInt(((date as number) / 1000).toFixed(0), 10);
268✔
172
        }
173
    } else {
174
        return parseInt(((date as Date).getTime() / 1000).toFixed(0), 10);
5✔
175
    }
5✔
176
}
9✔
177

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

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

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

15,197✔
200
function upperFirst(string: string): string {
201
    return string.slice(0, 1).toUpperCase() + string.slice(1);
202
}
7✔
203

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

215
export function generateRandomStr() {
7,717✔
216
    return Math.random().toString(36).substring(2);
217
}
218

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

5✔
223
export function isHTMLElement(value: any): value is HTMLElement {
224
    return value instanceof HTMLElement;
225
}
226

227
export function isElementRef(value: any): value is ElementRef {
228
    return value instanceof ElementRef;
113✔
229
}
113✔
230

231
/**
232
 * fix angular cdk's coerceBooleanProperty will transform 0 to true
22,134✔
233
 */
234
export function coerceBooleanProperty(value: ThyBooleanInput): boolean {
235
    if (value === '' || (value && value !== 'false')) {
249✔
236
        return true;
57✔
237
    } else {
238
        return false;
192✔
239
    }
10✔
240
}
241

182✔
242
export type FunctionProp<T> = (...args: any[]) => T;
182✔
243

182✔
244
/**
114✔
245
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
246
 */
68✔
247
export function coerceNumberValue(value: number | string): number;
68✔
248
/**
70✔
249
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
70!
UNCOV
250
 */
×
251
export function coerceNumberValue<D>(value: number | string, fallback: D): number | D;
252
/**
70✔
253
 * @deprecated Please use Angular cdk's coerceNumberProperty instead
67✔
254
 */
255
export function coerceNumberValue(value: number | string, fallbackValue: number = 0): number {
256
    return _isNumberValue(value) ? Number(value) : fallbackValue;
1✔
257
}
258

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

347✔
267
export function valueFunctionProp<T>(prop: FunctionProp<T>, ...args: any[]): T {
113✔
268
    return typeof prop === 'function' ? prop(...args) : prop;
48✔
269
}
270

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

234✔
276
    if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
277
        return false;
278
    }
×
279

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

3✔
283
    if (keysA.length !== keysB.length) {
3✔
284
        return false;
3✔
285
    }
3!
286

287
    const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
288

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

155✔
299
    return true;
155✔
300
}
301

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

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

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

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

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

337
    return /^[-+]?([0-9]+([.][0-9]*)?|[.][0-9]+)([Ee][-+]?[0-9]+)?$/.test(value);
338
}
339

340
export function hasTimeInStringDate(dateString: string): boolean {
341
    const standardFormat = /\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{1,2}/;
342
    const chineseFormat = /\d{4}年\d{1,2}月\d{1,2}日?\s+\d{1,2}[时:]\d{1,2}[分]?/;
343
    const reverseEnglishFormat = /\d{1,2}\s+[A-Za-z]{3,}\s+\d{4}\s+\d{1,2}:\d{1,2}/;
344
    const englishFormat = /[A-Za-z]{3,}\s+\d{1,2},?\s+\d{4}\s+\d{1,2}:\d{1,2}/;
345
    const isoFormat = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
346

347
    return (
348
        standardFormat.test(dateString) ||
349
        chineseFormat.test(dateString) ||
350
        reverseEnglishFormat.test(dateString) ||
351
        englishFormat.test(dateString) ||
352
        isoFormat.test(dateString)
353
    );
354
}
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