Files
tuir/tests/conftest.py
Michael Lazar a7b789bfd9 Squashed commit of the following:
Updated the supported python versions list.
    Fixed regression in displaying xposts. #173.
    Fixing a few style things.
    Added a more robust test for the tornado handler.
    Trying without pytest-cov
    Updated travis for coverage.
    Remove python 3.2 support because no unicode literals, following what praw supports.
    "Side effect is not iterable."
    Added requirements for travis.
    Renamed travis file correctly.
    Adding test configurations, got tox working.
    Adding vcr cassettes to the repo.
    Renamed requirements files.
    Split up tests and cleaned up test names.
    Tests done, still one failure.
    Treat cassettes as binary to prevent bad merging.
    Fixed a few broken tests.
    Added a timeout to notifications.
    Prepping subreddit page.
    Finished submission page tests.
    Working on submission tests.
    Fixed vcr matching on urls with params, started submission tests.
    Log cleanup.
    Still trying to fix a broken test.
    -Fixed a few pytest bugs and tweaked logging.
    Still working on subscription tests.
    Finished page tests, on to subscription page.
    Finished content tests and starting page tests.
    Added the test refresh-token file to gitignore.
    Moved functional test file out of the repository.
    Continuing work on subreddit content tests.
    Tests now match module names, cassettes are split into individual tests for faster loading.
    Linter fixes.
    Cleanup.
    Added support for nested loaders.
    Added pytest options, starting subreddit content tests.
    Back on track with loader, continuing content tests.
    Finishing submission content tests and discovered snag with loader exception handling.
    VCR up and running, continuing to implement content tests.
    Playing around with vcr.py
    Moved helper functions into terminal and new objects.py
    Fixed a few broken tests.
    Working on navigator tests.
    Reorganizing some things.
    Mocked webbrowser._tryorder for terminal test.
    Completed oauth tests.
    Progress on the oauth tests.
    Working on adding fake tornado request.
    Starting on OAuth tool tests.
    Finished curses helpers tests.
    Still working on curses helpers tests.
    Almost finished with tests on curses helpers.
    Adding tests and working on mocking stdscr.
    Starting to add tests for curses functions.
    Merge branch 'future_work' of https://github.com/michael-lazar/rtv into future_work
    Refactoring controller, still in progress.
    Renamed auth handler.
    Rename CursesHelper to CursesBase.
    Added temporary file with a possible template for func testing.
    Mixup between basename and dirname.
    Merge branch 'future_work' of https://github.com/michael-lazar/rtv into future_work
    py3 compatability for mock.
    Beginning to refactor the curses session.
    Started adding tests, improved unicode handling in the config.
    Cleanup, fixed a few typos.
    Major refactor, almost done!.
    Started a config class.
    Merge branch 'master' into future_work
    The editor now handles unicode characters in all situations.
    Fixed a few typos from previous commits.
    __main__.py formatting.
    Cleaned up history logic and moved to the config file.
2015-12-02 22:37:50 -08:00

222 lines
6.8 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import curses
import logging
from functools import partial
import praw
import pytest
from vcr import VCR
from six.moves.urllib.parse import urlparse, parse_qs
from rtv.page import Page
from rtv.oauth import OAuthHelper
from rtv.config import Config
from rtv.terminal import Terminal
from rtv.subreddit import SubredditPage
from rtv.submission import SubmissionPage
from rtv.subscription import SubscriptionPage
try:
from unittest import mock
except ImportError:
import mock
# Turn on autospec by default for convenience
patch = partial(mock.patch, autospec=True)
# Turn on logging, but disable vcr from spamming
logging.basicConfig(level=logging.DEBUG)
for name in ['vcr.matchers', 'vcr.stubs']:
logging.getLogger(name).disabled = True
def pytest_addoption(parser):
parser.addoption('--record-mode', dest='record_mode', default='none')
parser.addoption('--refresh-token', dest='refresh_token',
default='tests/refresh-token')
class MockStdscr(mock.MagicMock):
"""
Extend mock to mimic curses.stdscr by keeping track of the terminal
coordinates and allowing for the creation of subwindows with the same
properties as stdscr.
"""
def getyx(self):
return self.y, self.x
def getmaxyx(self):
return self.nlines, self.ncols
def derwin(self, *args):
"""
derwin()
derwin(begin_y, begin_x)
derwin(nlines, ncols, begin_y, begin_x)
"""
if 'subwin' not in dir(self):
self.attach_mock(MockStdscr(), 'subwin')
if len(args) == 0:
nlines = self.nlines
ncols = self.ncols
elif len(args) == 2:
nlines = self.nlines - args[0]
ncols = self.ncols - args[1]
else:
nlines = min(self.nlines - args[2], args[0])
ncols = min(self.ncols - args[3], args[1])
self.subwin.nlines = nlines
self.subwin.ncols = ncols
self.subwin.x = 0
self.subwin.y = 0
return self.subwin
@pytest.fixture(scope='session')
def vcr(request):
def auth_matcher(r1, r2):
return (r1.headers.get('authorization') ==
r2.headers.get('authorization'))
def uri_with_query_matcher(r1, r2):
"URI matcher that allows query params to appear in any order"
p1, p2 = urlparse(r1.uri), urlparse(r2.uri)
return (p1[:3] == p2[:3] and
parse_qs(p1.query, True) == parse_qs(p2.query, True))
# Use `none` to use the recorded requests, and `once` to delete existing
# cassettes and re-record.
record_mode = request.config.option.record_mode
assert record_mode in ('once', 'none')
cassette_dir = os.path.join(os.path.dirname(__file__), 'cassettes')
if not os.path.exists(cassette_dir):
os.makedirs(cassette_dir)
# https://github.com/kevin1024/vcrpy/pull/196
vcr = VCR(
record_mode=request.config.option.record_mode,
filter_headers=[('Authorization', '**********')],
filter_post_data_parameters=[('refresh_token', '**********')],
match_on=['method', 'uri_with_query', 'auth', 'body'],
cassette_library_dir=cassette_dir)
vcr.register_matcher('auth', auth_matcher)
vcr.register_matcher('uri_with_query', uri_with_query_matcher)
return vcr
@pytest.fixture()
def refresh_token(request):
if request.config.option.record_mode == 'none':
return 'mock_refresh_token'
else:
return open(request.config.option.refresh_token).read()
@pytest.yield_fixture()
def config():
with patch('rtv.config.Config.save_refresh_token'), \
patch('rtv.config.Config.save_history'):
yield Config()
@pytest.yield_fixture()
def stdscr():
with patch('curses.initscr'), \
patch('curses.echo'), \
patch('curses.flash'), \
patch('curses.endwin'), \
patch('curses.newwin'), \
patch('curses.noecho'), \
patch('curses.cbreak'), \
patch('curses.doupdate'), \
patch('curses.nocbreak'), \
patch('curses.curs_set'), \
patch('curses.init_pair'), \
patch('curses.color_pair'), \
patch('curses.start_color'), \
patch('curses.use_default_colors'):
out = MockStdscr(nlines=40, ncols=80, x=0, y=0)
curses.initscr.return_value = out
curses.newwin.side_effect = lambda *args: out.derwin(*args)
curses.color_pair.return_value = 23
curses.ACS_VLINE = 0
yield out
@pytest.yield_fixture()
def reddit(vcr, request):
cassette_name = '%s.yaml' % request.node.name
# Clear the cassette before running the test
if request.config.option.record_mode == 'once':
filename = os.path.join(vcr.cassette_library_dir, cassette_name)
if os.path.exists(filename):
os.remove(filename)
with vcr.use_cassette(cassette_name):
with patch('praw.Reddit.get_access_information'):
reddit = praw.Reddit(user_agent='rtv test suite',
decode_html_entities=False,
disable_update_check=True)
if request.config.option.record_mode == 'none':
# Turn off praw rate limiting when using cassettes
reddit.config.api_request_delay = 0
yield reddit
@pytest.fixture()
def terminal(stdscr, config):
term = Terminal(stdscr, ascii=config['ascii'])
# Disable the python 3.4 addch patch so that the mock stdscr calls are
# always made the same way
term.addch = lambda window, *args: window.addch(*args)
return term
@pytest.fixture()
def oauth(reddit, terminal, config):
return OAuthHelper(reddit, terminal, config)
@pytest.fixture()
def submission_page(reddit, terminal, config, oauth):
submission = 'https://www.reddit.com/r/Python/comments/2xmo63'
with terminal.loader():
page = SubmissionPage(reddit, terminal, config, oauth, url=submission)
assert terminal.loader.exception is None
page.draw()
return page
@pytest.fixture()
def subreddit_page(reddit, terminal, config, oauth):
subreddit = '/r/python'
with terminal.loader():
page = SubredditPage(reddit, terminal, config, oauth, subreddit)
assert not terminal.loader.exception
page.draw()
return page
@pytest.fixture()
def subscription_page(reddit, terminal, config, oauth, refresh_token):
# Must be logged in to view your subscriptions
config.refresh_token = refresh_token
oauth.authorize()
with terminal.loader():
page = SubscriptionPage(reddit, terminal, config, oauth)
assert terminal.loader.exception is None
page.draw()
return page