Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
1646be2
feat: add backstop js test
Revathyvenugopal162 Sep 30, 2025
bf592bb
chore: adding changelog file 804.added.md [dependabot-skip]
pyansys-ci-bot Sep 30, 2025
da0b372
feat: update the cicd
Revathyvenugopal162 Sep 30, 2025
001fd01
Merge branch 'feat/test' of https://github.com/ansys/ansys-sphinx-the…
Revathyvenugopal162 Sep 30, 2025
26db4d4
feat: update the cicd
Revathyvenugopal162 Sep 30, 2025
e629cc3
feat: update the cicd
Revathyvenugopal162 Sep 30, 2025
0b8e014
feat: update the cicd
Revathyvenugopal162 Sep 30, 2025
68890c7
fix: refernce url
Revathyvenugopal162 Sep 30, 2025
84900fb
fix: xvfb
Revathyvenugopal162 Sep 30, 2025
2e87e71
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 6, 2025
39235bd
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 6, 2025
8e5f41b
fix: add more test cases
Revathyvenugopal162 Oct 6, 2025
f72a977
Merge branch 'feat/test' of https://github.com/ansys/ansys-sphinx-the…
Revathyvenugopal162 Oct 6, 2025
b8c0195
feat: add reference
Revathyvenugopal162 Oct 6, 2025
737f2e4
feat: add references
Revathyvenugopal162 Oct 6, 2025
efe79ae
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 7, 2025
9aea686
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 13, 2025
3577509
fix: components by components tests
Revathyvenugopal162 Oct 14, 2025
ae5ba72
fix: add switch versions
Revathyvenugopal162 Oct 14, 2025
5386a15
fix: add gitignore
Revathyvenugopal162 Oct 14, 2025
83018f2
fix: precommit
Revathyvenugopal162 Oct 14, 2025
78f79c3
feat: add test for sd
Revathyvenugopal162 Oct 14, 2025
e7484ec
fix: precommit
Revathyvenugopal162 Oct 14, 2025
25ff727
feat: add tests for index page
Revathyvenugopal162 Oct 15, 2025
4456c72
feat: add components
Revathyvenugopal162 Oct 15, 2025
c814ec5
feat: update all components
Revathyvenugopal162 Oct 15, 2025
b21bd91
feat: add search bar
Revathyvenugopal162 Oct 15, 2025
8fd0673
feat: update the test_search
Revathyvenugopal162 Oct 15, 2025
d9f3a3a
ci: try test
Revathyvenugopal162 Oct 15, 2025
9945706
ci: try test
Revathyvenugopal162 Oct 15, 2025
8341080
ci: try test
Revathyvenugopal162 Oct 15, 2025
ea63e7f
ci: try test actions
Revathyvenugopal162 Oct 15, 2025
c98737d
feat: update
Revathyvenugopal162 Oct 15, 2025
dc96e1a
ci: try test actions
Revathyvenugopal162 Oct 15, 2025
bb3f70f
test: reference images
Revathyvenugopal162 Oct 15, 2025
480a2fe
ci: update the node
Revathyvenugopal162 Oct 16, 2025
f653bab
ci: update the node install
Revathyvenugopal162 Oct 16, 2025
ecd685b
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 16, 2025
b7a4cbd
feat: add tix
Revathyvenugopal162 Oct 16, 2025
63fbbc8
Merge branch 'feat/test' of https://github.com/ansys/ansys-sphinx-the…
Revathyvenugopal162 Oct 16, 2025
2b65b5a
ci: update the node install
Revathyvenugopal162 Oct 16, 2025
0084e67
feat: cicd
Revathyvenugopal162 Oct 16, 2025
aae871f
feat: cicd
Revathyvenugopal162 Oct 16, 2025
2c3eb9a
feat: cicd
Revathyvenugopal162 Oct 16, 2025
f7d0f8f
feat: cicd
Revathyvenugopal162 Oct 16, 2025
13170fb
fix: update the reference
Revathyvenugopal162 Oct 16, 2025
059d1be
fix: check the dir
Revathyvenugopal162 Oct 16, 2025
fcba814
fix: tests
Revathyvenugopal162 Oct 16, 2025
9a98a54
fix: tests
Revathyvenugopal162 Oct 16, 2025
890f54f
fix: tests
Revathyvenugopal162 Oct 16, 2025
46d57e2
fix: tests python
Revathyvenugopal162 Oct 16, 2025
97ee215
fix: tests python
Revathyvenugopal162 Oct 16, 2025
b005dc4
fix: update the vfb
Revathyvenugopal162 Oct 16, 2025
25b1d28
fix: update the pandoc
Revathyvenugopal162 Oct 16, 2025
67920ae
fix: update the pandoc
Revathyvenugopal162 Oct 16, 2025
119cf1e
fix: update the backstop
Revathyvenugopal162 Oct 17, 2025
3902b0b
fix: cleanup
Revathyvenugopal162 Oct 17, 2025
df121c5
fix: cleanup
Revathyvenugopal162 Oct 17, 2025
ced12ca
fix: dimension
Revathyvenugopal162 Oct 17, 2025
c94f3ec
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 20, 2025
bc542d9
fix: update the conf
Revathyvenugopal162 Oct 20, 2025
2ab58ff
Merge branch 'feat/test' of https://github.com/ansys/ansys-sphinx-the…
Revathyvenugopal162 Oct 20, 2025
16d6bf0
fix: tests tox
Revathyvenugopal162 Oct 20, 2025
0704628
fix: tactions
Revathyvenugopal162 Oct 20, 2025
b1c2956
fix: rename tests
Revathyvenugopal162 Oct 20, 2025
16fc77c
fix: actions hash
Revathyvenugopal162 Oct 20, 2025
a529144
fix: test with treshold
Revathyvenugopal162 Oct 20, 2025
43ef0bc
fix: update the tox
Revathyvenugopal162 Oct 20, 2025
a7b1a10
fix: update the playwright
Revathyvenugopal162 Oct 20, 2025
b1bd9d3
fix: update the pyproject
Revathyvenugopal162 Oct 20, 2025
be76666
Merge branch 'main' into feat/test
jorgepiloto Oct 23, 2025
bab0b92
Merge branch 'main' into feat/test
jorgepiloto Oct 23, 2025
c6721dc
Merge branch 'main' into feat/test
Revathyvenugopal162 Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/backstop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Backstop test
on:
push:
branches:
- main
pull_request:
branches:
- main

permissions:
contents: read

jobs:
backstop-tests:
name: Visual regression tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
persist-credentials: false

- name: Set up Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: "20"

- name: Set up Python
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55
with:
python-version: "3.13"

- name: Install dependencies
run: |
npm install

- name: Install xvfb
run: sudo apt-get install -y xvfb pandoc

- name: Build documentation
run: |
pip install -e .[doc]
xvfb-run make -C doc html

- name: Serve documentation
run: npx http-server -u -p 8000 ./doc/_build/html &

- name: check if server is up
run: curl -I http://localhost:8000 || true

- name: Run BackstopJS tests
run: |
npm run test

- name: Upload Backstop report (if failed)
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: backstop-report
path: backstop_data/html_report


6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,8 @@ doc/source/examples/api/
# node modules and env
node_modules/
.nodeenv/
package-lock.json
package-lock.json

# BackstopJS outputs (do not commit)
tests/backstop_data/
test-results/
1 change: 1 addition & 0 deletions doc/changelog.d/804.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add backstop js test
18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,30 @@
"scripts": {
"build:scss": "sass src/ansys_sphinx_theme/assets/styles/ansys-sphinx-theme.scss src/ansys_sphinx_theme/theme/ansys_sphinx_theme/static/styles/ansys-sphinx-theme.css",
"build:postcss": "postcss src/ansys_sphinx_theme/theme/ansys_sphinx_theme/static/styles/ansys-sphinx-theme.css -o src/ansys_sphinx_theme/theme/ansys_sphinx_theme/static/styles/ansys-sphinx-theme.css",
"build": "npm run build:scss && npm run build:postcss"
"build": "npm run build:scss && npm run build:postcss",
"reference-tests": "cd tests && backstop reference && backstop test",
"playwright-test": "npx playwright install && cd tests && npx playwright test",
"test": "npm run reference-tests && npm run playwright-test"
},
"scriptsDescription": {
"build:scss": "Compile SCSS to CSS",
"build:postcss": "Apply PostCSS transformations (autoprefixer, minify, etc.)",
"build": "Build complete CSS from SCSS and apply PostCSS",
"reference-tests": "Run BackstopJS visual regression tests (reference and test)",
"playwright-test": "Run Playwright end-to-end tests",
"test": "Run all tests (visual regression + e2e)"
},
"devDependencies": {
"@playwright/test": "^1.56.0",
"autoprefixer": "^10.4.21",
"backstopjs": "^6.3.25",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.0",
"postcss-import": "^16.1.0",
"postcss-minify": "^1.1.0",
"postcss-nested": "^7.0.2",
"sass": "^1.85.1"
"sass": "^1.85.1",
"wait-on": "^9.0.1"
},
"dependencies": {
"postcss-scss": "^4.0.9"
Expand Down
116 changes: 116 additions & 0 deletions tests/backstop.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"id": "ansys_sphinx_theme_backstop",
"viewports": [
{
"label": "tablet",
"width": 1024,
"height": 768
},
{
"label": "desktop",
"width": 1920,
"height": 1080
}
],
"onBeforeScript": "puppet/onBefore.js",
"onReadyScript": "puppet/onReady.js",
"scenarios": [
{
"label": "Ansys Sphinx Theme - Home Page",
"cookiePath": "backstop_data/engine_scripts/cookies.json",
"url": "http://localhost:8000",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"hideSelectors": [],
"removeSelectors": [],
"hoverSelector": "",
"clickSelector": "",
"postInteractionWait": 0,
"selectors": [],
"selectorExpansion": true,
"expect": 0,
"misMatchThreshold" : 0.1,
"requireSameDimensions": true
},
{
"label": "Ansys Sphinx Theme - sphinx design example page",
"url": "http://localhost:8000/examples/sphinx-design.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/sphinx-design.html",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"misMatchThreshold" : 0.1,
"requireSameDimensions": false
},
{
"label": "Ansys Sphinx Theme - api reference example page",
"url": "http://localhost:8000/examples/api/examples/index.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/api/examples/index.html",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"misMatchThreshold" : 0.2,
"requireSameDimensions": false
},
{
"label": "Ansys Sphinx Theme - jupyter notebook example page",
"url": "http://localhost:8000/examples/nbsphinx/jupyter-notebook.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/nbsphinx/jupyter-notebook.html",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"misMatchThreshold" : 0.1,
"requireSameDimensions": false
},
{
"label": "Ansys Sphinx Theme - examples- table page",
"url": "http://localhost:8000/examples/table.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/table.html",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"misMatchThreshold" : 0.1,
"requireSameDimensions": false
},
{
"label": "Ansys Sphinx Theme - admonitions example page",
"url": "http://localhost:8000/examples/admonitions.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/admonitions.html",
"readyEvent": "",
"readySelector": "",
"delay": 20,
"misMatchThreshold" : 0.1,
"requireSameDimensions": false
},
{
"label": "Ansys Sphinx Theme - gallery examples page",
"url": "http://localhost:8000/examples/gallery-examples/index.html",
"referenceUrl": "https://sphinxdocs.ansys.com/version/dev/examples/gallery-examples/index.html",
"delay": 20,
"misMatchThreshold" : 0.1,
"requireSameDimensions": false
}
],
"paths": {
"bitmaps_reference": "backstop_data/bitmaps_reference",
"bitmaps_test": "backstop_data/bitmaps_test",
"engine_scripts": "backstop_data/engine_scripts",
"html_report": "backstop_data/html_report",
"ci_report": "backstop_data/ci_report"
},
"ci": {
"format": "junit",
"testReportFileName": "myproject-xunit"
},
"report": ["browser","CI"],
"engine": "puppet",
"engineOptions": {
"args": ["--no-sandbox"]
},
"asyncCaptureLimit": 5,
"asyncCompareLimit": 50,
"debug": false,
"debugWindow": false
}
136 changes: 136 additions & 0 deletions tests/test_components.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { test, expect } from "@playwright/test";

// Code blocks and copy button
test("Test code blocks and copy button", async ({ page }) => {
await page.goto("http://localhost:8000/user-guide/configuration.html");
const codeBlock = await page.$(".highlight");
if (!codeBlock) test.skip("No code block found on this page");
expect(codeBlock).not.toBeNull();
const copyBtn = await page.$("button.copybtn, .copy-button, .btn-copy");
if (copyBtn) await copyBtn.click();
expect(copyBtn).not.toBeNull();
});

// Tabs (Sphinx-design)
test("Test sphinx tabs", async ({ page }) => {
await page.goto("http://localhost:8000/user-guide/configuration.html");
const tabSet = await page.$(".sd-tab-set, .tab-set, .tab-content");
expect(tabSet).not.toBeNull();
const tabLabels = await page.$$(
".sd-tab-label, .tab-label, .nav-tabs .nav-link",
);
if (tabLabels.length > 1) {
await tabLabels[1].click();
}
});

// Tables
test("Test tables", async ({ page }) => {
await page.goto("http://localhost:8000/examples/table.html");
const table = await page.$(".pst-scrollable-table-container");
expect(table).not.toBeNull();
const headers = await table.$$("th");
expect(headers.length).toBeGreaterThan(0);
const rows = await table.$$("tbody tr");
expect(rows.length).toBeGreaterThan(0);
});

// Admonitions
test("Test admonitions", async ({ page }) => {
await page.goto("http://localhost:8000/examples/admonitions.html");
const admonition = await page.$(
".admonition, .note, .warning, .caution, .tip, .important",
);
expect(admonition).not.toBeNull();
});

// Sphinx-design components
test("Test example sphinx design page card", async ({ page }) => {
await page.goto("http://localhost:8000/examples/sphinx-design.html");
const card = await page.$(".sd-card, .card, div.sd-card");
expect(card).not.toBeNull();
});

// Sphinx-design grid layout
test("Test example sphinx design page grid", async ({ page }) => {
await page.goto("http://localhost:8000/examples/sphinx-design.html");
const grid = await page.$(".sd-row, .sd-grid, .row, .grid");
expect(grid).not.toBeNull();
});

// Sphinx-design badge
test("Test example sphinx design page badge", async ({ page }) => {
await page.goto("http://localhost:8000/examples/sphinx-design.html");
// Sphinx-design badges are usually rendered as span.sd-badge or similar
const badge = await page.$(".sd-badge, span.sd-badge, button.sd-badge");
expect(badge).not.toBeNull();
// Only click if it's a button or has a click handler
if (badge) {
const tag = await badge.evaluate((el) => el.tagName.toLowerCase());
if (tag === "button") {
await badge.click();
}
// If not a button, just check it exists
}
});

// Sphinx-design clickable card
test("Test clickable card", async ({ page }) => {
await page.goto("http://localhost:8000/examples/sphinx-design.html");
// Find the stretched link inside the card
const link = await page.$(
'.sd-card:has(.sd-card-title:has-text("Clickable Card (external)")) a.sd-stretched-link',
);
expect(link).not.toBeNull();
const href = await link.getAttribute("href");
// Check if link opens in new tab
const target = await link.getAttribute("target");
if (target === "_blank") {
const [newPage] = await Promise.all([
page.context().waitForEvent("page"),
link.click(),
]);
await newPage.waitForLoadState();
expect(newPage.url()).toContain(href);
} else {
await Promise.all([page.waitForNavigation(), link.click()]);
expect(page.url()).toContain(href);
}
});

// Sphinx-design dropdown
test("Test sphinx-design dropdown", async ({ page }) => {
await page.goto("http://localhost:8000/examples/sphinx-design.html");
// Target the <details> element with .sd-dropdown
const dropdown = await page.$("details.sd-dropdown");
expect(dropdown).not.toBeNull();
// Find the summary inside the dropdown
const summary = await dropdown.$("summary.sd-summary-title");
expect(summary).not.toBeNull();
// If the dropdown is open, close it first
let isOpen = await dropdown.getAttribute("open");
if (isOpen) {
await summary.click();
await page.waitForTimeout(200);
}
// Now open the dropdown
await summary.click();
await page.waitForTimeout(200);
isOpen = await dropdown.getAttribute("open");
expect(isOpen).not.toBeNull();
// Check for dropdown content
const content = await dropdown.$(".sd-summary-content");
expect(content).not.toBeNull();
const text = await content.textContent();
expect(text).toContain("Dropdown content");
});

test("Test sidebar", async ({ page }) => {
await page.goto("http://localhost:8000/user-guide.html");
const sidebar = await page.$(
'.bd-sidebar-primary, .bd-sidebar-secondary, .sidebar, nav[role="navigation"]',
);
expect(sidebar).not.toBeNull();
const links = await sidebar.$$("a");
expect(links.length).toBeGreaterThan(0);
});
Loading
Loading