Skip to content

Commit

Permalink
chore: update get-modules-graph to 0.0.9
Browse files Browse the repository at this point in the history
chore: update devDependencies (eslint, @typescript-eslint/*, etc)
fix: add type `FilePathFromRoot` to public API
fix: duration for long time intervals (in HTML report)
  • Loading branch information
uid11 committed Oct 11, 2023
1 parent 64b383b commit e30bd34
Show file tree
Hide file tree
Showing 12 changed files with 265 additions and 231 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(The MIT License)

Copyright (c) 2021-2023 uid11
Copyright (c) 2021-2023 SIA Joom

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand Down
326 changes: 171 additions & 155 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@
"dependencies": {
"bin-v8-flags-filter": "1.2.0",
"create-locator": "0.0.17",
"get-modules-graph": "0.0.8",
"get-modules-graph": "0.0.9",
"globby": "11.1.0",
"pngjs": "7.0.0",
"testcafe-without-typecheck": "3.3.0-rc.1"
},
"devDependencies": {
"@types/node": "20.6.3",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"@types/node": "20.8.4",
"@typescript-eslint/eslint-plugin": "6.7.5",
"@typescript-eslint/parser": "6.7.5",
"assert-modules-support-case-insensitive-fs": "1.0.1",
"assert-package-lock-is-consistent": "1.0.0",
"eslint": "8.50.0",
"eslint": "8.51.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.28.1",
Expand Down
2 changes: 1 addition & 1 deletion src/getModulesGraph.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export type {Graph, Module, Package} from 'get-modules-graph';
export type {Graph, Module, Options, Package} from 'get-modules-graph';
export {getModulesGraph, resolveImports, resolveReexports} from 'get-modules-graph';
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type {
PageClassType,
PageClassTypeArgs,
} from './pages';
export type {TestFilePath} from './paths';
export type {FilePathFromRoot, TestFilePath} from './paths';
export type {AsyncVoid, MaybePromise, UnwrapPromise} from './promise';
export type {LiteReport, LiteRetry} from './report';
export type {
Expand Down
92 changes: 46 additions & 46 deletions src/types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type {IsIncludeUndefined} from './undefined';
declare const PARAMS_KEY: unique symbol;

/**
* Entry pair that Object.entries(T) returns.
* Entry pair that `Object.entries<Type>` returns.
*/
type EntryPair<T> = [keyof T, Values<T> | undefined];
type EntryPair<Type> = [key: keyof Type, value: Values<Type> | undefined];

/**
* Alias for type any (to suppress the @typescript-eslint/no-explicit-any rule).
Expand All @@ -20,48 +20,48 @@ export type Any = any;
/**
* Returns the type of instance params.
*/
export type GetParamsType<C> = C extends {[PARAMS_KEY]: unknown}
? Normalize<C[PARAMS_KEY_TYPE]>
export type GetParamsType<Class> = Class extends {[PARAMS_KEY]: unknown}
? Normalize<Class[PARAMS_KEY_TYPE]>
: never;

/**
* Returns `true` if type is an array (or tuple) of given element's type, and `false` otherwise.
* IsArray<[]> = true.
* IsArray<[true, false]> = true.
* IsArray<readonly [1, 2], number> = true.
* IsArray<[1, 2], string> = false.
* IsArray<string[], string> = true.
* `IsArray<[]>` = `true`.
* `IsArray<[true, false]>` = `true`.
* `IsArray<readonly [1, 2], number>` = `true`.
* `IsArray<[1, 2], string>` = `false`.
* `IsArray<string[], string>` = `true`.
*/
export type IsArray<T, E = unknown> = T extends readonly E[] ? true : false;
export type IsArray<Type, Element = unknown> = Type extends readonly Element[] ? true : false;

/**
* Returns a copy of the object type with mutable properties.
* Mutable<{readonly foo: string}> = {foo: string}.
* `Mutable<{readonly foo: string}>` = `{foo: string}`.
*/
export type Mutable<T> = {
-readonly [K in keyof T]: T[K];
export type Mutable<Type> = {
-readonly [Key in keyof Type]: Type[Key];
};

/**
* Normalizes intersection of types.
* Normalize<{foo: string} & {bar: number}> = {foo: string, bar: number}.
* `Normalize<{foo: string} & {bar: number}>` = `{foo: string, bar: number}`.
*/
export type Normalize<T> = keyof T extends never
? T
: IsBrand<T> extends true
? T
: {[K in keyof T]: Normalize<T[K]>};
export type Normalize<Type> = keyof Type extends never
? Type
: IsBrand<Type> extends true
? Type
: {[Key in keyof Type]: Normalize<Type[Key]>};

/**
* List of pairs that Object.entries(T) returns.
* List of pairs that `Object.entries<Type>` returns.
*/
export type ObjectEntries<T> = EntryPair<T>[];
export type ObjectEntries<Type> = EntryPair<Type>[];

/**
* Returns a tuple of two elements. If the second element includes `undefined`,
* then it becomes optional in the tuple.
* OneOrTwoArgs<'foo', string> = [arg1: 'foo', arg2: string].
* OneOrTwoArgs<'foo', undefined | number> = [arg1: 'foo', arg2?: number].
* `OneOrTwoArgs<'foo', string>` = `[arg1: 'foo', arg2: string]`.
* `OneOrTwoArgs<'foo', undefined | number>` = `[arg1: 'foo', arg2?: number]`.
*/
export type OneOrTwoArgs<Arg1, Arg2> = IsIncludeUndefined<Arg2> extends true
? [arg1: Arg1, arg2?: Arg2]
Expand All @@ -70,10 +70,10 @@ export type OneOrTwoArgs<Arg1, Arg2> = IsIncludeUndefined<Arg2> extends true
/**
* The property value will be optional if its default value
* is included in the set of possible values.
* OptionalIfValueIncludeDefault<'foo', 1 | 2, 2> = {foo?: 1 | 2}.
* OptionalIfValueIncludeDefault<'foo', 1 | 2, 3> = {foo: 1 | 2}.
* OptionalIfValueIncludeDefault<'foo', {bar?: string}, {}> = {foo?: {bar?: string}}.
* OptionalIfValueIncludeDefault<'foo', {bar: string}, {}> = {foo: {bar: string}}.
* `OptionalIfValueIncludeDefault<'foo', 1 | 2, 2>` = `{foo?: 1 | 2}`.
* `OptionalIfValueIncludeDefault<'foo', 1 | 2, 3>` = `{foo: 1 | 2}`.
* `OptionalIfValueIncludeDefault<'foo', {bar?: string}, {}>` = `{foo?: {bar?: string}}`.
* `OptionalIfValueIncludeDefault<'foo', {bar: string}, {}>` = `{foo: {bar: string}}`.
*/
export type OptionalIfValueIncludeDefault<
Key extends string,
Expand All @@ -88,37 +88,37 @@ export type PARAMS_KEY_TYPE = typeof PARAMS_KEY;

/**
* Takes a union, and returns the intersection of the elements of the union.
* UnionToIntersection<((x: string) => number) | ((x: number) => string)> =
* ((x: string) => number) & ((x: number) => string)
* `UnionToIntersection<((x: string) => number) | ((x: number) => string)>` =
* `((x: string) => number) & ((x: number) => string)`
*/
export type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
k: infer I,
) => void
? I
export type UnionToIntersection<Union> = (
Union extends unknown ? (arg: Union) => void : never
) extends (arg: infer Intersection) => void
? Intersection
: never;

/**
* If the type is a set, unwraps it and returns the set value type.
* UnwrapSet<number> = number.
* UnwrapSet<Set<string>> = string.
* `UnwrapSet<number>` = `number`.
* `UnwrapSet<Set<string>>` = `string`.
*/
export type UnwrapSet<T> = T extends Set<infer V> ? V : T;
export type UnwrapSet<Type> = Type extends Set<infer Value> ? Value : Type;

/**
* Values of all properties of type T.
* Values<{foo: 1, bar: 2}> = 1 | 2.
* Values<[1, 2], true> = 1 | 2.
* Values of all properties of type `Type`.
* `Values<{foo: 1, bar: 2}>` = `1 | 2`.
* `Values<[1, 2], true>` = `1 | 2`.
*/
export type Values<T, WithArrays extends boolean = false> = WithArrays extends true
? T extends readonly unknown[]
? T[number]
: T[keyof T]
: T[keyof T];
export type Values<Type, WithArrays extends boolean = false> = WithArrays extends true
? Type extends readonly unknown[]
? Type[number]
: Type[keyof Type]
: Type[keyof Type];

/**
* Returns a tuple of one element. If the element includes `undefined`,
* then it becomes optional in the tuple.
* ZeroOrOneArg<string> = [arg: string].
* ZeroOrOneArg<undefined | number> = [arg?: number].
* `ZeroOrOneArg<string>` = `[arg: string]`.
* `ZeroOrOneArg<undefined | number>` = `[arg?: number]`.
*/
export type ZeroOrOneArg<Arg> = IsIncludeUndefined<Arg> extends true ? [arg?: Arg] : [arg: Arg];
10 changes: 5 additions & 5 deletions src/utils/deepMerge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import type {DeepPartial, ObjectEntries, Values} from '../types/internal';

/**
* Deep merge two objects (arrays does not merge).
* y overwrites x; x and y are immutable.
* `y` overwrites `x`; `x` and `y` are immutable.
*/
export const deepMerge = <T extends object>(x: T, y: DeepPartial<T>): T => {
const result = {} as T;
export const deepMerge = <Type extends object>(x: Type, y: DeepPartial<Type>): Type => {
const result = {} as Type;

for (const key of Object.keys(x)) {
const descriptor = Object.getOwnPropertyDescriptor(x, key);
Expand All @@ -18,9 +18,9 @@ export const deepMerge = <T extends object>(x: T, y: DeepPartial<T>): T => {
Object.defineProperty(result, key, descriptor);
}

for (const [key, value] of Object.entries(y) as ObjectEntries<T>) {
for (const [key, value] of Object.entries(y) as ObjectEntries<Type>) {
if (isObjectAndNotAnArray(x[key]) && isObjectAndNotAnArray(value)) {
result[key] = deepMerge(x[key] as object, value) as Values<T>;
result[key] = deepMerge(x[key] as object, value) as Values<Type>;
} else {
const descriptor = Object.getOwnPropertyDescriptor(y, key);

Expand Down
34 changes: 25 additions & 9 deletions src/utils/report/client/render/renderDuration.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
import {sanitizeHtml as clientSanitizeHtml} from '../sanitizeHtml';
import {createSafeHtmlWithoutSanitize as clientCreateSafeHtmlWithoutSanitize} from '../sanitizeHtml';

import type {SafeHtml} from '../../../../types/internal';

const sanitizeHtml = clientSanitizeHtml;
const createSafeHtmlWithoutSanitize = clientCreateSafeHtmlWithoutSanitize;

/**
* Renders the duration of time interval in minutes and seconds.
* Renders the duration of time interval in hours, minutes, seconds and milliseconds.
* This base client function should not use scope variables (except other base functions).
* @internal
*/
export function renderDuration(durationMs: number): SafeHtml {
const durationInSeconds = Math.round(durationMs / 1000);
const minutes = Math.floor(durationInSeconds / 60);
const minutesString = minutes === 0 ? '' : `${minutes}m `;
const secondsString = `${durationInSeconds % 60}s`;
export function renderDuration(durationInMs: number): SafeHtml {
const remainderInMs = durationInMs % 1000;
const durationInSeconds = Math.round((durationInMs - remainderInMs) / 1000);
const remainderInSeconds = durationInSeconds % 60;
const durationInMinutes = Math.round((durationInSeconds - remainderInSeconds) / 60);
const remainderInMinutes = durationInMinutes % 60;
const durationInHours = Math.round((durationInMinutes - remainderInMinutes) / 60);

return sanitizeHtml`${minutesString}${secondsString}`;
const parts: string[] = [`${remainderInMs}ms`];

if (remainderInSeconds > 0) {
parts.unshift(`${remainderInSeconds}s`);
}

if (remainderInMinutes > 0) {
parts.unshift(`${remainderInMinutes}m`);
}

if (durationInHours > 0) {
parts.unshift(`${durationInHours}h`);
}

return createSafeHtmlWithoutSanitize`${parts.slice(-2).join(' ')}`;
}
6 changes: 4 additions & 2 deletions src/utils/report/client/render/renderStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import {LogEventStatus, LogEventType} from '../../../../constants/internal';

import {sanitizeHtml as clientSanitizeHtml} from '../sanitizeHtml';

import {renderDuration as clientRenderDuration} from './renderDuration';
import {renderStepContent as clientRenderStepContent} from './renderStepContent';

import type {LogEvent, ReportClientState, SafeHtml, UtcTimeInMs} from '../../../../types/internal';

const renderDuration = clientRenderDuration;
const renderStepContent = clientRenderStepContent;
const sanitizeHtml = clientSanitizeHtml;

Expand All @@ -23,7 +25,7 @@ type Options = Readonly<{
*/
export function renderStep({logEvent, nextLogEventTime}: Options): SafeHtml {
const {message, payload, time, type} = logEvent;
const durationMs = nextLogEventTime - time;
const durationInMs = nextLogEventTime - time;
const status = payload?.logEventStatus ?? LogEventStatus.Passed;

let pathToScreenshotFromReportPage: string | undefined;
Expand All @@ -46,7 +48,7 @@ export function renderStep({logEvent, nextLogEventTime}: Options): SafeHtml {
return sanitizeHtml`
<button aria-expanded="${isErrorScreenshot}" class="step-expanded step-expanded_status_${status}">
<span class="step-expanded__name">${message}</span>
<span class="step-expanded__time">${durationMs}ms</span>
<span class="step-expanded__time">${renderDuration(durationInMs)}</span>
</button>
${content}
`;
Expand Down
4 changes: 2 additions & 2 deletions src/utils/report/client/render/renderTestRunDescription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const sanitizeHtml = clientSanitizeHtml;
*/
export function renderTestRunDescription(fullTestRun: FullTestRun): SafeHtml {
const {endTimeInMs, startTimeInMs} = fullTestRun;
const durationMs = endTimeInMs - startTimeInMs;
const durationInMs = endTimeInMs - startTimeInMs;
const {meta} = fullTestRun.options;
const metaHtmls: SafeHtml[] = [];

Expand All @@ -47,7 +47,7 @@ export function renderTestRunDescription(fullTestRun: FullTestRun): SafeHtml {
</dd>
<dt class="test-description__term">Duration</dt>
<dd class="test-description__definition">
${renderDuration(durationMs)}
${renderDuration(durationInMs)}
</dd>
</dl>`;
}
4 changes: 2 additions & 2 deletions src/utils/report/render/renderRetryHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ export const renderRetryHeader = ({
retryIndex,
startTimeInMs,
}: RetryProps): SafeHtml => {
const durationMs = endTimeInMs - startTimeInMs;
const durationInMs = endTimeInMs - startTimeInMs;

return sanitizeHtml`
<h3 class="__title">Retry ${retryIndex}</h3>
<p class="__date">
${renderDatesInterval({endTimeInMs, startTimeInMs})}
(${renderDuration(durationMs)})
(${renderDuration(durationInMs)})
</p>`;
};
4 changes: 2 additions & 2 deletions src/utils/report/render/renderTestRunButton.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {sanitizeHtml} from '../client';
import {renderDuration, sanitizeHtml} from '../client';

import type {SafeHtml, TestRunButtonProps} from '../../../types/internal';

Expand All @@ -20,6 +20,6 @@ export const renderTestRunButton = (
>
<span class="test-button__order">#${index + 1}</span>
<span class="test-button__name">${name}<span class="test-button__parameters">${mainParams}</span></span>
<span class="test-button__time">${durationInMs}ms</span>
<span class="test-button__time">${renderDuration(durationInMs)}</span>
</button>`;
};

0 comments on commit e30bd34

Please sign in to comment.