mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-16 16:40:06 +00:00
chore(sasjs-tests): use test framework in SASjs Tests
This commit is contained in:
5
sasjs-tests/package-lock.json
generated
5
sasjs-tests/package-lock.json
generated
@@ -1378,6 +1378,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@sasjs/test-framework": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sasjs/test-framework/-/test-framework-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-SA+Rc5N+r29O1OwtZPR7O/Km3FFy3X7zWSYhV+y9cTrruGvILE5mYOS1T9yJb9JJNno3DmtXC+y1XD97F+hDmQ=="
|
||||||
|
},
|
||||||
"@sheerun/mutationobserver-shim": {
|
"@sheerun/mutationobserver-shim": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/adapter": "^1.0.5",
|
"@sasjs/adapter": "^1.0.5",
|
||||||
|
"@sasjs/test-framework": "^1.0.1",
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
"@testing-library/react": "^9.5.0",
|
"@testing-library/react": "^9.5.0",
|
||||||
"@testing-library/user-event": "^7.2.1",
|
"@testing-library/user-event": "^7.2.1",
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
import React, { ReactElement, useState, useContext, useEffect } from "react";
|
import React, { ReactElement, useState, useContext, useEffect } from "react";
|
||||||
|
import { TestSuiteRunner, TestSuite, AppContext } from "@sasjs/test-framework";
|
||||||
|
import { basicTests } from "./testSuites/Basic";
|
||||||
|
import { sendArrTests, sendObjTests } from "./testSuites/RequestData";
|
||||||
|
import { specialCaseTests } from "./testSuites/SpecialCases";
|
||||||
|
import { sasjsRequestTests } from "./testSuites/SasjsRequests";
|
||||||
|
import "@sasjs/test-framework/dist/index.css";
|
||||||
import "./App.scss";
|
import "./App.scss";
|
||||||
import TestSuiteRunner from "./TestSuiteRunner";
|
|
||||||
import { AppContext } from "./context/AppContext";
|
|
||||||
|
|
||||||
const App = (): ReactElement<{}> => {
|
const App = (): ReactElement<{}> => {
|
||||||
const [appLoc, setAppLoc] = useState("");
|
const [appLoc, setAppLoc] = useState("");
|
||||||
const [debug, setDebug] = useState(false);
|
const [debug, setDebug] = useState(false);
|
||||||
const { adapter } = useContext(AppContext);
|
const { adapter, config } = useContext(AppContext);
|
||||||
|
const [testSuites, setTestSuites] = useState<TestSuite[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (adapter) {
|
if (adapter) {
|
||||||
adapter.setDebugState(debug);
|
adapter.setDebugState(debug);
|
||||||
|
setTestSuites([
|
||||||
|
basicTests(adapter, config.userName, config.password),
|
||||||
|
sendArrTests(adapter),
|
||||||
|
sendObjTests(adapter),
|
||||||
|
specialCaseTests(adapter),
|
||||||
|
sasjsRequestTests(adapter),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}, [debug, adapter]);
|
}, [debug, adapter]);
|
||||||
|
|
||||||
@@ -50,7 +62,7 @@ const App = (): ReactElement<{}> => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{adapter && <TestSuiteRunner adapter={adapter} />}
|
{adapter && testSuites && <TestSuiteRunner testSuites={testSuites} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { ReactElement, useState, useCallback, useContext } from "react";
|
import React, { ReactElement, useState, useCallback, useContext } from "react";
|
||||||
import "./Login.scss";
|
import "./Login.scss";
|
||||||
import { AppContext } from "./context/AppContext";
|
import { AppContext } from "@sasjs/test-framework";
|
||||||
import { Redirect } from "react-router-dom";
|
import { Redirect } from "react-router-dom";
|
||||||
|
|
||||||
const Login = (): ReactElement<{}> => {
|
const Login = (): ReactElement<{}> => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { ReactElement, useContext, FunctionComponent } from "react";
|
import React, { ReactElement, useContext, FunctionComponent } from "react";
|
||||||
import { Redirect, Route } from "react-router-dom";
|
import { Redirect, Route } from "react-router-dom";
|
||||||
import { AppContext } from "./context/AppContext";
|
import { AppContext } from "@sasjs/test-framework";
|
||||||
|
|
||||||
interface PrivateRouteProps {
|
interface PrivateRouteProps {
|
||||||
component: FunctionComponent;
|
component: FunctionComponent;
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
.button-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
.loading-spinner {
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-button {
|
|
||||||
padding: 10px;
|
|
||||||
min-height: 80px;
|
|
||||||
font-size: 2em;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import React, { useEffect, useState, ReactElement, useContext } from "react";
|
|
||||||
import TestSuiteComponent from "./components/TestSuite";
|
|
||||||
import TestSuiteCard from "./components/TestSuiteCard";
|
|
||||||
import { TestSuite, Test } from "./types";
|
|
||||||
import { basicTests } from "./testSuites/Basic";
|
|
||||||
import "./TestSuiteRunner.scss";
|
|
||||||
import SASjs from "@sasjs/adapter";
|
|
||||||
import { AppContext } from "./context/AppContext";
|
|
||||||
import { sendArrTests, sendObjTests } from "./testSuites/RequestData";
|
|
||||||
import { specialCaseTests } from "./testSuites/SpecialCases";
|
|
||||||
import { sasjsRequestTests } from "./testSuites/SasjsRequests";
|
|
||||||
|
|
||||||
interface TestSuiteRunnerProps {
|
|
||||||
adapter: SASjs;
|
|
||||||
}
|
|
||||||
const TestSuiteRunner = (
|
|
||||||
props: TestSuiteRunnerProps
|
|
||||||
): ReactElement<TestSuiteRunnerProps> => {
|
|
||||||
const { adapter } = props;
|
|
||||||
const { config } = useContext(AppContext);
|
|
||||||
const [testSuites, setTestSuites] = useState<TestSuite[]>([]);
|
|
||||||
const [runTests, setRunTests] = useState(false);
|
|
||||||
const [completedTestSuites, setCompletedTestSuites] = useState<
|
|
||||||
{
|
|
||||||
name: string;
|
|
||||||
completedTests: {
|
|
||||||
test: Test;
|
|
||||||
result: boolean;
|
|
||||||
error: Error | null;
|
|
||||||
executionTime: number;
|
|
||||||
}[];
|
|
||||||
}[]
|
|
||||||
>([]);
|
|
||||||
const [currentTestSuite, setCurrentTestSuite] = useState<TestSuite | null>(
|
|
||||||
(null as unknown) as TestSuite
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (adapter) {
|
|
||||||
setTestSuites([
|
|
||||||
basicTests(adapter, config.userName, config.password),
|
|
||||||
sendArrTests(adapter),
|
|
||||||
sendObjTests(adapter),
|
|
||||||
specialCaseTests(adapter),
|
|
||||||
sasjsRequestTests(adapter),
|
|
||||||
]);
|
|
||||||
setCompletedTestSuites([]);
|
|
||||||
}
|
|
||||||
}, [adapter]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (testSuites.length) {
|
|
||||||
setCurrentTestSuite(testSuites[0]);
|
|
||||||
}
|
|
||||||
}, [testSuites]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (runTests) {
|
|
||||||
setCompletedTestSuites([]);
|
|
||||||
setCurrentTestSuite(testSuites[0]);
|
|
||||||
}
|
|
||||||
}, [runTests, testSuites]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="button-container">
|
|
||||||
<button
|
|
||||||
className={runTests ? "submit-button disabled" : "submit-button"}
|
|
||||||
onClick={() => setRunTests(true)}
|
|
||||||
disabled={runTests}
|
|
||||||
>
|
|
||||||
{runTests ? (
|
|
||||||
<>
|
|
||||||
<div className="loading-spinner"></div>Running tests...
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
"Run tests!"
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{completedTestSuites.map((completedTestSuite, index) => {
|
|
||||||
return (
|
|
||||||
<TestSuiteCard
|
|
||||||
key={index}
|
|
||||||
tests={completedTestSuite.completedTests}
|
|
||||||
name={completedTestSuite.name}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{currentTestSuite && runTests && (
|
|
||||||
<TestSuiteComponent
|
|
||||||
{...currentTestSuite}
|
|
||||||
onCompleted={(
|
|
||||||
name,
|
|
||||||
completedTests: {
|
|
||||||
test: Test;
|
|
||||||
result: boolean;
|
|
||||||
error: Error | null;
|
|
||||||
executionTime: number;
|
|
||||||
}[]
|
|
||||||
) => {
|
|
||||||
const currentIndex = testSuites.indexOf(currentTestSuite);
|
|
||||||
const nextIndex =
|
|
||||||
currentIndex < testSuites.length - 1 ? currentIndex + 1 : -1;
|
|
||||||
if (nextIndex >= 0) {
|
|
||||||
setCurrentTestSuite(testSuites[nextIndex]);
|
|
||||||
} else {
|
|
||||||
setCurrentTestSuite(null);
|
|
||||||
}
|
|
||||||
const newCompletedTestSuites = [
|
|
||||||
...completedTestSuites,
|
|
||||||
{ name, completedTests },
|
|
||||||
];
|
|
||||||
setCompletedTestSuites(newCompletedTestSuites);
|
|
||||||
|
|
||||||
if (newCompletedTestSuites.length === testSuites.length) {
|
|
||||||
setRunTests(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TestSuiteRunner;
|
|
||||||
@@ -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;
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import React, { createContext, useState, useEffect, ReactNode } from "react";
|
|
||||||
import SASjs from "@sasjs/adapter";
|
|
||||||
|
|
||||||
export const AppContext = createContext<{
|
|
||||||
config: any;
|
|
||||||
sasJsConfig: any;
|
|
||||||
isLoggedIn: boolean;
|
|
||||||
setIsLoggedIn: (value: boolean) => void;
|
|
||||||
adapter: SASjs;
|
|
||||||
}>({
|
|
||||||
config: null,
|
|
||||||
sasJsConfig: null,
|
|
||||||
isLoggedIn: false,
|
|
||||||
setIsLoggedIn: (null as unknown) as (value: boolean) => void,
|
|
||||||
adapter: (null as unknown) as SASjs,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AppProvider = (props: { children: ReactNode }) => {
|
|
||||||
const [config, setConfig] = useState<{ sasJsConfig: any }>({
|
|
||||||
sasJsConfig: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [adapter, setAdapter] = useState<SASjs>((null as unknown) as SASjs);
|
|
||||||
|
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetch("config.json")
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((configJson: any) => {
|
|
||||||
setConfig(configJson);
|
|
||||||
const sasjs = new SASjs(configJson.sasJsConfig);
|
|
||||||
setAdapter(sasjs);
|
|
||||||
sasjs.checkSession().then((response) => {
|
|
||||||
setIsLoggedIn(response.isLoggedIn);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppContext.Provider
|
|
||||||
value={{
|
|
||||||
config,
|
|
||||||
sasJsConfig: config.sasJsConfig,
|
|
||||||
isLoggedIn,
|
|
||||||
setIsLoggedIn,
|
|
||||||
adapter,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{props.children}
|
|
||||||
</AppContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -3,7 +3,7 @@ import ReactDOM from "react-dom";
|
|||||||
import { Route, HashRouter, Switch } from "react-router-dom";
|
import { Route, HashRouter, Switch } from "react-router-dom";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import * as serviceWorker from "./serviceWorker";
|
import * as serviceWorker from "./serviceWorker";
|
||||||
import { AppProvider } from "./context/AppContext";
|
import { AppProvider } from "@sasjs/test-framework";
|
||||||
import PrivateRoute from "./PrivateRoute";
|
import PrivateRoute from "./PrivateRoute";
|
||||||
import Login from "./Login";
|
import Login from "./Login";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import SASjs, { ServerType, SASjsConfig } from "@sasjs/adapter";
|
import SASjs, { ServerType, SASjsConfig } from "@sasjs/adapter";
|
||||||
import { TestSuite } from "../types";
|
import { TestSuite } from "@sasjs/test-framework";
|
||||||
|
|
||||||
const defaultConfig: SASjsConfig = {
|
const defaultConfig: SASjsConfig = {
|
||||||
serverUrl: window.location.origin,
|
serverUrl: window.location.origin,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import SASjs from "@sasjs/adapter";
|
import SASjs from "@sasjs/adapter";
|
||||||
import { TestSuite } from "../types";
|
import { TestSuite } from "@sasjs/test-framework";
|
||||||
|
|
||||||
const stringData: any = { table1: [{ col1: "first col value" }] };
|
const stringData: any = { table1: [{ col1: "first col value" }] };
|
||||||
const numericData: any = { table1: [{ col1: 3.14159265 }] };
|
const numericData: any = { table1: [{ col1: 3.14159265 }] };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import SASjs from "@sasjs/adapter";
|
import SASjs from "@sasjs/adapter";
|
||||||
import { TestSuite } from "../types";
|
import { TestSuite } from "@sasjs/test-framework";
|
||||||
|
|
||||||
const data: any = { table1: [{ col1: "first col value" }] };
|
const data: any = { table1: [{ col1: "first col value" }] };
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import SASjs from "@sasjs/adapter";
|
import SASjs from "@sasjs/adapter";
|
||||||
import { TestSuite } from "../types";
|
import { TestSuite } from "@sasjs/test-framework";
|
||||||
|
|
||||||
const specialCharData: any = {
|
const specialCharData: any = {
|
||||||
table1: [
|
table1: [
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
export interface Test {
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
beforeTest?: (...args: any) => Promise<any>;
|
|
||||||
afterTest?: (...args: any) => Promise<any>;
|
|
||||||
test: (context?: any) => Promise<any>;
|
|
||||||
assertion: (...args: any) => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TestSuite {
|
|
||||||
name: string;
|
|
||||||
tests: Test[];
|
|
||||||
beforeAll?: (...args: any) => Promise<any>;
|
|
||||||
afterAll?: (...args: any) => Promise<any>;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
export const uploadFile = (file: File, fileName: string, url: string) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const data = new FormData();
|
|
||||||
data.append("file", file);
|
|
||||||
data.append("filename", fileName);
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.addEventListener("readystatechange", function () {
|
|
||||||
if (this.readyState === 4) {
|
|
||||||
let response: any;
|
|
||||||
try {
|
|
||||||
response = JSON.parse(this.responseText);
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
resolve(response);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
xhr.open("POST", url);
|
|
||||||
xhr.setRequestHeader("cache-control", "no-cache");
|
|
||||||
xhr.send(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user