Skip to content

Commit

Permalink
Merge from 3.x: PR #6345
Browse files Browse the repository at this point in the history
Fixes #6317
  • Loading branch information
ccordoba12 committed Feb 7, 2018
2 parents 1c84364 + 0c209d7 commit 43034fd
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 44 deletions.
95 changes: 86 additions & 9 deletions spyder/app/tests/test_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from spyder.config.base import get_home_dir
from spyder.config.main import CONF
from spyder.widgets.dock import TabFilter
from spyder.plugins.help import ObjectComboBox
from spyder.plugins.runconfig import RunConfiguration
from spyder.py3compat import PY2, to_text_string
from spyder.utils.ipython.kernelspec import SpyderKernelSpec
Expand All @@ -48,9 +49,9 @@
from urllib2 import urlopen, URLError


#==============================================================================
# =============================================================================
# Constants
#==============================================================================
# =============================================================================
# Location of this file
LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__)))

Expand All @@ -60,7 +61,7 @@

# Need longer EVAL_TIMEOUT, because need to cythonize and C compile ".pyx" file
# before import and eval it
COMPILE_AND_EVAL_TIMEOUT=30000
COMPILE_AND_EVAL_TIMEOUT = 30000

# Time to wait for the IPython console to evaluate something (in
# miliseconds)
Expand All @@ -69,9 +70,9 @@
# Temporary directory
TEMP_DIRECTORY = tempfile.gettempdir()

#==============================================================================
# =============================================================================
# Utility functions
#==============================================================================
# =============================================================================
def open_file_in_editor(main_window, fname, directory=None):
"""Open a file using the Editor and its open file dialog"""
top_level_widgets = QApplication.topLevelWidgets()
Expand Down Expand Up @@ -119,9 +120,18 @@ def start_new_kernel(startup_timeout=60, kernel_name='python', spykernel=False,
return km, kc


#==============================================================================
def find_desired_tab_in_window(tab_name, window):
all_tabbars = window.findChildren(QTabBar)
for current_tabbar in all_tabbars:
for tab_index in range(current_tabbar.count()):
if current_tabbar.tabText(tab_index) == str(tab_name):
return current_tabbar, tab_index
return None, None


# =============================================================================
# Fixtures
#==============================================================================
# =============================================================================
@pytest.fixture
def main_window(request):
"""Main Window fixture"""
Expand Down Expand Up @@ -157,9 +167,9 @@ def close_window():
return window


#==============================================================================
# =============================================================================
# Tests
#==============================================================================
# =============================================================================
# IMPORTANT NOTE: Please leave this test to be the first one here to
# avoid possible timeouts in Appveyor
@pytest.mark.slow
Expand Down Expand Up @@ -1245,5 +1255,72 @@ def test_tabfilter_typeerror_full(main_window):
assert mockEvent_instance.pos.call_count == 1


@flaky(max_runs=3)
@pytest.mark.slow
def test_help_opens_when_show_tutorial_full(main_window, qtbot):
"""Test fix for #6317 : 'Show tutorial' opens the help plugin if closed."""
HELP_STR = "Help"

# Wait until the window is fully up
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None,
timeout=SHELL_TIMEOUT)

help_pane_menuitem = None
for action in main_window.plugins_menu.actions():
if action.text() == HELP_STR:
help_pane_menuitem = action
break

# Test opening tutorial with Help plguin closed
try:
main_window.help.plugin_closed()
except Exception:
pass
qtbot.wait(500)
help_tabbar, help_index = find_desired_tab_in_window(HELP_STR, main_window)

assert help_tabbar is None and help_index is None
assert not isinstance(main_window.focusWidget(), ObjectComboBox)
assert not help_pane_menuitem.isChecked()

main_window.help.show_tutorial()
qtbot.wait(500)

help_tabbar, help_index = find_desired_tab_in_window(HELP_STR, main_window)
assert None not in (help_tabbar, help_index)
assert help_index == help_tabbar.currentIndex()
assert isinstance(main_window.focusWidget(), ObjectComboBox)
assert help_pane_menuitem.isChecked()

# Test opening tutorial with help plugin open, but not selected
help_tabbar.setCurrentIndex((help_tabbar.currentIndex() + 1)
% help_tabbar.count())
qtbot.wait(500)
help_tabbar, help_index = find_desired_tab_in_window(HELP_STR, main_window)
assert None not in (help_tabbar, help_index)
assert help_index != help_tabbar.currentIndex()
assert not isinstance(main_window.focusWidget(), ObjectComboBox)
assert help_pane_menuitem.isChecked()

main_window.help.show_tutorial()
qtbot.wait(500)
help_tabbar, help_index = find_desired_tab_in_window(HELP_STR, main_window)
assert None not in (help_tabbar, help_index)
assert help_index == help_tabbar.currentIndex()
assert isinstance(main_window.focusWidget(), ObjectComboBox)
assert help_pane_menuitem.isChecked()

# Test opening tutorial with help plugin open and the active tab
qtbot.wait(500)
main_window.help.show_tutorial()
help_tabbar, help_index = find_desired_tab_in_window(HELP_STR, main_window)
qtbot.wait(500)
assert None not in (help_tabbar, help_index)
assert help_index == help_tabbar.currentIndex()
assert isinstance(main_window.focusWidget(), ObjectComboBox)
assert help_pane_menuitem.isChecked()


if __name__ == "__main__":
pytest.main()
4 changes: 4 additions & 0 deletions spyder/plugins/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,10 @@ def show_plain_text(self, text):

@Slot()
def show_tutorial(self):
"""Show the Spyder tutorial in the Help plugin, opening it if needed"""
if not self.dockwidget.isVisible():
self.dockwidget.show()
self.toggle_view_action.setChecked(True)
tutorial_path = get_module_source_path('spyder.utils.help')
tutorial = osp.join(tutorial_path, 'tutorial.rst')
text = open(tutorial).read()
Expand Down
124 changes: 89 additions & 35 deletions spyder/plugins/tests/test_help.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright © Spyder Project Contributors
#
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
# -----------------------------------------------------------------------------
"""Test scripts for `findinfiles` plugin."""

# 3rd party imports
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright © Spyder Project Contributors
#
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
# -----------------------------------------------------------------------------

"""
Tests for the Spyder `help` plugn, `help.py`.
"""

# Standard library imports
try:
from unittest.mock import Mock, MagicMock
except ImportError:
from mock import Mock, MagicMock # Python 2

# Third party imports
from qtpy.QtWebEngineWidgets import WEBENGINE
import pytest

# Local imports
from spyder.plugins.help import Help
from spyder.utils.introspection.utils import default_info_response


@pytest.fixture
def help_plugin(qtbot):
"""Help plugin fixture"""
help_plugin = Help()
import pytest
from flaky import flaky

# Local imports
from spyder.plugins.help import Help
from spyder.utils.introspection.utils import default_info_response


# =============================================================================
# Fixtures
# =============================================================================
@pytest.fixture
def help_plugin(qtbot):
"""Help plugin fixture"""
help_plugin = Help()
webview = help_plugin.rich_text.webview._webview

if WEBENGINE:
Expand All @@ -28,9 +41,12 @@ def help_plugin(qtbot):
help_plugin._webpage = webview.page().mainFrame()

qtbot.addWidget(help_plugin)
return help_plugin
return help_plugin


# =============================================================================
# Utility functions
# =============================================================================
def check_text(widget, text):
"""Check if some text is present in a widget."""
if WEBENGINE:
Expand All @@ -44,20 +60,25 @@ def callback(data):
return False
else:
return text in widget.toHtml()


def test_no_docs_message(help_plugin, qtbot):


# =============================================================================
# Tests
# =============================================================================
@flaky(max_runs=3)
def test_no_docs_message(help_plugin, qtbot):
"""
Test that no docs message is shown when instrospection plugins
can't get any info.
"""
help_plugin.render_sphinx_doc(default_info_response())
help_plugin.render_sphinx_doc(default_info_response())
qtbot.waitUntil(lambda: check_text(help_plugin._webpage,
"No documentation available"),
timeout=2000)


def test_no_further_docs_message(help_plugin, qtbot):
timeout=4000)


@flaky(max_runs=3)
def test_no_further_docs_message(help_plugin, qtbot):
"""
Test that no further docs message is shown when instrospection
plugins can get partial info.
Expand All @@ -66,11 +87,44 @@ def test_no_further_docs_message(help_plugin, qtbot):
info['name'] = 'foo'
info['argspec'] = '(x, y)'

help_plugin.render_sphinx_doc(info)
help_plugin.render_sphinx_doc(info)
qtbot.waitUntil(lambda: check_text(help_plugin._webpage,
"No further documentation available"),
timeout=2000)


if __name__ == "__main__":
timeout=3000)


def test_help_opens_when_show_tutorial_unit(help_plugin, qtbot,):
"""Test fix for #6317 : 'Show tutorial' opens the help plugin if closed."""
MockDockwidget = MagicMock()
MockDockwidget.return_value.isVisible.return_value = False
mockDockwidget_instance = MockDockwidget()

MockAction = Mock()
mock_toggle_view_action = MockAction()
mock_show_rich_text = Mock()

help_plugin.dockwidget = mockDockwidget_instance
help_plugin.toggle_view_action = mock_toggle_view_action
help_plugin.show_rich_text = mock_show_rich_text

help_plugin.show_tutorial()
qtbot.wait(100)

assert mockDockwidget_instance.show.call_count == 1
assert mock_toggle_view_action.setChecked.call_count == 1
mock_toggle_view_action.setChecked.assert_called_once_with(True)
assert mock_show_rich_text.call_count == 1

MockDockwidget.return_value.isVisible.return_value = True
mockDockwidget_instance = MockDockwidget()
help_plugin.dockwidget = mockDockwidget_instance

help_plugin.show_tutorial()
qtbot.wait(100)
assert mockDockwidget_instance.show.call_count == 1
assert mock_toggle_view_action.setChecked.call_count == 1
assert mock_show_rich_text.call_count == 2


if __name__ == "__main__":
pytest.main()

0 comments on commit 43034fd

Please sign in to comment.