Skip to content

Commit

Permalink
🎉 (test page) add explorer test pages (#3246)
Browse files Browse the repository at this point in the history
### Background

- It would be great if we had some testing in place for explorers
    - In recent months, two explorer bugs happened that we should have caught before they went live:
        1. The source line disappeared for charts in an explorer 
        2. The entity selector disappeared for an explorer 
     - Both of these bugs weren't a result of work that was done on explorers, they were the result of code changes that were made far away from explorers
     - Additionally, these bugs only surfaced for one (or few) explorers, not all of them
     - (What I'm trying to say is that, without any testing in place, it is quite difficult at the moment to catch these bugs before shipping because, in theory, we would need to manually check all explorers for every grapher code change...)
 - In the long term, I'd love for the site screenshotting tool to include a few carefully selected explorers (ideal would be all of them, but I realise that that is probably not feasible...)
- For now, I figured that a relatively simple thing to do that would help me check explorers before shipping is to add explorer test pages in the admin that allow me to quickly scroll through before/after views of all explorers

### Summary

Adds:
- explorer test page that lists before/after views of all published explorers
- three more test pages that split explorer by chart creation mode, i.e.
    - Grapher id based explorers
    - CSV based explorers
    - Indicator based explorers

### Notes

- I didn't add pagination because I prefer scrolling and I think lazy loading should be enough to make the page performant
- Test pages don't currently work on staging sites because the [embed script](https://ourworldindata.org/grapher/embedCharts.js) isn't correctly served on staging. It's something that Marcel will look into once he's back
  • Loading branch information
sophiamersmann authored Mar 13, 2024
1 parent 19f5469 commit 5609362
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
36 changes: 36 additions & 0 deletions adminSiteClient/TestIndexPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,42 @@ export class TestIndexPage extends React.Component {
</Link>
</li>
</ul>

<h2>Test Explorer Embeds</h2>
<ul>
<li>
<Link native target="_blank" to="/test/explorers">
All explorers
</Link>
</li>
<li>
<Link
native
target="_blank"
to="/test/explorers?type=grapher-ids"
>
Grapher ID-based explorers
</Link>
</li>
<li>
<Link
native
target="_blank"
to="/test/explorers?type=csv-files"
>
CSV file-based explorers
</Link>
</li>
<li>
<Link
native
target="_blank"
to="/test/explorers?type=indicators"
>
Indicator-based explorers
</Link>
</li>
</ul>
</main>
</AdminLayout>
)
Expand Down
136 changes: 136 additions & 0 deletions adminSiteServer/testPageRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ import {
GrapherTabOption,
StackMode,
} from "@ourworldindata/types"
import { ExplorerAdminServer } from "../explorerAdminServer/ExplorerAdminServer.js"
import { GIT_CMS_DIR } from "../gitCms/GitCmsConstants.js"
import { ExplorerChartCreationMode } from "../explorer/ExplorerConstants.js"

const IS_LIVE = ADMIN_BASE_URL === "https://owid.cloud"
const DEFAULT_COMPARISON_URL = "https://ourworldindata.org"

const explorerAdminServer = new ExplorerAdminServer(GIT_CMS_DIR)

const testPageRouter = Router()

interface ChartItem {
Expand All @@ -51,6 +56,21 @@ function getViewPropsFromQueryParams(
return { comparisonUrl, hasComparisonView }
}

function getChartCreationModeFromQueryParams(
params: Pick<ExplorerTestPageQueryParams, "type">
): ExplorerChartCreationMode | undefined {
switch (params.type) {
case "grapher-ids":
return ExplorerChartCreationMode.FromGrapherId
case "csv-files":
return ExplorerChartCreationMode.FromExplorerTableColumnSlugs
case "indicators":
return ExplorerChartCreationMode.FromVariableIds
default:
return undefined
}
}

function parseStringArrayOrUndefined(param: string | undefined): string[] {
if (param === undefined) return []
return param.split(",")
Expand Down Expand Up @@ -83,6 +103,12 @@ interface EmbedTestPageQueryParams {
readonly namespaces?: string
}

interface ExplorerTestPageQueryParams {
readonly originalUrl?: string
readonly comparisonUrl?: string
readonly type?: "grapher-ids" | "csv-files" | "indicators"
}

async function propsFromQueryParams(
params: EmbedTestPageQueryParams
): Promise<EmbedTestPageProps> {
Expand Down Expand Up @@ -606,4 +632,114 @@ testPageRouter.get("/:slug.svg", async (req, res) => {
res.send(await grapherToSVG(grapher.config, vardata))
})

testPageRouter.get("/explorers", async (req, res) => {
let explorers = await explorerAdminServer.getAllPublishedExplorers()
const viewProps = getViewPropsFromQueryParams(req.query)
const chartCreationMode = getChartCreationModeFromQueryParams(req.query)

if (chartCreationMode) {
explorers = explorers.filter(
(explorer) => explorer.chartCreationMode === chartCreationMode
)
}

const slugs = explorers.map((explorer) => explorer.slug)

res.send(
renderToHtmlPage(<ExplorerTestPage slugs={slugs} {...viewProps} />)
)
})

interface ExplorerTestPageProps {
slugs: string[]
comparisonUrl?: string
hasComparisonView?: boolean
}

function ExplorerTestPage(props: ExplorerTestPageProps) {
const comparisonUrl = props.comparisonUrl ?? DEFAULT_COMPARISON_URL

const style = `
html, body {
height: 100%;
margin: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
figure, iframe {
border: 0;
flex: 1;
height: 700px;
width: 100%;
margin: 10px;
max-width: 1200px;
}
.row {
padding: 10px;
margin: 0;
border-bottom: 1px solid #ddd;
}
.side-by-side {
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
}
.side-by-side + .side-by-side {
margin-top: 64px;
}
h3 {
font-size: 18px;
font-weight: bold;
}
.row > h3 {
text-align: center;
}
`

return (
<html>
<Head
canonicalUrl=""
pageTitle="Test Explorers"
baseUrl={BAKED_BASE_URL}
>
<style dangerouslySetInnerHTML={{ __html: style }} />
</Head>
<body>
<div className="row">
<div className="side-by-side">
{props.hasComparisonView && <h3>{comparisonUrl}</h3>}
<h3>{BAKED_BASE_URL}</h3>
</div>
</div>
{props.slugs.map((slug, index) => (
<div key={slug} className="row">
<h3>
{slug} ({index + 1}/{props.slugs.length})
</h3>
<div className="side-by-side">
{props.hasComparisonView && (
<iframe
src={`${comparisonUrl}/explorers/${slug}`}
loading="lazy"
/>
)}
<figure
data-explorer-src={`${BAKED_BASE_URL}/explorers/${slug}`}
/>
</div>
</div>
))}
<script src={`${BAKED_BASE_URL}/assets/embedCharts.js`} />
</body>
</html>
)
}

export { testPageRouter }

0 comments on commit 5609362

Please sign in to comment.