#!/usr/bin/python3

from app import make_app
import util

import unittest
import tornado.testing
import json

util.platform_setup()


class TestBaseAPI(tornado.testing.AsyncHTTPTestCase):
    """Example test case"""
    def get_app(self):
        return make_app()

    def test_health_endpoint(self):
        response = self.fetch('/v0/health',
                              method='GET')
        self.assertEqual(200, response.code, "GET /health must be available")

        health = json.loads(response.body.decode())

        self.assertIn('api-version', health, msg="api-version is not provided by health endpoint")
        self.assertEqual("v0", health['api-version'], msg="API version should be v0")
        self.assertIn('git-version', health, msg="git-version is not provided by health endpoint")
        self.assertIn('timestamp', health, msg="timestamp is not provided by health endpoint")
        self.assertIn('uptime', health, msg="uptime is not provided by health endpoint")

    def test_oas3(self):
        response = self.fetch('/v0/oas3',
                              method='GET')
        self.assertEqual(200, response.code, "GET /oas3 must be available")

        # check contents against local OAS3.yml
        with open('OAS3.yml') as oas3f:
            self.assertEqual(response.body.decode(), oas3f.read(), "OAS3 content differs from spec file!")


class TestValidation(tornado.testing.AsyncHTTPTestCase):
    """Validation test cases"""
    def get_app(self):
        return make_app()

    def test_null_validation(self):
        entity = {}

        response = self.fetch('/v0/validate',
                              method='POST',
                              body=json.dumps(entity))

        self.assertEqual(200, response.code, "Validation must always return 200")

        validation_result = json.loads(response.body.decode())

        self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
        self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")

    def test_valid_entity(self):
        with open('test_cases/valid/valid.json', 'r') as f:
            entity_file = json.load(f)

        response = self.fetch('/v0/validate',
                              method='POST',
                              body=json.dumps(entity_file))

        self.assertEqual(200, response.code, "Validation must always return 200")

        validation_result = json.loads(response.body.decode())

        self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
        self.assertTrue(validation_result['valid'], "Validation result is expected to be valid==true")

    def test_invalid_iban(self):
        with open('test_cases/invalid/invalid_iban.json', 'r') as f:
            entity_file = json.load(f)

        response = self.fetch('/v0/validate',
                              method='POST',
                              body=json.dumps(entity_file))

        self.assertEqual(200, response.code, "Validation must always return 200")

        validation_result = json.loads(response.body.decode())

        self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
        self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")

    def test_missing_id(self):
        with open('test_cases/invalid/missing_id.json', 'r') as f:
            entity_file = json.load(f)

        response = self.fetch('/v0/validate',
                              method='POST',
                              body=json.dumps(entity_file))

        self.assertEqual(200, response.code, "Validation must always return 200")

        validation_result = json.loads(response.body.decode())

        self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
        self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
        self.assertIn('id', validation_result['errors'])

    def test_invalid_id(self):
        with open('test_cases/invalid/invalid_id.json', 'r') as f:
            entity_file = json.load(f)

        response = self.fetch('/v0/validate',
                              method='POST',
                              body=json.dumps(entity_file))

        self.assertEqual(200, response.code,
                         "Validation must always return 200")

        validation_result = json.loads(response.body.decode())

        self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
        self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
        self.assertIn('id', validation_result['errors'])


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