[tox]
minversion = 3.18.0
envlist = pep8,py39,releasenotes,npm,py3-dj32
skipsdist = True
# Automatic envs (pyXX) will only use the python version appropriate to that
# env and ignore basepython inherited from [testenv] if we set
# ignore_basepython_conflict.
ignore_basepython_conflict = True

[testenv]
basepython = python3
usedevelop = True
setenv =
  VIRTUAL_ENV = {envdir}
  PYTHONDONTWRITEBYTECODE = 1
  # TODO(amotoki): There are three variants of PYTHONWARNINGS. They should be merged.
  PYTHONWARNINGS = once,ignore::PendingDeprecationWarning
  py{3,39}:PYTHONWARNINGS = once,ignore::PendingDeprecationWarning,ignore::ImportWarning:backports
  # DeprecationWarning is disabled in dj32 tox env as Django 3.2
  # deprecated Django 2.2 features. This workaround is just to reduce
  # the number of warnings due to this change.
  # It should be dropped when we drop Django 2.2 support.
  dj32: PYTHONWARNINGS = once,ignore::PendingDeprecationWarning,ignore::DeprecationWarning

allowlist_externals =
  bash
  find
deps =
  -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
  -r{toxinidir}/test-requirements.txt
  -r{toxinidir}/requirements.txt
  # Unit test for a local hacking rule requires hacking.
  hacking>=3.0.1,<3.1.0 # Apache-2.0
commands =
  dj32: pip install django>=3.2,<3.3
  find . -type f -name "*.pyc" -delete
  bash {toxinidir}/tools/unit_tests.sh {toxinidir} {posargs}

[testenv:venv]
envdir = {toxworkdir}/venv
commands = {posargs}

[testenv:pep8]
envdir = {toxworkdir}/linters
deps =
  {[testenv]deps}
  flake8-import-order==0.12 # LGPLv3
  pylint==2.6.0 # GPLv2
  bandit!=1.6.0,>=1.4.0 # Apache-2.0
setenv =
  DJANGO_SETTINGS_MODULE=openstack_dashboard.test.settings
commands =
  flake8 {posargs}
  {envpython} {toxinidir}/manage.py extract_messages --verbosity 0 --check-only
  bash {toxinidir}/tools/find_executables.sh
  pylint -j 4 --verbose --rcfile=.pylintrc -f colorized openstack_dashboard openstack_auth horizon

[testenv:cover]
envdir = {toxworkdir}/venv
allowlist_externals =
  bash
commands =
  coverage erase
  bash {toxinidir}/tools/unit_tests.sh --coverage {toxinidir}
  coverage xml
  coverage html -d coverage
  coverage report --show-missing --skip-covered

[testenv:selenium]
envdir = {toxworkdir}/venv
setenv =
  {[testenv]setenv}
  WITH_SELENIUM=1
commands =
  find . -type f -name "*.pyc" -delete
  bash {toxinidir}/tools/selenium_tests.sh {toxinidir} {posargs}

[testenv:selenium-headless]
envdir = {toxworkdir}/venv
setenv =
  {[testenv]setenv}
  SELENIUM_HEADLESS=1
  WITH_SELENIUM=1
commands =
  find . -type f -name "*.pyc" -delete
  bash {toxinidir}/tools/selenium_tests.sh {toxinidir} {posargs}

[testenv:selenium-phantomjs]
envdir = {toxworkdir}/venv
setenv =
  {[testenv]setenv}
  SELENIUM_PHANTOMJS=1
  WITH_SELENIUM=1
commands =
  find . -type f -name "*.pyc" -delete
  bash {toxinidir}/tools/selenium_tests.sh {toxinidir} {posargs}

[testenv:integration]
envdir = {toxworkdir}/venv
# Run integration tests only
passenv =
  DISPLAY
  FFMPEG_INSTALLED
setenv =
  INTEGRATION_TESTS=1
  SELENIUM_HEADLESS=False
commands =
  oslo-config-generator --namespace openstack_dashboard_integration_tests
  pytest --ds=openstack_dashboard.test.settings -v --junitxml="{toxinidir}/test_reports/integration_test_results.xml" --html="{toxinidir}/test_reports/integration_test_results.html" --self-contained-html {posargs:{toxinidir}/openstack_dashboard/test/integration_tests}

[testenv:npm]
passenv =
  HOME
  DISPLAY
commands =
  nodeenv -p
  npm install
  npm run {posargs:test}

[testenv:tests_system_packages]
# Provide an environment for system packagers that dont want anything from pip
# Any extra deps needed for this env can be passed by setting TOX_EXTRA_DEPS
sitepackages = True
passenv = TOX_EXTRA_DEPS http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
# Sets deps to an empty list so nothing is installed from pip
deps =
commands =
  pip install -U {env:TOX_EXTRA_DEPS:}
  {[testenv]commands}

[testenv:docs]
# We need to install horizon dependecies to build module references
deps =
  -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
  -r{toxinidir}/requirements.txt
  -r{toxinidir}/doc/requirements.txt
commands =
  sphinx-build -j auto -W -b html doc/source doc/build/html
  doc8 doc/source

[testenv:pdf-docs]
envdir = {toxworkdir}/docs
deps = {[testenv:docs]deps}
allowlist_externals =
  make
commands =
  sphinx-build -j auto -W -b latex doc/source doc/build/pdf
  make -C doc/build/pdf

[testenv:releasenotes]
envdir = {toxworkdir}/docs
deps = {[testenv:docs]deps}
commands =
  sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
  doc8 doc/source

[testenv:manage]
envdir = {toxworkdir}/venv
commands = {envpython} {toxinidir}/manage.py {posargs}

[testenv:runserver]
envdir = {toxworkdir}/venv
commands =
    {envpython} {toxinidir}/manage.py collectstatic -v 0 -c --noinput
    {envpython} {toxinidir}/manage.py runserver -v 0 {posargs}

[testenv:translations]
envdir = {toxworkdir}/venv
commands =
    {envpython} {toxinidir}/manage.py extract_messages -v 0 --traceback
    {envpython} {toxinidir}/manage.py compilemessages -v 0 --traceback

[testenv:bandit]
envdir = {toxworkdir}/linters
deps = {[testenv:pep8]deps}
commands = bandit -r horizon openstack_auth openstack_dashboard -n5 -x tests -ll

[testenv:bandit-baseline]
envdir = {toxworkdir}/linters
deps = {[testenv:pep8]deps}
commands = bandit-baseline -r horizon openstack_auth openstack_dashboard -n5 -x tests -ii -ll

[flake8]
filename = *.py,django.wsgi
exclude = .git,.tox,dist,*lib/python*,*egg,build,panel_template,dash_template,local_settings.py,*/local/*,*/test/test_plugins/*,.ropeproject,node_modules,openstack_dashboard/enabled/*,horizon_wsgi.py
# W504 line break after binary operator
# (W503 and W504 are incompatible and we need to choose one of them.
#  Existing codes follows W503, so we disable W504.)
# F405 TEMPLATES may be undefined, or defined from star imports
# (because it is not easy to avoid this in openstack_dashboard.test.settings)
ignore = W504,F405
# Enable the following hacking rules which are disabled by default
# H106 Do not put vim configuration in source files.
# H203 Use assertIs(Not)None to check for None.
# H204 Use assert(Not)Equal to check for equality.
# H205 Use assert(Greater|Less)(Equal) for comparison.
# H904 Delay string interpolations at logging calls.
enable-extensions=H106,H203,H204,H205,H904
max-complexity = 20
max_line_length = 80

# flake8-import-order configurations
import-order-style = pep8
application-import-names = horizon,openstack_dashboard

[flake8:local-plugins]
extension =
  M322 = horizon.hacking.checks:no_mutable_default_args

[doc8]
# File extensions to check
extensions = .rst, .yaml
# Maximal line length should be 80 but we have some overlong lines.
# Let's not get far more in.
max-line-length = 80
# Disable some doc8 checks:
# D000: Check RST validity
# - cannot handle "none" for code-block directive
ignore = D000


[pytest]
markers =
  selenium: Mark for selenium tests
  integration: Mark for integration tests
  plugin_test: Mark for plugin tests
python_files =
  test_*.py
  *_test.py
  tests.py
