Skip to content

Commit

Permalink
feat: initial test results block
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Apr 22, 2021
1 parent b1fdf18 commit 380886a
Show file tree
Hide file tree
Showing 16 changed files with 3,289 additions and 73 deletions.
35 changes: 21 additions & 14 deletions core/core/src/jest.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { TestResult } from '@jest/test-result';
export interface JestTestResults {
ancestorTitles: string[];
failureDetails: unknown[];
failureMessages: string[];
numPassingAsserts: number;
status: 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled';
title: string;
}

import {
TestResult as JestTestResult,
AssertionResult,
} from '@jest/test-result';
export interface CoverageMetrics {
total: number;
covered: number;
Expand All @@ -22,14 +16,27 @@ export interface JestCoverage {
branches: CoverageMetrics;
}

export type JestResult = Pick<
JestTestResult,
'leaks' | 'perfStats' | 'testFilePath'
> & {
testResults: (Pick<
AssertionResult,
| 'ancestorTitles'
| 'duration'
| 'fullName'
| 'status'
| 'title'
| 'numPassingAsserts'
> & {
failureDetails: { message: string }[];
})[];
};
export interface JestTests {
/**
* test results
*/
results: Pick<
TestResult,
'leaks' | 'memoryUsage' | 'perfStats' | 'testFilePath' | 'testResults'
>[];
results: JestResult[];
/**
* coverage summary data, by file
*/
Expand Down
3 changes: 1 addition & 2 deletions core/instrument/src/misc/jest-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
runProjectTests,
findJestConfig,
getRelatedTests,
JestResults,
} from '@component-controls/jest-extract';
import { JestTests } from '@component-controls/core';
import { CachedFileResource } from './chached-file';
Expand Down Expand Up @@ -38,7 +37,7 @@ export const extractTests = async (
{ testFiles: [], coverageFiles: [] },
);
if (tests.testFiles.length) {
const cached = new CachedFileResource<JestResults>('jest-tests', files[0], [
const cached = new CachedFileResource<JestTests>('jest-tests', files[0], [
...tests.testFiles,
...tests.coverageFiles,
]);
Expand Down
5 changes: 3 additions & 2 deletions core/jest-extract/src/related-tests.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import path from 'path';
import { Config } from '@jest/types';
import { JestTests } from '@component-controls/core';
import { sync as globSync } from 'glob';
import { runTests, JestResults } from './run-tests';
import { runTests } from './run-tests';

export type RelatedTest = {
/**
* full name of the test file
*/
testFileName: string;
} & JestResults;
} & JestTests;

export type RelatedTests = RelatedTest[];

Expand Down
61 changes: 34 additions & 27 deletions core/jest-extract/src/run-tests.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import path from 'path';
import { runCLI } from 'jest';
import { Config } from '@jest/types';
import { JestTests } from '@component-controls/core';
import { findUpFile } from '@component-controls/core/node-utils';
import { TestResult, AggregatedResult } from '@jest/test-result';
import { FileCoverage, CoverageSummaryData } from 'istanbul-lib-coverage';
import { AggregatedResult } from '@jest/test-result';
import { FileCoverage } from 'istanbul-lib-coverage';
import fastq from 'fastq';

export const findJestConfig = (filePath: string): string =>
Expand All @@ -15,21 +16,6 @@ export const findJestConfig = (filePath: string): string =>
]) || filePath,
);

export interface JestResults {
/**
* test results
*/
results: Pick<
TestResult,
'leaks' | 'memoryUsage' | 'perfStats' | 'testFilePath' | 'testResults'
>[];

/**
* coverage summary data, by file
*/
coverage: Record<string, CoverageSummaryData>;
}

interface RunTestsInput {
/**
* related test files to execute
Expand All @@ -52,7 +38,7 @@ interface RunTestsInput {
const runTestsWorker: fastq.asyncWorker<
unknown,
RunTestsInput,
JestResults | undefined
JestTests | undefined
> = async ({
testFiles,
projectFolder,
Expand Down Expand Up @@ -90,14 +76,35 @@ const runTestsWorker: fastq.asyncWorker<
}
const { coverageMap, testResults } = runResults.results;
const relFolder = relativeFolder || projectFolder;
const result: JestResults = {
const result: JestTests = {
results: testResults.map(
({ leaks, memoryUsage, perfStats, testFilePath, testResults }) => ({
({ leaks, perfStats, testFilePath, testResults }) => ({
leaks,
memoryUsage,
perfStats: { ...perfStats },
perfStats,
testFilePath: path.relative(relFolder, testFilePath),
testResults: [...testResults],
testResults: testResults.map(
({
ancestorTitles,
duration,
fullName,
status,
title,
numPassingAsserts,
failureDetails,
}) => ({
ancestorTitles,
duration,
fullName,
status,
title,
numPassingAsserts,
failureDetails: (failureDetails as { message: string }[]).map(
failure => ({
message: failure.message,
}),
),
}),
),
}),
),
coverage: {},
Expand All @@ -120,7 +127,7 @@ const runTestsWorker: fastq.asyncWorker<

let queue: fastq.queueAsPromised<
RunTestsInput,
JestResults | undefined
JestTests | undefined
> | null = null;

/**
Expand All @@ -132,7 +139,7 @@ let queue: fastq.queueAsPromised<
export const runTests = async (
testFilePath: string,
options: Partial<Config.Argv> = {},
): Promise<JestResults> => {
): Promise<JestTests> => {
const testFiles = [path.basename(testFilePath)];
const projectFolder = findJestConfig(testFilePath);
const relativeFolder = path.dirname(testFilePath);
Expand All @@ -149,10 +156,10 @@ export const runTests = async (
*/
export const runProjectTests = async (
props: RunTestsInput,
): Promise<JestResults> => {
): Promise<JestTests> => {
if (!queue) {
queue = fastq.promise(runTestsWorker, 1);
}
const result = await queue.push(props);
return (result as unknown) as JestResults;
return (result as unknown) as JestTests;
};
1 change: 1 addition & 0 deletions ui/blocks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@component-controls/search-algolia": "^3.7.0",
"@component-controls/store": "^3.7.0",
"@theme-ui/css": "^0.6.0-alpha.7",
"ansi_up": "^5.0.1",
"copy-to-clipboard": "^3.2.1",
"global": "^4.3.2",
"js-string-escape": "^1.0.1",
Expand Down
168 changes: 168 additions & 0 deletions ui/blocks/src/ComponentTests/BaseComponentTests.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/* eslint-disable react/display-name */
/** @jsx jsx */
import { FC, useMemo, useCallback } from 'react';
import { jsx } from 'theme-ui';
import { Column } from 'react-table';
import AnsiUp from 'ansi_up';

import { Table, TableProps } from '@component-controls/components';
import { JestResult, Component } from '@component-controls/core';

type TestRow = { id: number } & Pick<
JestResult,
'leaks' | 'perfStats' | 'testFilePath'
> &
JestResult['testResults'][number];
export type BaseComponentTestsProps = {
component?: Component;
pagination?: TableProps<TestRow>['pagination'];
};

/**
* Displays commit history for a component
*/
export const BaseComponentTests: FC<BaseComponentTestsProps> = ({
component,
pagination = true,
}) => {
const ansi_up = useMemo(() => new AnsiUp(), []);

console.log(component?.jest);
const renderRowSubComponent = useCallback(
({ row }) => {
const errors = row.original.failureDetails.map(
(
failure: {
message: string;
},
index: number,
) => (
<code key={`error_msg_${index}`}>
<div
style={{ padding: '10px' }}
dangerouslySetInnerHTML={{
__html: ansi_up
.ansi_to_html(failure.message)
.replace(/\n/gi, '<div />'),
}}
/>
</code>
),
);

return (
<div>
<div>{errors}</div>
</div>
);
},
[ansi_up],
);
const columns = useMemo(
() =>
[
{
Header: () => null,
id: 'expander',
Cell: ({ row }: { row: any }) => {
if (row.original.failureDetails.length) {
return (
<span {...row.getToggleRowExpandedProps()}>
{row.isExpanded ? '👇' : '👉'}
</span>
);
}
return null;
},
},
{
Header: '#',
accessor: 'id',
Cell: ({
row: {
original: { id },
},
}) => <span>{id}</span>,
},
{
Header: 'Test file',
accessor: 'testFilePath',
Cell: ({
row: {
original: { testFilePath },
},
}) => {
return (
<div>
<div>{testFilePath}</div>
</div>
);
},
},
{
Header: 'Full name',
accessor: 'fullName',
Cell: ({
row: {
original: { fullName },
},
}) => <span sx={{ mr: 1 }}>{fullName}</span>,
},
{
Header: 'Title',
accessor: 'title',
Cell: ({
row: {
original: { title },
},
}) => <span>{title}</span>,
},
{
Header: 'Status',
accessor: 'status',
Cell: ({
row: {
original: { status },
},
}) => {
return <span>{status}</span>;
},
},
] as Column<TestRow>[],
[],
);

if (!component?.jest) {
return null;
}

const data: TestRow[] | undefined = component?.jest?.results.reduce(
(acc: TestRow[], { testResults, ...rest }) => {
return [
...acc,
...testResults.map((r, rowNum) => ({
id: acc.length + rowNum,
...rest,
...r,
})),
];
},
[],
);

return (
<Table<TestRow>
sorting={true}
data={data}
columns={columns}
sortBy={[
{
id: 'id',
desc: false,
},
]}
renderRowSubComponent={renderRowSubComponent}
pagination={pagination}
/>
);
};
20 changes: 20 additions & 0 deletions ui/blocks/src/ComponentTests/ComponentTests.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { Document, Example } from '@component-controls/core';
import { ComponentTests, ComponentTestsProps } from './ComponentTests';
import { makeDecorators } from '../test/MockContext';

export default {
title: 'Blocks/ComponentTests',
component: ComponentTests,
category: ' Component',
decorators: makeDecorators('blocks-core-story-plain--controls'),
} as Document;

export const overview: Example = () => <ComponentTests id="." name="Commits" />;

export const pagination: Example<ComponentTestsProps['pagination']> = props => (
<ComponentTests id="." name="Tests" pagination={props} />
);

pagination.smartControls = { smart: false };
pagination.controls = { pageSize: 10, pageVisible: true };
Loading

0 comments on commit 380886a

Please sign in to comment.