
from unittest import TestCase
from MoinMoin._tests import TestConfig
from MoinMoin import auth, user, userform
from MoinMoin import oidauth
import unittest

# TEST: openid login with known user
# TEST: openid login with user not seen before
# TEST: openid login that fails at beginAuth 
# TEST: openid login that fails at completeAuth

class DummyLoginFormHandler(object):
    called = 0
    identityURL = None

    def authmethod(self, request, name=None, password=None, login=None,
                   logout=None, _consumer=None, **kw):
        self.called = self.called + 1
        self.identityURL = name

class TestUserForm(TestCase):
    def setUp(self):
        self.config = TestConfig(self.request,
                                 auth=[oidauth.openid, auth.moin_cookie],
                                 user_form_fields=
                                 oidauth.ConfigMixin.user_form_fields)
        # self.request.initTheme()

    def tearDown(self):
        del self.config

    def test_openIDField(self):
        self.request.form['login'] = ['on']
        self.request.user = user.User(self.request, "JimUnitTest")
        self.request.user.valid = True
        loginform = userform.UserSettings(self.request).asHTML()
        # Does there exist a field named 'openid_url'?
        # (as per http://openid.net/specs.bml#submitclaim )
        # This is a pretty weak test:
        self.failUnless('openid_url' in loginform, loginform)

    def test_openIDSet(self):
        self.request.request_method = 'POST'
        f = {'save': ['on'],
             'name': ['JoeUnitTest'],
             'openid_url': ['http://unittest7.myopenid.com/'],
             'email': ['joe.ut@localhost'],
             'password': ['secret'],
             'password2': ['secret'],
             }
        self.request.form.update(f)
        self.request.user = user.User(self.request, "JoeUnitTest")
        result = userform.UserSettingsHandler(self.request).handleData()
        self.failUnlessEqual(result, "User preferences saved!")
        self.failUnlessEqual(self.request.user.openid_url,
                             'http://unittest7.myopenid.com/')


class MockRequest(object):
    def __init__(self, orig):
        self.orig = orig
        self.cfg = orig.cfg
        self.calls = []
        self.request_uri = orig.request_uri
        self.query_string = orig.query_string

    def getBaseURL(self, *a):
        return self.orig.getBaseURL(*a)

    def getQualifiedURL(self, *a):
        return self.orig.getQualifiedURL(*a)

    def log(self, msg):
        self.calls.append(('log', [msg]))

    def http_redirect(self, url):
        self.calls.append(('http_redirect', [url]))

    def finish(self):
        self.calls.append(('finish', []))

class DummyBeginAuth(object):
    def __init__(self, result, username):
        from openid.consumer import consumer
        auth_req = lambda : None
        auth_req.token = "a_shiny_silver_token"
        self.result = {
            'good': (consumer.SUCCESS, auth_req),
            'cancelled': (consumer.SUCCESS, None),
            'failed': (consumer.FAILURE, None)}[result]

    def beginAuth(self, identityURL):
        return self.result

    def constructRedirect(self, foo, bar, baz):
        return "http://blah.blah.blah"

class TestLoginForm(TestCase):
    def setUp(self):
        self.config = TestConfig(self.request,
                                 auth=[auth.moin_cookie, oidauth.openid],
                                 openid_assoc_dir = './openid/',
                                 user_form_fields=
                                 oidauth.ConfigMixin.user_form_fields)
        self.request.initTheme()

    def tearDown(self):
        del self.config

    def test_redirect(self):
        identityURL = "http://openidenabled.com/test.bob"
        request = MockRequest(self.request)
        retval = oidauth.openid(request, name=identityURL, login=True,
                                _consumer=DummyBeginAuth('good', identityURL))
        self.failUnlessEqual(len(request.calls), 2,
                             "Request received wrong number of messages: %s"
                             % (request.calls,))
        self.failUnlessEqual(request.calls[0][0], 'http_redirect')
        self.failUnlessEqual(request.calls[-1][0], 'finish')


class DummyCompleteAuth(object):
    def __init__(self, result, username):
        from openid.consumer import consumer
        self.result = {
            'good': (consumer.SUCCESS, username),
            'cancelled': (consumer.SUCCESS, None),
            'failed': (consumer.FAILURE, None)}[result]

    def completeAuth(self, token, query):
        return self.result


class TestCheckIDAuth(TestCase):
    def test_idResponse(self):
        self.request.form['openid.mode'] = ['id_res']
        self.request.form['moidtoken'] = ['shiny']
        consumer = DummyCompleteAuth('good', "http://frankie.myopenid.com/")
        r = oidauth.openid(self.request, _consumer=consumer)
        self.failUnlessEqual(r[1], False)
        self.failUnless(isinstance(r[0], user.User),
                        "This is not user: %r" % (r[0],))

    def test_cancelled(self):
        self.request.form['openid.mode'] = ['cancel']
        self.request.form['moidtoken'] = ['penny']
        consumer = DummyCompleteAuth('cancelled',
                                       "http://lousy.myopenid.com/")
        r = oidauth.openid(self.request, _consumer=consumer)
        self.failUnlessEqual(r, (None, False))
        # FIXME: Test for user interface.  Should *tell* you that you tried
        # to log in and failed.

    def test_failure(self):
        self.request.form['openid.mode'] = ['id_res']
        self.request.form['moidtoken'] = ['copper']
        consumer = DummyCompleteAuth('failed', "http://bugsy.myopenid.com/")
        r = oidauth.openid(self.request, _consumer=consumer)
        self.failUnlessEqual(r, (None, False))
        # FIXME: Test for user interface.  Should *tell* you that you tried
        # to log in and failed.
