diff --git a/.circleci/config.yml b/.circleci/config.yml index ac6546a9a..42cc173f9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -81,7 +81,7 @@ jobs: gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE} - run: name: Deploy to gcloud - command: gcloud beta compute instance-groups managed rolling-action replace mrm-backend-instance-group --max-unavailable=1 --min-ready=280 --zone=europe-west1-b + command: gcloud beta compute instance-groups managed rolling-action replace mrm-backend-instance-group --region europe-west1 workflows: version: 2 diff --git a/.env.example b/.env.example index bf6c520a3..7c4c38f6b 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,7 @@ export SECRET_KEY="some-very-long-string-of-random-characters" export DEV_DATABASE_URL="" # Db for Development. export TEST_DATABASE_URL="" # Db for Testing export DATABASE_URL="" # Db for Production +export API_KEY="" # Google API app Api key +export OOATH2_CLIENT_ID="" # Google API app ooath2_client_id +export OOATH2_CLIENT_SECRET="" # Google API app ooath2_client_secret + diff --git a/alembic/versions/06c4fd428167_.py b/alembic/versions/06c4fd428167_.py new file mode 100644 index 000000000..ec031d186 --- /dev/null +++ b/alembic/versions/06c4fd428167_.py @@ -0,0 +1,40 @@ +"""empty message + +Revision ID: 06c4fd428167 +Revises: +Create Date: 2018-06-05 12:29:10.404447 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '06c4fd428167' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('devices') + op.add_column('rooms', sa.Column('calendar_id', sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('rooms', 'calendar_id') + op.create_table('devices', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('device_type', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('date_added', sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column('last_seen', sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column('location', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('resource_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], name='devices_resource_id_fkey'), + sa.PrimaryKeyConstraint('id', name='devices_pkey') + ) + # ### end Alembic commands ### diff --git a/alembic/versions/16706f39418e_add_calndarid_field_to_room_table.py b/alembic/versions/16706f39418e_add_calndarid_field_to_room_table.py new file mode 100644 index 000000000..3d35f2419 --- /dev/null +++ b/alembic/versions/16706f39418e_add_calndarid_field_to_room_table.py @@ -0,0 +1,40 @@ +"""Add calndarId field to room table + +Revision ID: 16706f39418e +Revises: c231314bba8d +Create Date: 2018-06-07 15:51:04.456452 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '16706f39418e' +down_revision = 'c231314bba8d' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('devices') + op.add_column('rooms', sa.Column('calendar_id', sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('rooms', 'calendar_id') + op.create_table('devices', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('device_type', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('date_added', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('last_seen', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('location', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('resource_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], name='devices_resource_id_fkey'), + sa.PrimaryKeyConstraint('id', name='devices_pkey') + ) + # ### end Alembic commands ### diff --git a/alembic/versions/21ca82d232ff_add_calendarid.py b/alembic/versions/21ca82d232ff_add_calendarid.py new file mode 100644 index 000000000..d7fc0cc50 --- /dev/null +++ b/alembic/versions/21ca82d232ff_add_calendarid.py @@ -0,0 +1,40 @@ +"""Add calendarId + +Revision ID: 21ca82d232ff +Revises: b3be355ffe21 +Create Date: 2018-06-13 13:08:35.409236 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '21ca82d232ff' +down_revision = 'b3be355ffe21' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('devices') + op.add_column('rooms', sa.Column('calendar_id', sa.String(), nullable=False)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('rooms', 'calendar_id') + op.create_table('devices', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('device_type', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('date_added', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('last_seen', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('location', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('resource_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], name='devices_resource_id_fkey'), + sa.PrimaryKeyConstraint('id', name='devices_pkey') + ) + # ### end Alembic commands ### diff --git a/alembic/versions/631fe5fea815_.py b/alembic/versions/631fe5fea815_.py new file mode 100644 index 000000000..4644012fe --- /dev/null +++ b/alembic/versions/631fe5fea815_.py @@ -0,0 +1,24 @@ +"""empty message + +Revision ID: 631fe5fea815 +Revises: b3be355ffe21, 06c4fd428167 +Create Date: 2018-06-07 14:07:21.597872 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '631fe5fea815' +down_revision = ('b3be355ffe21', '06c4fd428167') +branch_labels = None +depends_on = None + + +def upgrade(): + pass + + +def downgrade(): + pass diff --git a/alembic/versions/a3a250e2805a_.py b/alembic/versions/a3a250e2805a_.py new file mode 100644 index 000000000..db147602a --- /dev/null +++ b/alembic/versions/a3a250e2805a_.py @@ -0,0 +1,40 @@ +"""empty message + +Revision ID: a3a250e2805a +Revises: 16706f39418e +Create Date: 2018-06-08 15:32:37.991700 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'a3a250e2805a' +down_revision = '16706f39418e' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('devices') + op.add_column('rooms', sa.Column('calendar_id', sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('rooms', 'calendar_id') + op.create_table('devices', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('device_type', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('date_added', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('last_seen', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('location', sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column('resource_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], name='devices_resource_id_fkey'), + sa.PrimaryKeyConstraint('id', name='devices_pkey') + ) + # ### end Alembic commands ### diff --git a/api/room/models.py b/api/room/models.py index f65ed5363..a88d86289 100644 --- a/api/room/models.py +++ b/api/room/models.py @@ -13,6 +13,7 @@ class Room(Base, Utility): room_type = Column(String, nullable=False) capacity = Column(Integer, nullable=False) image_url = Column(String) + calendar_id = Column(String) floor_id = Column(Integer, ForeignKey('floors.id')) resources = relationship('Resource') @@ -24,4 +25,5 @@ def __init__(self, **kwargs): self.room_type = kwargs['room_type'] self.capacity = kwargs['capacity'] self.image_url = kwargs['image_url'] + self.calendar_id = kwargs['calendar_id'] self.floor_id = kwargs['floor_id'] diff --git a/api/room/schema.py b/api/room/schema.py index 950f2d25d..cf0b98079 100644 --- a/api/room/schema.py +++ b/api/room/schema.py @@ -5,6 +5,7 @@ from api.room.models import Room as RoomModel from utilities.utility import validate_empty_fields, update_entity_fields +from helpers.calendar.events import RoomSchedules class Room(SQLAlchemyObjectType): @@ -12,6 +13,10 @@ class Meta: model = RoomModel +class Calendar(graphene.ObjectType): + events = graphene.String() + + class CreateRoom(graphene.Mutation): class Arguments: name = graphene.String(required=True) @@ -19,6 +24,7 @@ class Arguments: capacity = graphene.Int(required=True) image_url = graphene.String() floor_id = graphene.Int(required=True) + calendar_id = graphene.String(required=True) room = graphene.Field(Room) def mutate(self, info, **kwargs): @@ -50,9 +56,19 @@ def mutate(self, info, room_id, **kwargs): class Query(graphene.ObjectType): all_rooms = graphene.List(Room) - get_room_by_id = graphene.List( - lambda: Room, + get_room_by_id = graphene.Field( + Room, room_id=graphene.Int() + ) + room_schedule = graphene.Field( + Calendar, + calendar_id=graphene.String(), + days=graphene.Int(), + ) + room_schedule = graphene.Field( + Calendar, + calendar_id=graphene.String(), + days=graphene.Int(), ) def resolve_all_rooms(self, info): @@ -64,8 +80,22 @@ def resolve_get_room_by_id(self, info, room_id): check_room = query.filter(RoomModel.id == room_id).first() if not check_room: raise GraphQLError("Room not found") - result = query.filter(RoomModel.id == room_id) - return result + return check_room + + def resolve_room_schedule(self, info, calendar_id, days): + query = Room.get_query(info) + check_calendar_id = query.filter( + RoomModel.calendar_id == calendar_id + ).first() + if not check_calendar_id: + raise GraphQLError("CalendarId given not assigned to any room on converge") # noqa: E501 + room_schedule = RoomSchedules.get_room_schedules( + self, + calendar_id, + days) + return Calendar( + events=room_schedule + ) class Mutation(graphene.ObjectType): diff --git a/app.py b/app.py index 9ce58e34c..6572676ce 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,5 @@ from flask import Flask +from flask_cors import CORS from flask_graphql import GraphQLView @@ -10,8 +11,11 @@ def create_app(config_name): app = Flask(__name__) + CORS(app) + app.config.from_object(config[config_name]) config[config_name].init_app(app) + app.add_url_rule( '/mrm', view_func=GraphQLView.as_view( diff --git a/credentials.json b/credentials.json new file mode 100644 index 000000000..53e4ad8e1 --- /dev/null +++ b/credentials.json @@ -0,0 +1 @@ +{"access_token": "ya29.Gl3ZBUb8ewx_F9NdEtMIDxH1XPsKOJA64dJwSqd7I6SuDbynB-UHCDw58VtcbjgYZPFrEKrk_99kvJolLRGGuXAUXBRLzAZ85ZaRUkPen-ehtjsycrPbMefC6wV7rMo", "client_id": "753057157806-4n8rnuuvn9iagp7md6s6448omdqi0iif.apps.googleusercontent.com", "client_secret": "DV154Q4dUxR-gaGtiBmonItI", "refresh_token": "1/scqhTOtBcRLGoC5a5brOZElp6a__tUbdbe17p8R7o9g", "token_expiry": "2018-06-13T12:59:51Z", "token_uri": "https://www.googleapis.com/oauth2/v4/token", "user_agent": null, "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "id_token": null, "id_token_jwt": null, "token_response": {"access_token": "ya29.Gl3ZBUb8ewx_F9NdEtMIDxH1XPsKOJA64dJwSqd7I6SuDbynB-UHCDw58VtcbjgYZPFrEKrk_99kvJolLRGGuXAUXBRLzAZ85ZaRUkPen-ehtjsycrPbMefC6wV7rMo", "token_type": "Bearer", "expires_in": 3600}, "scopes": ["https://www.googleapis.com/auth/calendar.readonly"], "token_info_uri": "https://www.googleapis.com/oauth2/v3/tokeninfo", "invalid": false, "_class": "OAuth2Credentials", "_module": "oauth2client.client"} diff --git a/fixtures/location/all_locations_fixtures.py b/fixtures/location/all_locations_fixtures.py index fd74ab472..ff709b9e2 100644 --- a/fixtures/location/all_locations_fixtures.py +++ b/fixtures/location/all_locations_fixtures.py @@ -63,18 +63,18 @@ }''' expected_response_pass_an_arg = { - "errors": [ - { - "message": "Unknown argument \"locationId\" on field \"allLocations\" of type \"Query\".", # noqa: E501 - "locations": [ - { - "line": 3, - "column": 22 - } - ] - } - ] - } + "errors": [ + { + "message": "Unknown argument \"locationId\" on field \"allLocations\" of type \"Query\".", # noqa: E501 + "locations": [ + { + "line": 3, + "column": 22 + } + ] + } + ] + } all_location_no_hierachy = '''{ allLocations{ diff --git a/fixtures/room/room_fixtures.py b/fixtures/room/room_fixtures.py index 7d7fcd2d8..a22f138ff 100644 --- a/fixtures/room/room_fixtures.py +++ b/fixtures/room/room_fixtures.py @@ -4,6 +4,7 @@ mutation { createRoom( name: "Mbarara", roomType: "Meeting", capacity: 4, floorId: 1, + calendarId:"andela.com_3836323338323230343935@resource.calendar.google.com", imageUrl: "https://www.officelovin.com/wp-content/uploads/2016/10/andela-office-main-1.jpg") { # noqa: E501 room { name @@ -86,16 +87,16 @@ room_query_by_id_response = { "data": { - "getRoomById": [{ - "capacity": 6, - "name": "Entebbe", - "roomType": "meeting" - } - ] + "getRoomById": { + "capacity": 6, + "name": "Entebbe", + "roomType": "meeting" + } } } -room_query_by_nonexistant_id = '''{ + +room_with_non_existant_id = '''{ getRoomById(roomId: 100) { id name @@ -103,16 +104,56 @@ } ''' -room_query_by_nonexistant_id_response = { - "errors": [{ - "message": "Room not found", - "locations": [{ - "line": 2, - "column": 5 - } - ] - }], - "data": { - "getRoomById": null - } -} +room_query_with_non_existant_id_response = { + "errors": [ + { + "message": "Room not found", + "locations": [ + { + "line": 2, + "column": 5 + } + ] + } + ], + "data": { + "getRoomById": null + } + } + +room_schedule_query = ''' + { + roomSchedule( + calendarId:"andela.com_3836323338323230343935@resource.calendar.google.com", + days:7){ + events + } + } + ''' + +room_schedule_query_with_non_existant_calendar_id = ''' + { + roomSchedule( + calendarId:"andela.com_38363230343935@resource.calendar.google.com", + days:7){ + events + } + } + ''' + +room_schedule_of_non_existant_calendar_id_response = { + "errors": [ + { + "message": "CalendarId given not assigned to any room on converge", # noqa: E501 + "locations": [ + { + "line": 1, + "column": 2 + } + ] + } + ], + "data": { + "roomSchedule": null + } + } diff --git a/helpers/auth/__init__.py b/helpers/auth/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/helpers/auth/authentication.py b/helpers/auth/authentication.py new file mode 100644 index 000000000..4fb4aa4e2 --- /dev/null +++ b/helpers/auth/authentication.py @@ -0,0 +1,37 @@ +import jwt +from flask import request, jsonify + + +class Authentication: + """ Authenicate token + :methods + decode_token + get_token + """ + + def get_token(self): + token = request.headers.get('token') # get token from headers + return token + + def decode_token(self): + """ + Decodes the auth token + :param + :return + integer|string + """ + + try: + auth_token = self.get_token() + payload = jwt.decode(auth_token, verify=False) + return payload['UserInfo'] # Return User Info + except jwt.ExpiredSignatureError: + return jsonify({ + 'message': 'Signature expired. Please log in again.'}), 401 + except jwt.InvalidTokenError: + return jsonify({ + 'message': 'Invalid token. Please Provide a valid token!' + }), 401 + + +Auth = Authentication() diff --git a/helpers/calendar/__init__.py b/helpers/calendar/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/helpers/calendar/credentials.py b/helpers/calendar/credentials.py new file mode 100644 index 000000000..35b652e25 --- /dev/null +++ b/helpers/calendar/credentials.py @@ -0,0 +1,36 @@ +import os + +from apiclient.discovery import build +from httplib2 import Http +from oauth2client import file, client, tools # noqa +from oauth2client.client import OAuth2WebServerFlow # noqa + + +class Credentials(): + """Define api credentials + :methods + set_api_credentials + """ + + def set_api_credentials(self): + """ + Setup the Calendar API + """ + SCOPES = 'https://www.googleapis.com/auth/calendar' + store = file.Storage('credentials.json') + credentials = store.get() + + if not credentials or credentials.invalid: + # Create a flow object. This object holds the client_id, + # client_secret, and + # SCOPES. It assists with OAuth 2.0 steps to get user + # authorization and credentials. + flow = OAuth2WebServerFlow( + os.getenv('OOATH2_CLIENT_ID'), + os.getenv('OOATH2_CLIENT_SECRET'), + SCOPES) + credentials = tools.run_flow(flow, store) + api_key = os.getenv('API_KEY') + service = build('calendar', 'v3', developerKey=api_key, + http=credentials.authorize(Http())) + return service diff --git a/helpers/calendar/events.py b/helpers/calendar/events.py new file mode 100644 index 000000000..f114fe2ca --- /dev/null +++ b/helpers/calendar/events.py @@ -0,0 +1,46 @@ +import datetime + +from .credentials import Credentials + + +class RoomSchedules(Credentials): + """Create and get room schedules + :methods + create_room_event_schedules + get_room_event_schedules + """ + + # define schedule methods here + def get_room_schedules(self, calendar_id, days): + """ Get room schedules. This method is responsible + for getting all the events on a rooms calendar. + :params + - calendar_id + - days(Time limit for the schedule you need) + """ + + service = Credentials.set_api_credentials(self) + # 'Z' indicates UTC time + now = datetime.datetime.utcnow().isoformat() + 'Z' + + new_time = ( + datetime.datetime.now() + datetime.timedelta(days=days) + ).isoformat() + 'Z' + + events_result = service.events().list( + calendarId=calendar_id, + timeMin=now, + timeMax=new_time, + singleEvents=True, + orderBy='startTime').execute() + + calendar_events = events_result.get('items', []) + output = [] + if not calendar_events: + return('No upcoming events found.') + for event in calendar_events: + event_details = {} + event_details["start"] = event['start'].get('dateTime', event['start'].get('date')) # noqa: E501 + event_details["summary"] = event.get("summary") + output.append(event_details) + return output diff --git a/requirements.txt b/requirements.txt index d0bdd494b..87dbba2a0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,9 @@ Flask-GraphQL==1.4.1 Flask-Script==2.0.6 Flask-Testing==0.7.1 funcsigs==1.0.2 +Flask-Cors==3.0.4 +google-api-python-client==1.6.7 +graphene-sqlalchemy==2.0.0 graphene==2.1 graphene-sqlalchemy==2.0.0 graphql-core==2.0 diff --git a/tests/base.py b/tests/base.py index 23107bbf4..24b532e61 100644 --- a/tests/base.py +++ b/tests/base.py @@ -40,6 +40,7 @@ def setUp(self): room_type='meeting', capacity=6, floor_id=floor.id, + calendar_id='andela.com_3836323338323230343935@resource.calendar.google.com', # noqa: E501 image_url="https://www.officelovin.com/wp-content/uploads/2016/10/andela-office-main-1.jpg") # noqa: E501 room.save() resource = Resource(name='Markers', diff --git a/tests/test_calendars/__init__.py b/tests/test_calendars/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_calendars/test_credentials.py b/tests/test_calendars/test_credentials.py new file mode 100644 index 000000000..c347bd948 --- /dev/null +++ b/tests/test_calendars/test_credentials.py @@ -0,0 +1,23 @@ +"""This module deals with testing Calendar Integration with focus on + googleapi credentials +""" +from helpers.calendar.credentials import Credentials +from tests.base import BaseTestCase + +import sys +import os +sys.path.append(os.getcwd()) + + +class TestCredentials(BaseTestCase): + """ This class tests for the google api credentials + func : + - test_response_credentails + """ + + def test_response_credentails(self): + """ This function tests for type of response + of the response to see if its a googleapi object + """ + response = Credentials.set_api_credentials(self) + self.assertEquals(str(type(response)), "") # noqa: E501 diff --git a/tests/test_calendars/test_events.py b/tests/test_calendars/test_events.py new file mode 100644 index 000000000..0e8265e63 --- /dev/null +++ b/tests/test_calendars/test_events.py @@ -0,0 +1,25 @@ +"""This module deals with testing Calendar Integration with focus on + googleapi credentials +""" +from helpers.calendar.events import RoomSchedules +from tests.base import BaseTestCase + +import sys +import os +sys.path.append(os.getcwd()) + + +class TestEvents(BaseTestCase): + """ This class tests for the google api credentials + func : + - test_response_events + """ + def test_response_event(self): + """ This function tests for type of response + of the response to see if its a googleapi object + RoomSchedule function + """ + calendarId = 'andela.com_3137313531373531393135@resource.calendar.google.com' # noqa: E501 + response = RoomSchedules.get_room_schedules(self, calendarId, 7) + assert type(response) is list + self.assertNotEquals(response, []) diff --git a/tests/test_rooms/test_query_rooms.py b/tests/test_rooms/test_query_rooms.py index 4758d2dbe..ce8682c51 100644 --- a/tests/test_rooms/test_query_rooms.py +++ b/tests/test_rooms/test_query_rooms.py @@ -5,8 +5,9 @@ query_rooms_response, room_query_by_id, room_query_by_id_response, - room_query_by_nonexistant_id, - room_query_by_nonexistant_id_response + room_with_non_existant_id, + room_query_with_non_existant_id_response + ) @@ -19,6 +20,6 @@ def test_query_room_with_id(self): query = self.client.execute(room_query_by_id) self.assertEquals(query, room_query_by_id_response) - def test_query_room_with_nonexistant_id(self): - query = self.client.execute(room_query_by_nonexistant_id) - self.assertEquals(query, room_query_by_nonexistant_id_response) + def test_query_room_with_non_existant_id(self): + query = self.client.execute(room_with_non_existant_id) + self.assertEquals(query, room_query_with_non_existant_id_response) diff --git a/tests/test_rooms/test_room_model.py b/tests/test_rooms/test_room_model.py index 47ee8b220..fc7d06e7f 100644 --- a/tests/test_rooms/test_room_model.py +++ b/tests/test_rooms/test_room_model.py @@ -42,6 +42,7 @@ def test_if_data_can_be_saved(self): object_count = Room.query.count() room = Room(name='Jinja', room_type='meeting', capacity=5, floor_id=1, + calendar_id='andela.com_3835468272423230343935@resource.calendar.google.com', # noqa: E501 image_url="https://www.officelovin.com/wp-content/uploads/2016/10/andela-office-main-1.jpg") # noqa: E501 room.save() diff --git a/tests/test_rooms/test_room_schedule.py b/tests/test_rooms/test_room_schedule.py new file mode 100644 index 000000000..a28c2e94e --- /dev/null +++ b/tests/test_rooms/test_room_schedule.py @@ -0,0 +1,39 @@ +"""This module containes test for the RoomSchedule Query +""" +from tests.base import BaseTestCase + +from fixtures.room.room_fixtures import ( + room_schedule_query, + room_schedule_query_with_non_existant_calendar_id, + room_schedule_of_non_existant_calendar_id_response + ) + + +class QueryRoomSchedule(BaseTestCase): + """This class deals with tests relating to querying room schedules + and the google api integration + funcs : + - test_room_schedule + - test_room_schedule_with_non_existant_calendar_id + """ + def test_room_schedule(self): + """ + This function tests the return types of the data received + from RoomSchedule query + - if it is a dictionary + - if data is obtained + """ + query = self.client.execute(room_schedule_query) + assert type(query) is dict + self.assertNotEquals(query, {}) + + def test_room_schedule_with_non_existant_calendar_id(self): + """This function tests whether an error is raised if the calendarId is + non existant. + """ + query = self.client.execute( + room_schedule_query_with_non_existant_calendar_id) + self.assertNotEquals( + query, + room_schedule_of_non_existant_calendar_id_response + )