mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-10 22:00:05 +00:00
chore(sasjs-tests): use test framework in SASjs Tests
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
import React, { ReactElement, useEffect, useState } from "react";
|
||||
import TestCard from "./TestCard";
|
||||
import { start } from "repl";
|
||||
|
||||
interface TestProps {
|
||||
title: string;
|
||||
description: string;
|
||||
beforeTest?: (...args: any) => Promise<any>;
|
||||
afterTest?: (...args: any) => Promise<any>;
|
||||
test: (context: any) => Promise<any>;
|
||||
assertion: (...args: any) => boolean;
|
||||
onCompleted: (payload: {
|
||||
result: boolean;
|
||||
error: Error | null;
|
||||
executionTime: number;
|
||||
}) => void;
|
||||
context: any;
|
||||
}
|
||||
|
||||
const getStatus = (isRunning: boolean, isPassed: boolean): string => {
|
||||
return isRunning ? "running" : isPassed ? "passed" : "failed";
|
||||
};
|
||||
|
||||
const Test = (props: TestProps): ReactElement<TestProps> => {
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
test,
|
||||
beforeTest,
|
||||
afterTest,
|
||||
assertion,
|
||||
onCompleted,
|
||||
context,
|
||||
} = props;
|
||||
const beforeTestFunction = beforeTest ? beforeTest : () => Promise.resolve();
|
||||
const afterTestFunction = afterTest ? afterTest : () => Promise.resolve();
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const [isPassed, setIsPassed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (test && assertion) {
|
||||
const startTime = new Date().valueOf();
|
||||
setIsRunning(true);
|
||||
setIsPassed(false);
|
||||
beforeTestFunction()
|
||||
.then(() => test(context))
|
||||
.then((res) => {
|
||||
setIsRunning(false);
|
||||
setIsPassed(assertion(res, context));
|
||||
return Promise.resolve(assertion(res, context));
|
||||
})
|
||||
.then((testResult) => {
|
||||
afterTestFunction();
|
||||
const endTime = new Date().valueOf();
|
||||
const executionTime = (endTime - startTime) / 1000;
|
||||
onCompleted({ result: testResult, error: null, executionTime });
|
||||
})
|
||||
.catch((e) => {
|
||||
setIsRunning(false);
|
||||
setIsPassed(false);
|
||||
console.error(e);
|
||||
const endTime = new Date().valueOf();
|
||||
const executionTime = (endTime - startTime) / 1000;
|
||||
onCompleted({ result: false, error: e, executionTime });
|
||||
});
|
||||
}
|
||||
}, [test, assertion]);
|
||||
|
||||
return (
|
||||
<TestCard
|
||||
title={title}
|
||||
description={description}
|
||||
status={getStatus(isRunning, isPassed)}
|
||||
error={null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Test;
|
||||
@@ -1,62 +0,0 @@
|
||||
.test {
|
||||
display: inline-flex;
|
||||
padding: 8px;
|
||||
margin: 8px;
|
||||
flex-direction: column;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
width: 20%;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: #eee;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.description,
|
||||
.execution-time {
|
||||
color: #c6c0c0;
|
||||
padding: 8px 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.description {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.execution-time {
|
||||
color: #f9e804;
|
||||
}
|
||||
|
||||
.icon {
|
||||
border-radius: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 8px;
|
||||
display: inline-block;
|
||||
|
||||
&.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
&.passed {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
&.failed {
|
||||
background-color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
.test {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 901px) and (max-width: 1280px) {
|
||||
.test {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import "./TestCard.scss";
|
||||
|
||||
interface TestCardProps {
|
||||
title: string;
|
||||
description: string;
|
||||
status: string;
|
||||
error: Error | null;
|
||||
executionTime?: number;
|
||||
}
|
||||
const TestCard = (props: TestCardProps): ReactElement<TestCardProps> => {
|
||||
const { title, description, status, error, executionTime } = props;
|
||||
|
||||
return (
|
||||
<div className="test">
|
||||
<code className="title">{title}</code>
|
||||
<span className="description">{description}</span>
|
||||
<span className="execution-time">
|
||||
{executionTime ? executionTime.toFixed(2) + "s" : ""}
|
||||
</span>
|
||||
{status === "running" && (
|
||||
<div>
|
||||
<span className="icon running"></span>Running...
|
||||
</div>
|
||||
)}
|
||||
{status === "passed" && (
|
||||
<div>
|
||||
<span className="icon passed"></span>Passed
|
||||
</div>
|
||||
)}
|
||||
{status === "failed" && (
|
||||
<>
|
||||
<div>
|
||||
<span className="icon failed"></span>Failed
|
||||
</div>
|
||||
{!!error && <code>{error.message}</code>}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestCard;
|
||||
@@ -1,106 +0,0 @@
|
||||
import React, { ReactElement, useState, useEffect } from "react";
|
||||
import "./TestSuiteCard.scss";
|
||||
import { Test } from "../types";
|
||||
import TestComponent from "./Test";
|
||||
import TestCard from "./TestCard";
|
||||
|
||||
interface TestSuiteProps {
|
||||
name: string;
|
||||
tests: Test[];
|
||||
beforeAll?: (...args: any) => Promise<any>;
|
||||
afterAll?: (...args: any) => Promise<any>;
|
||||
onCompleted: (
|
||||
name: string,
|
||||
completedTests: {
|
||||
test: Test;
|
||||
result: boolean;
|
||||
error: Error | null;
|
||||
executionTime: number;
|
||||
}[]
|
||||
) => void;
|
||||
}
|
||||
const TestSuite = (props: TestSuiteProps): ReactElement<TestSuiteProps> => {
|
||||
const { name, tests, beforeAll, afterAll, onCompleted } = props;
|
||||
const [context, setContext] = useState<any>(null);
|
||||
const [completedTests, setCompletedTests] = useState<
|
||||
{
|
||||
test: Test;
|
||||
result: boolean;
|
||||
error: Error | null;
|
||||
executionTime: number;
|
||||
}[]
|
||||
>([]);
|
||||
const [currentTest, setCurrentTest] = useState<Test | null>(
|
||||
(null as unknown) as Test
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (beforeAll) {
|
||||
beforeAll().then((data) => setContext({ data }));
|
||||
}
|
||||
}, [beforeAll]);
|
||||
|
||||
useEffect(() => {
|
||||
if (tests.length) {
|
||||
setCurrentTest(tests[0]);
|
||||
}
|
||||
setCompletedTests([]);
|
||||
setContext(null);
|
||||
}, [tests]);
|
||||
|
||||
return (!!beforeAll && !!context) || !beforeAll ? (
|
||||
<div className="test-suite">
|
||||
<div className="test-suite-name running">{name}</div>
|
||||
{currentTest && (
|
||||
<TestComponent
|
||||
{...currentTest}
|
||||
context={context}
|
||||
onCompleted={(completedTest) => {
|
||||
const newCompleteTests = [
|
||||
...completedTests,
|
||||
{
|
||||
test: currentTest,
|
||||
result: completedTest.result,
|
||||
error: completedTest.error,
|
||||
executionTime: completedTest.executionTime,
|
||||
},
|
||||
];
|
||||
setCompletedTests(newCompleteTests);
|
||||
const currentIndex = tests.indexOf(currentTest);
|
||||
const nextIndex =
|
||||
currentIndex < tests.length - 1 ? currentIndex + 1 : -1;
|
||||
if (nextIndex >= 0) {
|
||||
setCurrentTest(tests[nextIndex]);
|
||||
} else {
|
||||
setCurrentTest(null);
|
||||
}
|
||||
if (newCompleteTests.length === tests.length) {
|
||||
if (afterAll) {
|
||||
afterAll().then(() => onCompleted(name, newCompleteTests));
|
||||
} else {
|
||||
onCompleted(name, newCompleteTests);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{completedTests.map((completedTest, index) => {
|
||||
const { test, result, error } = completedTest;
|
||||
const { title, description } = test;
|
||||
return (
|
||||
<TestCard
|
||||
key={index}
|
||||
title={title}
|
||||
description={description}
|
||||
status={result === true ? "passed" : "failed"}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestSuite;
|
||||
@@ -1,19 +0,0 @@
|
||||
.test-suite {
|
||||
.test-suite-name {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #1f2027;
|
||||
|
||||
&.passed {
|
||||
color: green;
|
||||
}
|
||||
|
||||
&.failed {
|
||||
color: red;
|
||||
}
|
||||
|
||||
&.running {
|
||||
color: yellow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import "./TestSuiteCard.scss";
|
||||
import { Test } from "../types";
|
||||
import TestCard from "./TestCard";
|
||||
|
||||
interface TestSuiteCardProps {
|
||||
name: string;
|
||||
tests: {
|
||||
test: Test;
|
||||
result: boolean;
|
||||
error: Error | null;
|
||||
executionTime: number;
|
||||
}[];
|
||||
}
|
||||
const TestSuiteCard = (
|
||||
props: TestSuiteCardProps
|
||||
): ReactElement<TestSuiteCardProps> => {
|
||||
const { name, tests } = props;
|
||||
const overallStatus = tests.map((t) => t.result).reduce((x, y) => x && y);
|
||||
|
||||
return (
|
||||
<div className="test-suite">
|
||||
<div className={`test-suite-name ${overallStatus ? "passed" : "failed"}`}>
|
||||
{name}
|
||||
</div>
|
||||
{tests.map((completedTest, index) => {
|
||||
const { test, result, error, executionTime } = completedTest;
|
||||
const { title, description } = test;
|
||||
return (
|
||||
<TestCard
|
||||
key={index}
|
||||
title={title}
|
||||
description={description}
|
||||
status={result === true ? "passed" : "failed"}
|
||||
error={error}
|
||||
executionTime={executionTime}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestSuiteCard;
|
||||
Reference in New Issue
Block a user