@nativerent/js-utils 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.ts +18 -1
- package/tests/tests.ts +129 -0
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -791,7 +791,10 @@ export function flattenObject(
|
|
|
791
791
|
const val = obj[k];
|
|
792
792
|
const key = `${pre}${k}`;
|
|
793
793
|
|
|
794
|
-
if (
|
|
794
|
+
if (
|
|
795
|
+
(isObject(val) || Array.isArray(val)) &&
|
|
796
|
+
getObjectKeys(obj[k]).length > 0
|
|
797
|
+
) {
|
|
795
798
|
Object.assign(acc, flattenObject(val, key));
|
|
796
799
|
} else {
|
|
797
800
|
acc[key] = val;
|
|
@@ -906,3 +909,17 @@ export function autoSizeText(
|
|
|
906
909
|
|
|
907
910
|
resizeText();
|
|
908
911
|
}
|
|
912
|
+
|
|
913
|
+
export async function monitor(
|
|
914
|
+
fn: Function,
|
|
915
|
+
interval: number = 10,
|
|
916
|
+
attempts: number = 100,
|
|
917
|
+
): Promise<boolean> {
|
|
918
|
+
for (let i = 0; i < attempts; i++) {
|
|
919
|
+
if (await fn()) return true;
|
|
920
|
+
if (i < attempts - 1) {
|
|
921
|
+
await new Promise<void>((r) => setTimeout(r, interval));
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return false;
|
|
925
|
+
}
|
package/tests/tests.ts
CHANGED
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
toCamelCase,
|
|
73
73
|
toPercent,
|
|
74
74
|
toSnakeCase,
|
|
75
|
+
monitor,
|
|
75
76
|
} from "../src";
|
|
76
77
|
|
|
77
78
|
test.each([
|
|
@@ -2233,6 +2234,134 @@ describe("autoSizeText (using real getNumericStyleProp)", () => {
|
|
|
2233
2234
|
});
|
|
2234
2235
|
});
|
|
2235
2236
|
|
|
2237
|
+
describe("monitor", () => {
|
|
2238
|
+
beforeEach(() => jest.useFakeTimers());
|
|
2239
|
+
|
|
2240
|
+
afterEach(() => {
|
|
2241
|
+
jest.useRealTimers();
|
|
2242
|
+
jest.restoreAllMocks();
|
|
2243
|
+
});
|
|
2244
|
+
|
|
2245
|
+
test("returns true immediately when fn resolves true on first attempt (no sleep)", async () => {
|
|
2246
|
+
const fn = jest.fn().mockResolvedValue(true);
|
|
2247
|
+
|
|
2248
|
+
const promise = monitor(fn, 10, 100);
|
|
2249
|
+
|
|
2250
|
+
// fn resolves immediately; no timers needed
|
|
2251
|
+
await expect(promise).resolves.toBe(true);
|
|
2252
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2253
|
+
// no sleeps scheduled
|
|
2254
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
2255
|
+
});
|
|
2256
|
+
|
|
2257
|
+
test("retries until fn resolves true, sleeping between attempts", async () => {
|
|
2258
|
+
const fn = jest
|
|
2259
|
+
.fn()
|
|
2260
|
+
.mockResolvedValueOnce(false)
|
|
2261
|
+
.mockResolvedValueOnce(false)
|
|
2262
|
+
.mockResolvedValueOnce(true);
|
|
2263
|
+
|
|
2264
|
+
const promise = monitor(fn, 25, 10);
|
|
2265
|
+
|
|
2266
|
+
// attempt 1 happens immediately
|
|
2267
|
+
await Promise.resolve();
|
|
2268
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2269
|
+
|
|
2270
|
+
// sleep 25ms -> attempt 2
|
|
2271
|
+
await jest.advanceTimersByTimeAsync(25);
|
|
2272
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
2273
|
+
|
|
2274
|
+
// sleep 25ms -> attempt 3 succeeds
|
|
2275
|
+
await jest.advanceTimersByTimeAsync(25);
|
|
2276
|
+
await expect(promise).resolves.toBe(true);
|
|
2277
|
+
|
|
2278
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
2279
|
+
});
|
|
2280
|
+
|
|
2281
|
+
test("returns false after exhausting attempts", async () => {
|
|
2282
|
+
const fn = jest.fn().mockResolvedValue(false);
|
|
2283
|
+
|
|
2284
|
+
const promise = monitor(fn, 10, 3);
|
|
2285
|
+
|
|
2286
|
+
// attempt 1
|
|
2287
|
+
await Promise.resolve();
|
|
2288
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2289
|
+
|
|
2290
|
+
// attempt 2
|
|
2291
|
+
await jest.advanceTimersByTimeAsync(10);
|
|
2292
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
2293
|
+
|
|
2294
|
+
// attempt 3 (last) - no further sleep
|
|
2295
|
+
await jest.advanceTimersByTimeAsync(10);
|
|
2296
|
+
await expect(promise).resolves.toBe(false);
|
|
2297
|
+
|
|
2298
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
2299
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
2300
|
+
});
|
|
2301
|
+
|
|
2302
|
+
test("does not sleep after the last attempt (even if fn returns false)", async () => {
|
|
2303
|
+
const fn = jest.fn().mockResolvedValue(false);
|
|
2304
|
+
|
|
2305
|
+
const promise = monitor(fn, 50, 2);
|
|
2306
|
+
|
|
2307
|
+
// attempt 1 then one sleep scheduled
|
|
2308
|
+
await Promise.resolve();
|
|
2309
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2310
|
+
expect(jest.getTimerCount()).toBe(1);
|
|
2311
|
+
|
|
2312
|
+
// advance once -> attempt 2 (last)
|
|
2313
|
+
await jest.advanceTimersByTimeAsync(50);
|
|
2314
|
+
await expect(promise).resolves.toBe(false);
|
|
2315
|
+
|
|
2316
|
+
// should not schedule another sleep
|
|
2317
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
2318
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
2319
|
+
});
|
|
2320
|
+
|
|
2321
|
+
test("uses default interval=10 and attempts=100 when omitted", async () => {
|
|
2322
|
+
const fn = jest.fn().mockResolvedValue(false);
|
|
2323
|
+
|
|
2324
|
+
const promise = monitor(fn); // defaults
|
|
2325
|
+
|
|
2326
|
+
// attempt 1
|
|
2327
|
+
await Promise.resolve();
|
|
2328
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2329
|
+
|
|
2330
|
+
// drive 99 more attempts with 99 sleeps of 10ms each
|
|
2331
|
+
for (let i = 0; i < 99; i++) {
|
|
2332
|
+
await jest.advanceTimersByTimeAsync(10);
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
await expect(promise).resolves.toBe(false);
|
|
2336
|
+
expect(fn).toHaveBeenCalledTimes(100);
|
|
2337
|
+
});
|
|
2338
|
+
|
|
2339
|
+
test("awaits fn each time (supports async fn that resolves later)", async () => {
|
|
2340
|
+
const fn = jest
|
|
2341
|
+
.fn()
|
|
2342
|
+
.mockImplementationOnce(
|
|
2343
|
+
() => new Promise<boolean>((res) => setTimeout(() => res(false), 5)),
|
|
2344
|
+
)
|
|
2345
|
+
.mockImplementationOnce(
|
|
2346
|
+
() => new Promise<boolean>((res) => setTimeout(() => res(true), 5)),
|
|
2347
|
+
);
|
|
2348
|
+
|
|
2349
|
+
const promise = monitor(fn, 20, 5);
|
|
2350
|
+
|
|
2351
|
+
// attempt 1's internal 5ms
|
|
2352
|
+
await jest.advanceTimersByTimeAsync(5);
|
|
2353
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
2354
|
+
|
|
2355
|
+
// then monitor sleeps 20ms before attempt 2
|
|
2356
|
+
await jest.advanceTimersByTimeAsync(20);
|
|
2357
|
+
// attempt 2's internal 5ms
|
|
2358
|
+
await jest.advanceTimersByTimeAsync(5);
|
|
2359
|
+
|
|
2360
|
+
await expect(promise).resolves.toBe(true);
|
|
2361
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
2362
|
+
});
|
|
2363
|
+
});
|
|
2364
|
+
|
|
2236
2365
|
function mockRect(el: HTMLElement, rect: Partial<DOMRect>): void {
|
|
2237
2366
|
jest.spyOn(el, "getBoundingClientRect").mockReturnValue({
|
|
2238
2367
|
x: 0,
|