Repository: exadel-inc/esl
Pull request #821 (2022-02-07 20:42:55)

feat(esl-utils): Transition duration utility
In the scope of this PR I added a utility to get a transition length


ala-n: > To be discussed on tomorrow's call.
> 
> We should have a utility to resolve a class of problems but not specific ones. (But you are really close to making this code universal btw) Also, the esl-utils can be extended only with unit tests provided for extending, until it's not agreed with a @exadel-inc/esl-core-team.

````
/** @example parseTime('.5s') // 500 */
function parseTime(timeStr: string): number;

/** @example parseTimeSet('.5s, 1ms') // [500, 1] */
function parseTimeSet(timeStr: string): number[];
```
codeclimate[bot]: Code Climate has analyzed commit 6e50bbfb and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **100.0%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **54.7%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/821).


Patch:
diff --git a/src/modules/esl-utils/misc/format.ts b/src/modules/esl-utils/misc/format.ts
index fc5fd715f..fa8583ac6 100644
--- a/src/modules/esl-utils/misc/format.ts
+++ b/src/modules/esl-utils/misc/format.ts
@@ -82,3 +82,25 @@ export function format(str: string, source: Record<string, any>, matcher: RegExp
     return val === undefined ? match : val;
   });
 }
+/**
+ * Parses time string ([CSS style](https://developer.mozilla.org/en-US/docs/Web/CSS/time))
+ * @example
+ * `.3s`, `4.5s`, `1000ms`
+ * @returns number - time in milliseconds
+*/
+export function parseCSSTime(timeStr: string): number {
+  const str = timeStr.trim().toLowerCase();
+  if (!/\dm?s$/.test(str)) return NaN;
+  if (str.endsWith('ms')) return +str.slice(0, -2);
+  return +str.slice(0, -1) * 1000;
+}
+
+/**
+ * Parses string of times ([CSS style](https://developer.mozilla.org/en-US/docs/Web/CSS/time))
+ * @example
+ * `.3s`, `4.5s,1000ms`, `1s, 5s`
+ * @returns number[] - array of times in milliseconds
+*/
+export function parseCSSTimeSet(timeStr: string): number[] {
+  return timeStr.split(',').map((timeSubstr) => parseCSSTime(timeSubstr));
+}


Test patch:
diff --git a/src/modules/esl-utils/misc/test/format.test.ts b/src/modules/esl-utils/misc/test/format.test.ts
index 986e259a4..552083dcc 100644
--- a/src/modules/esl-utils/misc/test/format.test.ts
+++ b/src/modules/esl-utils/misc/test/format.test.ts
@@ -8,7 +8,9 @@ import {
   format,
   parseNumber,
   parseBoolean,
-  parseString
+  parseString,
+  parseCSSTime,
+  parseCSSTimeSet
 } from '../format';
 
 describe('misc/format helper tests', () => {
@@ -142,4 +144,62 @@ describe('misc/format helper tests', () => {
       (args, exp) => expect(parseNumber.apply(null, args)).toBe(exp)
     );
   });
+
+  describe('parseCSSTime', () => {
+    test.each([
+      // Positive integer
+      ['12s', 12000],
+      ['350ms', 350],
+      [' 12s ', 12000],
+      [' 350ms ', 350],
+      ['1024ms', 1024],
+      // Non-integer
+      ['.3s', 300],
+      ['.124s', 124],
+      ['.3ms', 0.3],
+      // Negative integer
+      ['-456ms', -456],
+      // Case insensitive
+      ['14mS', 14],
+      ['14S', 14000],
+      // Zero with leading +/-
+      ['+0s', 0],
+      ['-0ms', -0]
+    ])(
+      'valid time = %s parsed as %s',
+      (time: string, result: number) => expect(parseCSSTime(time)).toBe(result)
+    );
+    test.each([
+      // Although unitless zero is allowed for <length>s, it's invalid for <time>s.
+      '0',
+      // This is a <number>, not a <time>, because it's missing a unit.
+      '12.0',
+      // Invalid text
+      'five seconds',
+      's', 'ms',
+      '350.s',
+      ' s', ' ms',
+      '.s', '.ms',
+      // CSS time supports only seconds and milliseconds
+      '4min'
+    ])(
+      'invalid time = %p parsed as NaN',
+      (time: string) => expect(parseCSSTime(time)).toBe(NaN)
+    );
+  });
+
+  describe('parseCSSTimeSet', () => {
+    test.each([
+      [['.3s'], [300]],
+      [['.124s, .50s'], [124, 500]],
+      [['350ms, 1400ms'], [350, 1400]],
+      [['3s,1400ms'], [3000, 1400]],
+      [['1024ms, second'], [1024, NaN]],
+      [['350ms, 350.s'], [350, NaN]],
+      [['ms, s'], [NaN, NaN]]
+    ])(
+      'time = %p',
+      (time, num) => expect(parseCSSTimeSet.apply(null, time)).toStrictEqual(num)
+    );
+  });
 });