Skip to content

Commit

Permalink
Generic Sphinx-Needs JS test framework
Browse files Browse the repository at this point in the history
  • Loading branch information
iSOLveIT committed Sep 2, 2023
1 parent 321dcd5 commit b844648
Show file tree
Hide file tree
Showing 6 changed files with 838 additions and 771 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Cypress Test Framework
run: npm install cypress
- name: Install Nox Dependencies
run: |
python -m pip install poetry nox nox-poetry pyparsing==3.0.4
Expand Down
1,423 changes: 660 additions & 763 deletions poetry.lock

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""Pytest conftest module containing common test configuration and fixtures."""
import json
import shutil
from pathlib import Path
from tempfile import mkdtemp

import pytest
from sphinx.application import Sphinx
from sphinx.testing.path import path

pytest_plugins = "sphinx.testing.fixtures"
Expand All @@ -15,6 +18,13 @@ def copy_srcdir_to_tmpdir(srcdir, tmp):
return tmproot


def get_abspath(relpath):
if relpath and isinstance(relpath, str):
abspath = Path(__file__).parent.joinpath(relpath).resolve()
return str(abspath)
return relpath


@pytest.fixture(scope="function")
def test_app(make_app, request):
# We create a temp-folder on our own, as the util-functions from sphinx and pytest make troubles.
Expand All @@ -32,7 +42,7 @@ def test_app(make_app, request):
src_dir = copy_srcdir_to_tmpdir(srcdir, sphinx_test_tempdir)

# return sphinx.testing fixture make_app and new srcdir which in sphinx_test_tempdir
app = make_app(
app: Sphinx = make_app(
buildername=builder_params.get("buildername", "html"),
srcdir=src_dir,
freshenv=builder_params.get("freshenv"),
Expand All @@ -44,6 +54,21 @@ def test_app(make_app, request):
parallel=builder_params.get("parallel", 0),
)

cypress_test_config = builder_params.get("cypress_test_config")
js_test_config = {}

if cypress_test_config:
js_test_config["specPattern"] = get_abspath(cypress_test_config.get("specPattern"))
js_test_config["supportFile"] = get_abspath(cypress_test_config.get("supportFile")) or get_abspath(
"js_test/cypress/support/e2e.js"
)
js_test_config["fixturesFolder"] = False
js_test_config["baseUrl"] = "http://localhost:65323"

json_string = f"{json.dumps(js_test_config)}"

app.cypress_config_file = get_abspath("js_test/cypress.config.js")
app.cypress_config = json_string
yield app

# cleanup test temporary directory
Expand Down
7 changes: 0 additions & 7 deletions tests/doc_test/variant_doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,3 @@ Variant Handling Test
:maxdepth: 2
:caption: Contents:


Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
86 changes: 86 additions & 0 deletions tests/js_test/variant_doc/test-collapse-button.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
describe('Test Sphinx Needs Collapse', () => {
it('Visit Sphinx Needs Homepage', () => {
// 1. Given a user visits http://localhost:65323/
cy.visit('/')

cy.get('table.need span.needs.needs_collapse').each(($el, index, $list) => {
// 2. When page loads, select all elements that matches the selector `table.need span.needs.needs_collapse`

var id = $el.attr("id");
var parts = id.split("__");
var rows = parts.slice(2);

var table = $el.closest('table');
var need_table_id = table.closest("div[id^=SNCB-]").attr("id");

// 3. Check if the id of the element contains show or hide
if (parts[1] == "show") {
cy.get($el).within(() => {
// 4. Then check if `span.needs.visible` has the class `collapse_is_hidden`
cy.get('span.needs.visible').should('have.class', 'collapse_is_hidden')
})
} else {
cy.get($el).within(() => {
// 4. Then check if `span.needs.collapse` has the class `collapse_is_hidden`
cy.get('span.needs.collapsed').should('have.class', 'collapse_is_hidden')
})

for (var row in rows) {
// 5. And check if `#${need_table_id} table tr.${rows[row]}` has the class `collapse_is_hidden`
cy.get(`#${need_table_id} table tr.${rows[row]}`).should('have.class', 'collapse_is_hidden')
}
}
})
})
})

describe('Test Sphinx Needs Collapse Click', () => {
it('Visit Sphinx Needs Directive page', () => {
// 1. Given a user visits http://localhost:65323/
cy.visit('/')

cy.get('table.need span.needs.needs_collapse').each(($el, index, $list) => {
// 2. When page loads, select all elements that matches the selector `table.need span.needs.needs_collapse`

var id = $el.attr("id");
var parts = id.split("__");
var rows = parts.slice(2);

var table = $el.closest('table');
var need_table_id = table.closest("div[id^=SNCB-]").attr("id");

if (parts[1] == "show") {
// 3. Click collapse/expand button
cy.get($el).click()

for (var row in rows) {
// 4. And check if `#${need_table_id} table tr.${rows[row]}` has the class `collapse_is_hidden`
cy.get(`#${need_table_id} table tr.${rows[row]}`).should('have.class', 'collapse_is_hidden')
}

cy.get($el).within(() => {
// 5. Then check if `span.needs.collapse` has the class `collapse_is_hidden`
cy.get('span.needs.collapsed').should('have.class', 'collapse_is_hidden')
// 6. And check if `span.needs.visible` has the class `collapse_is_hidden`
cy.get('span.needs.visible').should('not.have.class', 'collapse_is_hidden')
})
} else{
// 3. Click collapse/expand button
cy.get($el).click()

for (var row in rows) {
// 4. And check if `#${need_table_id} table tr.${rows[row]}` has the class `collapse_is_hidden`
cy.get(`#${need_table_id} table tr.${rows[row]}`).should('not.have.class', 'collapse_is_hidden')
}

cy.get($el).within(() => {
// 5. Then check if `span.needs.collapse` has the class `collapse_is_hidden`
cy.get('span.needs.collapsed').should('not.have.class', 'collapse_is_hidden')
// 6. Check if `span.needs.visible` has the class `collapse_is_hidden`
cy.get('span.needs.visible').should('have.class', 'collapse_is_hidden')
})
}

})
})
})
60 changes: 60 additions & 0 deletions tests/test_variants.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,63 @@ def test_empty_variant_options_html(test_app):
'<span class="needs_dead_link '
'forbidden">unknown</span></span></span></div>' in html
)


@pytest.mark.parametrize(
"test_app",
[
{
"buildername": "html",
"srcdir": "doc_test/variant_doc",
"tags": ["tag_a"],
"cypress_test_config": {
"specPattern": "js_test/variant_doc/*",
"supportFile": "js_test/cypress/support/e2e.js",
},
}
],
indirect=True,
)
def test_cypress_js_testing_framework(test_app):
"""A quick working example of JS testing framework."""
import subprocess

app = test_app
app.build()

# Start the HTTP server using subprocess
server_process = subprocess.Popen(["python", "-m", "http.server", "-d", f"{app.outdir}", "65323"])

try:
# Run the Cypress test command
completed_process = subprocess.run(
[
"npx",
"cypress",
"run",
"--browser",
"chrome",
"--config-file",
rf"{app.cypress_config_file}",
"--config",
rf"{app.cypress_config}",
],
capture_output=True,
)

# Check the return code and stdout
assert completed_process.returncode == 0
assert "All specs passed!" in completed_process.stdout.decode("utf-8")
# To stop the server, we can terminate the process
server_process.terminate()
server_process.wait(timeout=5) # Wait for up to 5 seconds for the process to exit
print("Server stopped successfully.")
except subprocess.TimeoutExpired:
server_process.kill()
print("Server forcibly terminated due to timeout.")
except (Exception, subprocess.CalledProcessError) as e:
# Stop server when an exception occurs
server_process.terminate()
server_process.wait(timeout=5) # Wait for up to 5 seconds for the process to exit
print("Server stopped due to error.")
raise e

0 comments on commit b844648

Please sign in to comment.