Skip to content

Commit

Permalink
testing / mocking quote widget
Browse files Browse the repository at this point in the history
  • Loading branch information
lugipfupf committed May 1, 2024
1 parent 051e886 commit 67ce02d
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 28 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ If your widget uses custom routes, eg. to display an image, you can do so by imp
An example of how to do that can be found in the example widget 'simple_image'.

# How to run
## Testing
While in the root of this repo, simply type `pytest` to run all the tests. Alternatively, if that does not work,
try `pytest-3`.

## Development mode Windows
Get all you need by typing `pip install -e .`, then run the application directly from VSCode.

Expand Down
3 changes: 0 additions & 3 deletions happyMirror/widgets/README.md

This file was deleted.

1 change: 1 addition & 0 deletions happyMirror/widgets/quote/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quote_config.py
62 changes: 42 additions & 20 deletions happyMirror/widgets/quote/quote.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,66 @@
import os
import shutil
import importlib
import random
import sys

import requests
import json

from flask import render_template_string

from happyMirror.render import BaseRenderer, RenderResult

try:
import widget_secrets
import widget_config
except ImportError:
from . import widget_secrets
from . import widget_config


class Renderer(BaseRenderer):

def __init__(self, config=None, secrets_config=None) -> None:
if secrets_config is None:
self.secrets = widget_secrets
else:
self.secrets = secrets_config
def __init__(self, alt_config=None) -> None:
self.config = alt_config
if self.config is None:
self.config = self.__check_config()

if config is None:
self.config = widget_config
else:
self.config = config
def next(self, category=None):
if len(self.config.api_key) is not 40:
return [{
"quote": "NO API KEY SET IN CONFIG FILE",
"author": "'Quote' widget",
"category": category,
}]

def next(self):
category = random.choice(self.config.categories)
url = self.config.api_url
if category is not None:
url = url + '?category={}'.format(category)

quote = requests.get(
self.config.api_url + category, headers={'X-Api-Key': self.secrets.api_key}, timeout=10
url, headers={'X-Api-Key': self.config.api_key}, timeout=10
)

return json.loads(quote.text)

def render(self) -> RenderResult:
quote = self.next()
category = None

if self.config.categories is not None:
category = random.choice(self.config.categories)

quote = self.next(category)
return {
'view': render_template_string('{{ quote[0]["quote"] }} - {{ quote[0]["author"] }}', quote=quote),
'name': 'quote'
}

@staticmethod
def __check_config():
config_file = f"{os.getcwd()}/widgets/quote/quote_config.py"
config_example_file = f"{os.getcwd()}/widgets/quote/quote_config_example.py"

if os.path.isfile(config_file) is False:
print(f'No config file was found. A new one will be created as "{config_file}"')
print('Open it and insert your api key, then restart the application.')

shutil.copy(config_example_file, config_file)

return importlib.import_module('quote_config')



Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
api_url = 'https://api.api-ninjas.com/v1/quotes?category='
# Base API Ninja URL
api_url = 'https://api.api-ninjas.com/v1/quotes'

# Once you registered your free account, you can find your api key in you profile.
api_key = 'YOUR_API_KEY'

# These are all categories as per May 2024.
# Remove or comment the ones you don't want. Every time, a new quote is queried, a random category
# will be chosen from this list. This is the same as setting
# categories = None
categories = [
'age',
'alone',
Expand Down
61 changes: 58 additions & 3 deletions happyMirror/widgets/quote/test_quote.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,70 @@
import unittest
import requests_mock

from .quote import Renderer
from . import quote_config_example


class TestQuote(unittest.TestCase):
def setUp(self) -> None:
self.quote = Renderer()
self.API_BASE_URL = 'https://api.api-ninjas.com/v1/quotes'
self.TEST_RESULT = '[{"quote": "Tis but a scratch", "author": "Black Knight"}]'
self.TEST_API_KEY = '0000000000000000000000000000000000000000'


def test_next(self):
self.assertIsNotNone(self.quote.next())
@requests_mock.Mocker()
def test_next(self, m):
m.get(
self.API_BASE_URL + '?category=monty-python',
text=self.TEST_RESULT
)

config = quote_config_example
config.api_key = self.TEST_API_KEY
quote = Renderer(alt_config=config)
result = quote.next('monty-python')

self.__assert_result(result)

@requests_mock.Mocker()
def test_next_with_no_category(self, m):
m.get(
self.API_BASE_URL,
text=self.TEST_RESULT
)

config = quote_config_example
config.api_key = self.TEST_API_KEY
quote = Renderer(alt_config=config)

result = quote.next()

self.__assert_result(result)


@requests_mock.Mocker()
def test_next_with_no_apikey(self, m):
m.get(
self.API_BASE_URL,
text=self.TEST_RESULT
)

config = quote_config_example
config.api_key = '1234'
quote = Renderer(alt_config=quote_config_example)

result = quote.next()

self.assertEqual(result[0]['quote'], 'NO API KEY SET IN CONFIG FILE')
self.assertEqual(result[0]['author'], "'Quote' widget")

def __assert_result(self, result):
self.assertIsNotNone(result)
self.assertIsInstance(result, list)
self.assertEqual(len(result), 1)
self.assertIsInstance(result[0], dict)
self.assertEqual(result[0]['quote'], 'Tis but a scratch')
self.assertEqual(result[0]['author'], 'Black Knight')


if __name__ == '__main__':
Expand Down
1 change: 0 additions & 1 deletion happyMirror/widgets/quote/widget_secrets.py

This file was deleted.

0 comments on commit 67ce02d

Please sign in to comment.