def setup_class(self) -> None:
        #pylint: disable=W0201
        self.appInfo = AppInfo()
        settingsFilenameOrig = os.path.join(self.appInfo.path, "misc/setup/situationboard_default.conf")
        settingsFilename = os.path.join(self.appInfo.path, ".temp/situationboard.conf")
        databaseFilename = os.path.join(self.appInfo.path, ".temp/situationboard.sqlite")

        shutil.copy(settingsFilenameOrig, settingsFilename)

        self.database = Database(databaseFilename, reset = True)

        settings = Settings(settingsFilename, self.appInfo.path)
        settings.setFrontendHeader("header")
        settings.setFrontendNews("news")
        settings.setBoolean(Settings.SECTION_BACKEND, "web_api", True)

        displayPowerManager = DisplayPowerManager(settings)

        self.webSocket = WebSocket(self.appInfo, settings, self.database)

        pluginManager = PluginManager(settings, self.database, self.webSocket, displayPowerManager)

        self.webSocket.init(pluginManager)

        self.appClient = self.webSocket.app_test_client()
        self.socketClient = self.webSocket.socket_test_client(self.appClient)
Example #2
0
def main():
    # init
    db_handler = Database()
    scraper = Scraper()
    annotator_instance = Annotator()
    evaluator = Evaluator()

    # 1: scrape
    base_urls = db_handler.read("SELECT url FROM articles.source;")
    base_urls = [base_url[0] for base_url in base_urls]
    for base_url in base_urls:
        if "seekingalpha.com" in base_url:
            scraper.scrape(db_handler, base_url, True)
        else:
            scraper.scrape(db_handler, base_url)
    scraper.quit_driver()

    # 2: annotate
    articles = db_handler.read(
        "SELECT content FROM articles.article WHERE url LIKE '%fool.com%';")
    articles = [article[0] for article in articles]

    # run either

    # - manual (either)
    # -- internal annotation
    # annotator_instance.manual_annotation(articles[:50], "auto_annotated")
    # -- csv export
    annotator_instance.unannotated_csv_export(articles[:50], "auto_annotated")

    # - automatic
    # annotator_instance.automatic_annotation(articles, "auto_annotated")

    # 3: evaluate
    model_file = "auto_annotated"

    data = None
    with open("./backend/data/" + model_file + ".csv", "r") as csvfile:
        data = list(csv.reader(csvfile))

    data = [tuple((datum[0], datum[1])) for datum in data]
    classifier = NaiveBayesClassifier(data)

    for i in range(40, 50):
        evaluator.evaluate("article_" + str(i), classifier)
Example #3
0
    def test_csv(self) -> None:
        appInfo = AppInfo()
        dbFilename = os.path.join(appInfo.path, ".temp/situationboard.sqlite")
        inFilename = os.path.join(appInfo.path, "docs/dummy.csv")
        outFilename = os.path.join(appInfo.path, ".temp/dummy.csv")
        csvFilename = os.path.join(appInfo.path, ".temp/corner.csv")

        ###### TEST 1 (round trip) ######

        # create a new (empty) database
        d = Database(dbFilename, reset = True)
        assert(d.getEventCount(textOnly = False) == 0)

        # import data from CSV
        i = CSVImporter(d)
        result = i.importEvents(inFilename)
        assert(result == 0)
        assert(d.getEventCount(textOnly = False) > 0)

        # export data to CSV
        e = CSVExporter(d)
        result = e.exportEvents(outFilename)
        assert(result == 0)

        # compare CSV files
        assert(filecmp.cmp(inFilename, outFilename, shallow=False))

        # close database
        d.close()

        ###### TEST 2 (corner cases) ######

        # create a new (empty) database
        d = Database(dbFilename, reset = True)
        assert(d.getEventCount(textOnly = False) == 0)

        # add new event with pathologic content
        ts = datetime.datetime.now().strftime(AlarmEvent.TIMESTAMP_FORMAT)
        content = "Test\n;\\Test\nTest\"äöüß\"\"äöüß'äöüß''äöüß\näöüß"

        aeAdded = AlarmEvent()
        aeAdded.timestamp = ts
        aeAdded.event = content
        aeAdded.eventDetails = content
        aeAdded.location = content
        aeAdded.locationDetails = content
        aeAdded.comment = content
        aeAdded.alarmTimestamp = ts
        aeAdded.locationLatitude = 1.12
        aeAdded.locationLongitude = -13.2
        eventID = d.addEvent(aeAdded)

        # export data to CSV
        e = CSVExporter(d)
        result = e.exportEvents(csvFilename)
        assert(result == 0)

        # close database
        d.close()

        # create a new (empty) database
        d = Database(dbFilename, reset = True)

        # import data from CSV
        i = CSVImporter(d)
        result = i.importEvents(csvFilename)
        assert(result == 0)
        assert(d.getEventCount(textOnly = False) > 0)

        # load event
        aeLoaded = d.getEvent(eventID)
        assert(aeLoaded is not None)

        # compare event data
        assert(aeAdded.comment == aeLoaded.comment)

        # close database
        d.close()
Example #4
0
    def test_database(self) -> None:
        appInfo = AppInfo()
        databaseFilename = os.path.join(appInfo.path,
                                        ".temp/situationboard.sqlite")
        maxLastEvents = 10

        # check that creating a database works and yields an empty database
        db = Database(databaseFilename, reset=True)
        assert (db.getEventCount(textOnly=False) == 0)
        assert (db.getEventCount(textOnly=True) == 0)
        assert (db.getEvent(1302) is None)
        assert (len(db.getEvents(textOnly=False)) == 0)
        assert (len(db.getEvents(textOnly=True)) == 0)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 0)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 0)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 0)

        # check that inserting a binary event succeeds
        newEvent1 = self.__createBinaryEvent()
        newEventTemp1 = copy.deepcopy(newEvent1)
        assert (db.updateEvent(newEventTemp1) != 0)
        eventID1 = db.addEvent(newEventTemp1)
        assert (eventID1 != AlarmEvent.NO_ID)
        assert (newEventTemp1.eventID == eventID1)
        assert (db.getEventCount(textOnly=False) == 1)
        assert (db.getEventCount(textOnly=True) == 0)
        assert (len(db.getEvents(textOnly=False)) == 1)
        assert (len(db.getEvents(textOnly=True)) == 0)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 0)
        assert (db.getEvent(eventID1) is not None)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 0)

        # check that inserting a text event succeeds
        newEvent2 = self.__createTextEvent()
        newEvent2Temp = copy.deepcopy(newEvent2)
        eventID2 = db.addEvent(newEvent2Temp)
        assert (eventID2 != AlarmEvent.NO_ID)
        assert (newEvent2Temp.eventID == eventID2)
        assert (db.getEventCount(textOnly=False) == 2)
        assert (db.getEventCount(textOnly=True) == 1)
        assert (len(db.getEvents(textOnly=False)) == 2)
        assert (len(db.getEvents(textOnly=True)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 2)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 1)
        assert (db.getEvent(eventID2) is not None)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 2)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 2)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 2)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 2)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 1)

        db.commitAndClose()

        # check that reloading a database succeeds and yields existing data
        dbr = Database(databaseFilename, reset=False)
        assert (dbr.getEventCount(textOnly=False) == 2)
        assert (dbr.getEventCount(textOnly=True) == 1)
        assert (len(dbr.getEvents(textOnly=False)) == 2)
        assert (len(dbr.getEvents(textOnly=True)) == 1)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=False)) == 2)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=True)) == 1)

        # check that retrieving an event succeeds after reload succeeds and yields the correct data
        event1 = dbr.getEvent(eventID1)
        assert (event1 is not None)
        assert (isinstance(event1, AlarmEvent))
        assert (event1.eventID == eventID1)
        self.__compareEvents(event1, newEvent1)

        # check that retrieving an event succeeds after reload succeeds and yields the correct data
        event2 = dbr.getEvent(eventID2)
        assert (event2 is not None)
        assert (isinstance(event2, AlarmEvent))
        assert (event2.eventID == eventID2)
        self.__compareEvents(event2, newEvent2)

        # check that updating an event succeeds
        newEvent2Updated = copy.deepcopy(newEvent2Temp)
        self.__updateTextEvent(newEvent2Updated)
        newEvent2UpdatedTemp = copy.deepcopy(newEvent2Updated)
        assert (dbr.updateEvent(newEvent2UpdatedTemp) == 0)
        event2Updated = dbr.getEvent(eventID2)
        assert (event2Updated is not None)
        assert (isinstance(event2Updated, AlarmEvent))
        assert (event2Updated.eventID == eventID2)
        self.__compareEvents(event2Updated, newEvent2Updated)

        # check that deleting an event by ID succeeds
        assert (dbr.removeEventID(eventID1) == 0)
        assert (dbr.getEventCount(textOnly=False) == 1)
        assert (dbr.getEventCount(textOnly=True) == 1)
        assert (dbr.getEvent(eventID1) is None)
        assert (len(dbr.getEvents(textOnly=False)) == 1)
        assert (len(dbr.getEvents(textOnly=True)) == 1)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=False)) == 1)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=True)) == 1)

        # check that deleting an event succeeds
        assert (dbr.removeEvent(newEvent2Updated) == 0)
        assert (dbr.getEventCount(textOnly=False) == 0)
        assert (dbr.getEventCount(textOnly=True) == 0)
        assert (dbr.getEvent(eventID2) is None)
        assert (len(dbr.getEvents(textOnly=False)) == 0)
        assert (len(dbr.getEvents(textOnly=True)) == 0)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=False)) == 0)
        assert (len(dbr.getLastEvents(maxLastEvents, textOnly=True)) == 0)

        # check that deleting non-existent events fails
        assert (dbr.removeEvent(event1) != 0)
        assert (dbr.removeEventID(eventID2) != 0)

        dbr.commitAndClose()
Example #5
0
    def test_handle_event(self) -> None:
        #pylint: disable=W0201
        appInfo = AppInfo()
        settingsFilenameOrig = os.path.join(
            appInfo.path, "misc/setup/situationboard_default.conf")
        settingsFilename = os.path.join(appInfo.path,
                                        ".temp/situationboard.conf")
        databaseFilename = os.path.join(appInfo.path,
                                        ".temp/situationboard.sqlite")

        shutil.copy(settingsFilenameOrig, settingsFilename)

        settings = Settings(settingsFilename, appInfo.path)

        maxLastEvents = 10

        displayPowerManager = DisplayPowerManager(settings)

        db = Database(databaseFilename, reset=True)

        webSocket = WebSocket(appInfo, settings, db)

        pluginManager = PluginManager(settings, db, webSocket,
                                      displayPowerManager)

        webSocket.init(pluginManager)

        # check that creating a database works and yields an empty database
        assert (db.getEventCount(textOnly=False) == 0)
        assert (db.getEventCount(textOnly=True) == 0)
        assert (db.getEvent(1302) is None)
        assert (len(db.getEvents(textOnly=False)) == 0)
        assert (len(db.getEvents(textOnly=True)) == 0)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 0)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 0)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 0)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 0)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 0)

        action = ActionUpdateDatabase("", settings, db, webSocket)

        # check that inserting an alarm event succeeds
        newEvent = self.__createEvent()
        action.handleEvent(newEvent)
        assert (not newEvent.noID)
        assert (db.getEventCount(textOnly=False) == 1)
        assert (db.getEventCount(textOnly=True) == 1)
        assert (len(db.getEvents(textOnly=False)) == 1)
        assert (len(db.getEvents(textOnly=True)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 1)
        newEventID = newEvent.eventID
        assert (db.getEvent(newEventID) is not None)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 1)

        # check that updating an alarm event succeeds
        self.__updateEvent(newEvent)
        action.handleEvent(newEvent)
        assert (newEvent.eventID == newEventID)
        assert (db.getEventCount(textOnly=False) == 1)
        assert (db.getEventCount(textOnly=True) == 1)
        assert (len(db.getEvents(textOnly=False)) == 1)
        assert (len(db.getEvents(textOnly=True)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=False)) == 1)
        assert (len(db.getLastEvents(maxLastEvents, textOnly=True)) == 1)
        retrievedEvent = db.getEvent(newEventID)
        assert (retrievedEvent is not None)
        assert (retrievedEvent.comment ==
                Test_ActionUpdateDatabase.UPDATED_COMMENT)

        # check for valid stats
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=False) == 1)
        assert (db.getEventStats(DatabaseTimespan.TOTAL, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.YEAR, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.MONTH, textOnly=True) == 1)
        assert (db.getEventStats(DatabaseTimespan.TODAY, textOnly=True) == 1)

        db.commitAndClose()
    def run(self, argv: List[str]) -> None:
        """This is the main entry point of the backend application."""

        defaultConfigPath = os.path.join(
            self.appInfo.path, SituationBoard.DEFAULT_CONFIG_FILENAME)
        defaultConfigPath = os.getenv("SB_CONFIG", defaultConfigPath)

        defaultDatabasePath = os.path.join(
            self.appInfo.path, SituationBoard.DEFAULT_DATABASE_FILENAME)
        defaultDatabasePath = os.getenv("SB_DATABASE", defaultDatabasePath)

        parser = argparse.ArgumentParser(
            description=f"{self.appInfo.name} v{self.appInfo.version}",
            add_help=False)
        igroup = parser.add_argument_group("Important Commands and Parameters")
        mmutex = igroup.add_mutually_exclusive_group()
        mmutex.add_argument("-s",
                            "--server",
                            help="start backend server (default)",
                            default=True,
                            action='store_true')
        mmutex.add_argument("-i",
                            "--import",
                            help="import data from CSV",
                            default=None,
                            dest='importFile')
        mmutex.add_argument("-e",
                            "--export",
                            help="export data to CSV",
                            default=None,
                            dest='exportFile')
        mmutex.add_argument("-n",
                            "--version",
                            help="show version number and exit",
                            default=False,
                            action='store_true')
        mmutex.add_argument("-h",
                            "--help",
                            help="show this help message and exit",
                            action='help')
        ogroup = parser.add_argument_group("Other Parameters and Options")
        ogroup.add_argument("-c",
                            "--config",
                            help="alternate path to config file",
                            default=defaultConfigPath,
                            dest='configPath')
        ogroup.add_argument("-d",
                            "--database",
                            help="alternate path to database file",
                            default=defaultDatabasePath,
                            dest='databasePath')
        ogroup.add_argument("-r",
                            "--reset",
                            help="reset database before import",
                            default=False,
                            action='store_true')
        ogroup.add_argument("-v",
                            "--verbose",
                            help="force debug output",
                            default=False,
                            action='store_true')

        # args = parser.parse_args(argv)
        args = parser.parse_args()

        # Check command line parameters
        if (args.reset is True) and (args.importFile is None):
            parser.error("reset is only allowed for the import command")
            sys.exit(1)

        # Show version number and exit (if requested)
        if args.version:
            print(f"{self.appInfo.name} {self.appInfo.version}")
            sys.exit(0)

        # Print application header
        if args.importFile is not None:
            self.print("Starting import from CSV...")
        elif args.exportFile is not None:
            self.print("Starting export to CSV...")
        else:
            self.clrPrint(
                f"Starting {self.appInfo.name} backend v{self.appInfo.version} (PID {self.appInfo.pid})"
            )

        # Load configuration and database
        settings = Settings(args.configPath, self.appInfo.path, args.verbose)
        database = Database(args.databasePath, args.reset)
        self.lateInit(settings)

        # Handle CSV import/export (if required)
        if args.importFile is not None:
            csvImporter = CSVImporter(database)
            result = csvImporter.importEvents(args.importFile)
            sys.exit(result)
        elif args.exportFile is not None:
            csvExporter = CSVExporter(database)
            result = csvExporter.exportEvents(args.exportFile)
            sys.exit(result)

        # Start SituationBoard backend service
        backendService = SituationBoardBackend(self.appInfo, settings,
                                               database)
        backendService.run()
class Test_WebSocket:

    def setup_class(self) -> None:
        #pylint: disable=W0201
        self.appInfo = AppInfo()
        settingsFilenameOrig = os.path.join(self.appInfo.path, "misc/setup/situationboard_default.conf")
        settingsFilename = os.path.join(self.appInfo.path, ".temp/situationboard.conf")
        databaseFilename = os.path.join(self.appInfo.path, ".temp/situationboard.sqlite")

        shutil.copy(settingsFilenameOrig, settingsFilename)

        self.database = Database(databaseFilename, reset = True)

        settings = Settings(settingsFilename, self.appInfo.path)
        settings.setFrontendHeader("header")
        settings.setFrontendNews("news")
        settings.setBoolean(Settings.SECTION_BACKEND, "web_api", True)

        displayPowerManager = DisplayPowerManager(settings)

        self.webSocket = WebSocket(self.appInfo, settings, self.database)

        pluginManager = PluginManager(settings, self.database, self.webSocket, displayPowerManager)

        self.webSocket.init(pluginManager)

        self.appClient = self.webSocket.app_test_client()
        self.socketClient = self.webSocket.socket_test_client(self.appClient)

    def teardown_class(self) -> None:
        self.database.commitAndClose()

    def test_get_last_alarm_events(self) -> None:
        self.__emit("get_last_alarm_events", {'count': 10})
        (event, args) = self.__getReceived()
        assert(event == "last_alarm_events")
        assert(args['total_events'] == 0)
        assert(args['alarm_events'] == "[]")

    def test_get_stats(self) -> None:
        self.__emit("get_stats")
        (event, args) = self.__getReceived()
        assert(event == "stats")
        assert(args is not None)
        assert(args['total'] == 0)
        assert(args['year'] == 0)
        assert(args['month'] == 0)
        assert(args['today'] == 0)

    def test_get_header(self) -> None:
        self.__emit("get_header")
        (event, args) = self.__getReceived()
        assert(event == "header")
        assert(args is not None)
        assert(args['header'] == "header")

    def test_get_news(self) -> None:
        self.__emit("get_news")
        (event, args) = self.__getReceived()
        assert(event == "news")
        assert(args is not None)
        assert(args['news'] == "news")

    def test_get_state(self) -> None:
        self.__emit("get_state")
        (event, args) = self.__getReceived()
        assert(event == "state")
        assert(args is not None)
        assert(args['version'] == self.appInfo.version)
        assert(args['start_timestamp'] > 0)
        assert(args['source_state'] == SourceState.OK)

    def test_broadcast_alarm_event(self) -> None:
        alarmEvent = AlarmEvent(1302)
        self.webSocket.broadcastAlarmEvent(alarmEvent)
        (event, args) = self.__getReceived()
        assert(event == "alarm_event")
        assert(args is not None)
        assert(args['eventID'] == 1302)

    def test_broadcast_header(self) -> None:
        self.webSocket.broadcastHeader("TEST\nHEADER")
        (event, args) = self.__getReceived()
        assert(event == "header")
        assert(args is not None)
        assert(args['header'] == "TEST\nHEADER")

    def test_broadcast_news(self) -> None:
        self.webSocket.broadcastNews("TEST\nNEWS")
        (event, args) = self.__getReceived()
        assert(event == "news")
        assert(args is not None)
        assert(args['news'] == "TEST\nNEWS")

    def test_broadcast_database_changed(self) -> None:
        self.webSocket.broadcastDatabaseChanged()
        (event, _) = self.__getReceived()
        assert(event == "database_changed")

    def test_broadcast_calendar_changed(self) -> None:
        self.webSocket.broadcastCalendarChanged()
        (event, _) = self.__getReceived()
        assert (event == "calendar_changed")

    def test_static(self) -> None:
        response = self.appClient.get('/css/situationboard.css')
        assert(response.status_code == 200)

    def test_index(self) -> None:
        response = self.appClient.get('/')
        assert(response.status_code == 200)

    def test_javascript_frontend(self) -> None:
        response = self.appClient.get('/js/situationboard.js')
        assert(response.status_code == 200)

    def test_javascript_settings(self) -> None:
        response = self.appClient.get('/js/frontend/util/settings.js')
        assert(response.status_code == 200)

    def test_api_stats(self) -> None:
        response = self.appClient.get('/api/v1/stats')
        assert(response.status_code == 200)
        assert(response.json['result'] == "ok")
        stats = response.json['stats']
        assert(stats['total'] == 0)
        assert(stats['year'] == 0)
        assert(stats['month'] == 0)
        assert(stats['today'] == 0)

    def test_api_state(self) -> None:
        response = self.appClient.get('/api/v1/state')
        assert(response.status_code == 200)
        assert(response.json['result'] == "ok")
        state = response.json['state']
        assert(state['version'] == self.appInfo.version)
        assert(state['start_timestamp'] > 0)
        assert(state['source_state'] == SourceState.OK)

    def __emit(self, event: str, args: Optional[Dict[str, Any]] = None) -> None:
        if args is not None:
            self.socketClient.emit(event, args, namespace=WebSocket.NS)
        else:
            self.socketClient.emit(event, namespace=WebSocket.NS)

    def __getReceived(self) -> Tuple[Any, Any]:
        response = self.socketClient.get_received(WebSocket.NS)
        assert(len(response) == 1)
        result = response[0]
        event = result['name']
        argsList = result['args']
        asgsListLen = len(argsList)
        assert(asgsListLen <= 1)
        if asgsListLen == 1:
            args = argsList[0]
            return (event, args)

        return (event, None)
class Test_ActionUpdateFrontend:
    def setup_class(self) -> None:
        #pylint: disable=W0201
        appInfo = AppInfo()
        settingsFilenameOrig = os.path.join(
            appInfo.path, "misc/setup/situationboard_default.conf")
        settingsFilename = os.path.join(appInfo.path,
                                        ".temp/situationboard.conf")
        databaseFilename = os.path.join(appInfo.path,
                                        ".temp/situationboard.sqlite")

        shutil.copy(settingsFilenameOrig, settingsFilename)

        self.database = Database(databaseFilename, reset=True)

        settings = Settings(settingsFilename, appInfo.path)
        settings.setFrontendHeader("header")
        settings.setFrontendNews("news")

        displayPowerManager = DisplayPowerManager(settings)

        self.webSocket = WebSocket(appInfo, settings, self.database)

        pluginManager = PluginManager(settings, self.database, self.webSocket,
                                      displayPowerManager)

        self.webSocket.init(pluginManager)

        appClient = self.webSocket.app_test_client()
        self.socketClient = self.webSocket.socket_test_client(appClient)

        self.action = ActionUpdateFrontend("", settings, self.webSocket)

    def teardown_class(self) -> None:
        self.database.commitAndClose()

    def test_handle_event_alarm(self) -> None:
        alarmEvent = AlarmEvent(1302)
        self.action.handleEvent(alarmEvent)
        (event, args) = self.__getReceived()
        assert (event == "alarm_event")
        assert (args is not None)
        assert (args['eventID'] == 1302)

    def test_handle_event_setting_header(self) -> None:
        settingEvent = SettingEvent()
        settingEvent.key = "header"
        settingEvent.value = "new header"
        self.action.handleEvent(settingEvent)
        (event, args) = self.__getReceived()
        assert (event == "header")
        assert (args is not None)
        assert (args['header'] == "new header")

    def test_handle_event_setting_news(self) -> None:
        settingEvent = SettingEvent()
        settingEvent.key = "news"
        settingEvent.value = "new news"
        self.action.handleEvent(settingEvent)
        (event, args) = self.__getReceived()
        assert (event == "news")
        assert (args is not None)
        assert (args['news'] == "new news")

    def __getReceived(self) -> Tuple[Any, Any]:
        response = self.socketClient.get_received(WebSocket.NS)
        assert (len(response) == 1)
        result = response[0]
        event = result['name']
        argsList = result['args']
        asgsListLen = len(argsList)
        assert (asgsListLen <= 1)
        if asgsListLen == 1:
            args = argsList[0]
            return (event, args)

        return (event, None)