import pytest
import flask
import flask.testing
from client.flask.router import Router
from usecases import exceptions
from .mocks import MockService, BadService

app = Router(MockService()).app

@pytest.fixture
def client():
  app.config['TESTING'] = True
  with app.test_client() as client:
    return client

def test_needs_method_post(client: flask.testing.FlaskClient):
  rv: flask.Response = client.get('/login')
  assert rv.status_code == 405
  rv: flask.Response = client.patch('/login')
  assert rv.status_code == 405
  rv: flask.Response = client.put('/login')
  assert rv.status_code == 405
  rv: flask.Response = client.delete('/login')
  assert rv.status_code == 405

def test_needs_username(client: flask.testing.FlaskClient):
  rv: flask.Response = client.post('/login', json={})
  assert b'Username is required' in rv.data
  rv: flask.Response = client.post('/login', json={ 
    'password': '1234'
  })
  assert b'Username is required' in rv.data
  assert rv.status_code == 400

def test_needs_password(client: flask.testing.FlaskClient):
  rv: flask.Response = client.post('/login', json={
    'username': 'johndoe',
  })
  assert b'Password is required' in rv.data
  assert rv.status_code == 400

def test_responds_with_exception_message(client: flask.testing.FlaskClient):
  badApp = Router(BadService(Exception('Foo'))).app
  with badApp.test_client() as c:
    rv: flask.Response = c.post('/login', json={
      'username': 'johndoe',
      'password': 'supersecret'
    })
    assert b'Foo' in rv.data
    assert rv.status_code == 400

  badApp = Router(BadService(exceptions.Internal())).app
  with badApp.test_client() as c:
    rv: flask.Response = c.post('/login', json={
      'username': 'johndoe',
      'password': 'supersecret'
    })
    assert b'Internal error' in rv.data
    assert rv.status_code == 500

def test_success(client: flask.testing.FlaskClient):
  rv: flask.Response = client.post('/login', json={
    'username': 'johndoe',
    'password': 'supersecret'
  })
  json_data = rv.get_json()

  assert json_data['access_token'] == "johndoesupersecretfoo"
  assert json_data['refresh_token'] == "johndoesupersecretbar"
