We at SerpApi show integration test results on documentation pages. Anyone can browse source code of our RSpec files and it’s output. There’s a build badge on all documentation pages which points to the page with the list of test files. Each test file also displays build badge.
We started with Shields.io, but then implemented badges manually in React without SVG and dependencies. Complete code on Codesandbox.io.
Badge component usage
function App() {
return (
<div className="App">
<BuildBadge
status="loading"
summary="loading..."
page_url="https://serpapi.com/search-api"
/>
<BuildBadge
status="error"
summary="125 examples, 3 failures"
page_url="https://serpapi.com/organic-results"
/>
<BuildBadge
status="success"
summary="50 examples, 0 failures"
page_url="https://serpapi.com/google-scholar-api"
/>
<BuildBadge
status="pending"
summary="87 examples, 2 pending"
page_url="https://serpapi.com/images-results"
/>
</div>
);
}
Badge component itself
function BuildBadge({ status, summary, page_url }) {
let spinner;
if (status === "loading") {
spinner = <span className="loader" />;
}
return (
<div className="build-badge-container">
<a href={page_url}>
<div className="badge-name">build</div>
<div className={`badge-status ${status}`}>
{spinner}
<span>{summary}</span>
</div>
</a>
</div>
);
}
Badge styles
/* Thanks to https://shields.io/category/build for inspiration */
.build-badge-container {
height: 20px;
min-width: 200px;
margin: 2px 0;
}
.badge-name,
.badge-status {
display: inline-block;
height: 18px;
color: #fff;
font-family: Verdana, DejaVu Sans, sans-serif;
font-size: 11px;
line-height: 1.538;
letter-spacing: 0px;
text-shadow: 0px 1px rgba(1, 1, 1, 0.3);
}
.badge-name {
background: rgb(95, 95, 95);
background: linear-gradient(
180deg,
rgba(95, 95, 95, 1) 0%,
rgba(78, 78, 78, 1) 100%
);
border-radius: 3px 0px 0px 3px;
padding: 2px 4px 0px 6px;
}
.badge-status {
border-radius: 0px 3px 3px 0px;
padding: 2px 6px 0px 4px;
}
.badge-status.loading {
background: rgb(223, 179, 23);
background: linear-gradient(
180deg,
rgba(223, 179, 23, 1) 0%,
rgba(206, 162, 6, 1) 100%
);
}
.badge-status.success {
background: rgb(223, 179, 23);
background: linear-gradient(
180deg,
rgba(85, 202, 48, 1) 0%,
rgba(62, 183, 17, 1) 100%
);
}
.badge-status.pending {
background: rgb(247, 132, 71);
background: linear-gradient(
180deg,
rgba(247, 132, 71, 1) 0%,
rgba(228, 113, 49, 1) 100%
);
}
.badge-status.error,
.badge-status.failed {
background: rgb(221, 103, 81);
background: linear-gradient(
180deg,
rgba(221, 103, 81, 1) 0%,
rgba(201, 84, 61, 1) 100%
);
}
/* Thanks to
https://vineethtrv.github.io/loader/
and
https://www.w3schools.com/howto/howto_css_loader.asp
for inspiration
*/
.loader {
position: relative;
padding-left: 20px; /* spinner size * 2 */
}
.loader::before {
content: "";
display: inline-block;
position: absolute;
left: 0;
top: 0;
margin: 0px 6px 0px 2px;
border: 1px solid transparent;
border-radius: 50%;
border-top: 2px solid #fff;
width: 10px;
height: 10px;
animation: spin 1s ease-out infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
Thanks to Shields.io, Vineeth TR and W3Schools for inspiration.
Top comments (0)