import unittest
import main
import requests
import json
import os

from starlette.testclient import TestClient
from google.cloud import firestore
from google.auth import credentials
from backend import service, settings


def create_bit_data():
    return {
        'title': "My first bit title", 
        'content': "My first bit content",
        'tags': ['java', 'python'],
        'ispublic': False
    }

def request_to_create_a_bit(app_client, bit_data=create_bit_data()):
    response = app_client.post('/api/bits', data=json.dumps(bit_data))
    return response

def clearDatabase():
    emulator_host = os.environ['FIRESTORE_EMULATOR_HOST']
    requests.delete(url=f"http://{emulator_host}/emulator/v1/projects/test-{settings.FIRESTORE_PROJECT_ID}/databases/(default)/documents") 

class TestBitRoutes(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # Note project ids are allow a-z0-9 and hyphen
        project = f"test-{settings.FIRESTORE_PROJECT_ID}"
        db = firestore.Client(project=project, credentials=credentials.AnonymousCredentials())
        service.bit_service.init('bits', db=db)
        clearDatabase()

    def setUp(self):
        self.app_client = TestClient(main.app)

    def tearDown(self) -> None:
        clearDatabase()

    def test_all_bits_should_return_empty_list(self):
        response = self.app_client.get('/api/bits')        
        assert response.status_code == 200
        assert response.content == b'[]'

    def test_all_bits_should_return_list_with_bits(self):
        request_to_create_a_bit(self.app_client)
        request_to_create_a_bit(self.app_client)
        response = self.app_client.get('/api/bits')
        assert response.status_code == 200
        assert len(json.loads(response.content)) == 2

    def test_create_bit(self):
        bit_data = create_bit_data()
        response = request_to_create_a_bit(self.app_client, bit_data)
        bit = json.loads(response.content)
        assert bit['id'] is not None
        assert bit['title'] == bit_data['title']
        assert bit['content'] == bit_data['content']

    def test_update_bit(self):
        bit_data = create_bit_data()
        response = request_to_create_a_bit(self.app_client, bit_data)
        bit = json.loads(response.content)

        # perform update
        new_title = "My new title"
        self.app_client.put(f"/api/bits/{bit['id']}", data=json.dumps({'title': new_title}))
        
        # grab the bit from firestore
        response = self.app_client.get(f"/api/bits/{bit['id']}")
        bit = json.loads(response.content)
        assert bit['title'] == new_title

    def test_delete_bit(self):
        request_to_create_a_bit(self.app_client)
        response = request_to_create_a_bit(self.app_client)
        bit2 = json.loads(response.content)

        response = self.app_client.get('/api/bits')
        assert len(json.loads(response.content)) == 2
        # delete
        self.app_client.delete(f"/api/bits/{bit2['id']}")
        # confirm
        response = self.app_client.get('/api/bits')
        assert len(json.loads(response.content)) == 1


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

import unittest
import main
import requests
import json
import os

from starlette.testclient import TestClient
from google.cloud import firestore
from google.auth import credentials
from backend import service, settings


def create_bit_data():
    return {
        'title': "My first bit title", 
        'content': "My first bit content",
        'tags': ['java', 'python'],
        'ispublic': False
    }

def request_to_create_a_bit(app_client, bit_data=create_bit_data()):
    response = app_client.post('/api/bits', data=json.dumps(bit_data))
    return response

def clearDatabase():
    emulator_host = os.environ['FIRESTORE_EMULATOR_HOST']
    requests.delete(url=f"http://{emulator_host}/emulator/v1/projects/test-{settings.FIRESTORE_PROJECT_ID}/databases/(default)/documents") 

class TestBitRoutes(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # Note project ids are allow a-z0-9 and hyphen
        project = f"test-{settings.FIRESTORE_PROJECT_ID}"
        db = firestore.Client(project=project, credentials=credentials.AnonymousCredentials())
        service.bit_service.init('bits', db=db)
        clearDatabase()

    def setUp(self):
        self.app_client = TestClient(main.app)

    def tearDown(self) -> None:
        clearDatabase()

    def test_all_bits_should_return_empty_list(self):
        response = self.app_client.get('/api/bits')        
        assert response.status_code == 200
        assert response.content == b'[]'

    def test_all_bits_should_return_list_with_bits(self):
        request_to_create_a_bit(self.app_client)
        request_to_create_a_bit(self.app_client)
        response = self.app_client.get('/api/bits')
        assert response.status_code == 200
        assert len(json.loads(response.content)) == 2

    def test_create_bit(self):
        bit_data = create_bit_data()
        response = request_to_create_a_bit(self.app_client, bit_data)
        bit = json.loads(response.content)
        assert bit['id'] is not None
        assert bit['title'] == bit_data['title']
        assert bit['content'] == bit_data['content']

    def test_update_bit(self):
        bit_data = create_bit_data()
        response = request_to_create_a_bit(self.app_client, bit_data)
        bit = json.loads(response.content)

        # perform update
        new_title = "My new title"
        self.app_client.put(f"/api/bits/{bit['id']}", data=json.dumps({'title': new_title}))
        
        # grab the bit from firestore
        response = self.app_client.get(f"/api/bits/{bit['id']}")
        bit = json.loads(response.content)
        assert bit['title'] == new_title

    def test_delete_bit(self):
        request_to_create_a_bit(self.app_client)
        response = request_to_create_a_bit(self.app_client)
        bit2 = json.loads(response.content)

        response = self.app_client.get('/api/bits')
        assert len(json.loads(response.content)) == 2
        # delete
        self.app_client.delete(f"/api/bits/{bit2['id']}")
        # confirm
        response = self.app_client.get('/api/bits')
        assert len(json.loads(response.content)) == 1


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

# Note project ids are allow a-z0-9 and hyphen # perform update # grab the bit from firestore # delete # confirm