def post(self) -> (str, int): """ Save or Update a Widget Parameters can be passed using a POST request. POST request JSON body parameters: :param data: Widget JSON data :param widgetID: Widget Id :param x: x coordinate of the widget layout :param y: y coordinate of the widget layout :param h: height of the widget layout :param w: width of the widget layout :param static: layout static property :returns : A response message and an appropriate HTTP status code """ args = self.reqparse_post.parse_args() current_user = Users.find_by_email(get_jwt_identity()) curr_widget = None if "widget_id" in args: curr_widget = WidgetModel.get_widget_by_id_and_user_id( args["widget_id"], current_user.id) if curr_widget: curr_widget.data = args["data"] else: abort(HTTPStatus.NOT_FOUND, error="Widget with Id {} not found".format( args["widget_id"])) else: # Create a layout for the new widget layout = Layouts(1, 0, 0, args['height'], args['width'], False) curr_widget = WidgetModel(current_user.id, layout, args["data"]) try: db.session.add(curr_widget) # flush session to get new widgetID to assign to layout db.session.flush() self.update_layout(curr_widget, args) db.session.commit() except exc.SQLAlchemyError as e: logger.error(e.with_traceback(e.__traceback__)) abort(HTTPStatus.BAD_REQUEST.value, error="exc.SQLAlchemyError: create_widget") response = self.get_reponse_template(curr_widget, updated="widget_id" in args) return response, HTTPStatus.OK
def post(self) -> ([WidgetModel], int): """ Get one or more widgets from the database with a userID Parameters can be passed using a POST request that contains a JSON with the following fields: :param userID: Unique user identification number :param limit: the max count of widgets to be returned :type userID: int :type limit: int :returns [widget]: A list of widgets with a maximum length of limit and a status code 200 """ args = self.reqparser_get.parse_args() # Fetch the widget instances related to the userID passed widgets = WidgetModel.query.filter_by(user_id=args["userID"]).limit( args["limit"]).all() # Were widget instances returned if not widgets: # No widgets found for userID return [], 200 # Store widgets to be returned widget_list = [] for widget in widgets: widget = WidgetModel.get_widget_by_id(widget.id) # Format widget data for response widget_list.append(widget.json()) return widget_list, HTTPStatus.OK.value
def test_widget_model() -> NoReturn: """ Tests that widget data can be persisted and fetched from the database """ # Create a Layout instance required for Widget dummy_layout = Layouts(-1, 5, 4, 3, 2, True) # Persist a Widget to the database new_widget = WidgetModel(dependencies.user.id, dummy_layout, dependencies.get_widget_data()) db.session.add(new_widget) # Flush session to get Widgets Id for the layout db.session.flush() dummy_layout.widget_id = new_widget.id db.session.commit() # Fetch widget from database and check they are the same instance fetched_widget = WidgetModel.get_widget_by_id(new_widget.id) assert fetched_widget is new_widget assert fetched_widget.layout is new_widget.layout
def post(self) -> (str, int): """ Creates a Widget layout to the database table 'layouts' Parameters can be passed using a POST request that contains a JSON with the following fields: :param widgetID: The widget identification the layout belongs to :param x: x coordinate of the widget layout :param y: y coordinate of the widget layout :param h: height of the widget layout :param w: width of the widget layout :param static: layout static property :type widgetID: str :type x: int :type y: int :type h: int :type w: int :type static: str :returns: on success a HTTP status code 200, otherwiseif the layout instance is not found a HTTP status code 404, Not Found with json with a key "error" containing a message "layout object not found" """ # Fetch layout values from post content args = self.post_reqparser.parse_args() # Fetch the instance of the widget to assign new layout widget = WidgetModel.get_widget_by_id(args["widgetID"]) # does the widget with the passed widgetID exist? if not widget.layout: # No widget return with the passed widgetID logging.debug("CreateWidgetLayout(): ", status_code=HTTPStatus.NOT_FOUND.value, error="layout object not found") abort(HTTPStatus.NOT_FOUND.value, error="layout object not found") # Modify layout instance for widget widget.layout.widgetID = int(args["widgetID"]) widget.layout.x_coord = args["x"] widget.layout.y_coord = args["y"] widget.layout.height = args["h"] widget.layout.width = args["w"] widget.layout.static = args["static"] # Commit changes to the database widget.save() widget.commit() return "Widget crearted", 200
def make_dummy_widgets(self, number_of_widgets: int = 1) -> [int]: """ Creates widgets for tests :param number_of_widgets: the number of widgets to create :type number_of_widgets: int :return: A list of the widget ids created """ widget_ids = [] for _ in range(number_of_widgets): new_widget = WidgetModel(self.user.id, Layouts(-1, 0, 0, 5, 5, False), self.get_widget_data()) db.session.add(new_widget) db.session.flush() # new_widget.layout.layout.widget_id = new_widget.id db.session.commit() widget_ids.append(new_widget.id) return widget_ids
def remove_all_widgets(self) -> NoReturn: """ Removes all widgets created for the tests """ # Get all widgets with the admin user id response = self.client.post('/widgets/load_widgets', json=dict(userID=self.user.id, limit="1000"), headers=self.auth_header, follow_redirects=True) json_response = response.get_json() # check the type of reponse recieved if isinstance(json_response, dict): if response.get_json()['error'] == 'no widgets found for userID {}'.format(self.user.id): # No widgets were found so return return # Widgets were found, cleanup by removing them for widget in response.get_json(): if widget["userID"] == self.user.id: widget_instance = WidgetModel.get_widget_by_id(widget["id"]) print("Deleting dummy widget: {}".format(widget_instance.id)) db.session.delete(widget_instance) db.session.commit()
def test_save_layouts_endpoints() -> NoReturn: """ Tests the '/widgets/save_layouts' endpoint. The test checks the end point modifies the layout in the database """ global dependencies # Create dummy widgets for test number_of_widgets = 5 widget_ids = dependencies.make_dummy_widgets(number_of_widgets) # Create templates for new layout data layouts_data = {"layouts": []} layout_template = {"id": -1, "x": 0, "y": 0, "h": 0, "w": 0, "static": ""} # Bind the user to the database session but storing an instance of the user to keep user object from expiring dependencies.user.id for widget_id in widget_ids: new_layout = copy.deepcopy(layout_template) new_layout["id"] = widget_id new_layout["x"] = widget_id new_layout["y"] = widget_id new_layout["h"] = widget_id new_layout["w"] = widget_id new_layout["static"] = "true" layouts_data["layouts"].append(new_layout) json_layout = json.dumps(layouts_data) response = dependencies.client.post('/widgets/save_layouts', json=json.loads(json_layout), headers=dependencies.auth_header, follow_redirects=True) assert response.status_code == 200 # Check layout changed for each widget for widget_id in widget_ids: widget = WidgetModel.get_widget_by_id(widget_id) if widget: layout = widget.layout assert layout.x_coord == widget_id assert layout.y_coord == widget_id assert layout.height == widget_id assert layout.width == widget_id assert layout.static
def post(self) -> ([str], int): """ Fetches all layouts for the widgets with a specific userID :param userID: Unique user identification number :param limit: maximum count of widgets to be returned (optional) :type userID: int :type limit: int :returns: on success a list of all the widget layouts related to the userID are returned. If no widget are found for the userID a HTTP status code 404, Not Found is returned with an error message "no widgets found". """ # Fetch the userID from post content ( limit is optional ) args = self.reqparser.parse_args() # Fetch the instances of the widgets to assign the new layouts widgets = WidgetModel.query.filter_by(user_id=args["userID"]).limit( args["limit"]).all() # Where widgets returned if not widgets: # no widgets related to the userID supplied return [], 200 # Store layout instances to be returned layout_list = [] # Get all layout instances for the widgets for widget in widgets: widget = WidgetModel.get_widget_by_id(widget.id) widget.layout.widgetID = widget.id # Format layouts to be return layout_list.append(widget.layout.json()) return layout_list, HTTPStatus.OK.value
def post(self) -> (str, int): """ Pesists widget layout to the database Parameters can be passed using a POST request that contains a JSON with the following fields: :param layouts: layouts to be saved :type layouts: str :param id: Related widget identification number :type id: str :param x: x coordinate of widget :type x: int :param y: y coordinate of widget :type y: int :param h: height of widget :type h: int :param w: width of widget :type w: int :param static: static state :type static: str :return: On success a HTTP status code 200, executed successfully with no content is return otherwise, a HTTP status code 404, not found with content containing JSON objects """ # Keep track of widgetIDs that are not found to inform user widgets_not_found = [] # Keep track of widgetIDs that are updated to inform user widgets_updated = [] # Get layout data passed in post request args = self.post_reqparser.parse_args() # Cycle throught the layout/s recieved in post request (there may be multiple layouts) for layout in args['layouts']: # Sanitize the layout data to be loaded into JSON ( eg. replace single quote with double quotes) layout = layout.replace("'", "\"") # Change sanitized layout data into json format layout_json = json.loads(layout) # Fetch the widget instance widget = WidgetModel.get_widget_by_id(int(layout_json["id"])) # does the widget exist? if not widget: # widget with the widgetID received does not exist so log it for the response widgets_not_found.append(layout_json["id"]) else: # Got a widget. Update its layout widget.layout.widget_id = int(layout_json['id']) widget.layout.x_coord = layout_json['x'] widget.layout.y_coord = layout_json['y'] widget.layout.height = layout_json['h'] widget.layout.width = layout_json['w'] widget.layout.static = bool(layout_json['static']) widgets_updated.append(int(layout_json["id"])) # Save changes to the widget widget.save() widget.commit() # Where all widget layouts updated? if len(widgets_not_found) >= 1: abort(404, error="Widgets not found", widgets_not_found=len(widgets_not_found), widget_ids=json.dumps(widgets_not_found), widgets_updated=json.dumps(widgets_updated)) return "", 200