interactive bots: Create monkeytest.it bot.
This commit is contained in:
		
							parent
							
								
									1fd4dfc86e
								
							
						
					
					
						commit
						08bd395658
					
				
					 10 changed files with 487 additions and 0 deletions
				
			
		
							
								
								
									
										65
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/doc.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/doc.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
# monkeytest.it bot
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
This bot provides a quick way to check a site from a chat.
 | 
			
		||||
Using their monkeytestit's API  key, the user can check a website
 | 
			
		||||
for certain failures that user wants to see.
 | 
			
		||||
 | 
			
		||||
## Setting up API key
 | 
			
		||||
 | 
			
		||||
1. Get your monkeytest.it API key, located in your
 | 
			
		||||
   [dashboard](https://monkeytest.it/dashboard).
 | 
			
		||||
 | 
			
		||||
2. Create your own `monkeytestit.conf` file by copying the existing one in
 | 
			
		||||
   `bots/monkeytest/monkeytestit.conf`.
 | 
			
		||||
 | 
			
		||||
3. Inside the config file, you will see this:
 | 
			
		||||
   ```
 | 
			
		||||
   [monkeytestit]
 | 
			
		||||
   api_key = <api key here>
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
4. Replace `<api key here>` with your API key
 | 
			
		||||
 | 
			
		||||
5. Save the configuration file.
 | 
			
		||||
 | 
			
		||||
## Running the bot
 | 
			
		||||
 | 
			
		||||
Let `<path_to_config>` be the path to the config file, and let
 | 
			
		||||
`<path_to_zuliprc>` be the path to the zuliprc file.
 | 
			
		||||
 | 
			
		||||
You can run the bot by running:
 | 
			
		||||
 | 
			
		||||
`zulip-run-bot -b <path_to_config> monkeytestit --config-file
 | 
			
		||||
<path_to_zuliprc>`
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
**Note**: You **must** not forget to put `http://` or `https://`
 | 
			
		||||
before a website. Otherwise, the check will fail.
 | 
			
		||||
 | 
			
		||||
### Simple check with default settings
 | 
			
		||||
 | 
			
		||||
To check a website with all enabled checkers, run:
 | 
			
		||||
`check https://website`
 | 
			
		||||
 | 
			
		||||
### Check with options
 | 
			
		||||
 | 
			
		||||
To check a website with certain enabled checkers, run:
 | 
			
		||||
`check https://website <checker_options>`
 | 
			
		||||
 | 
			
		||||
The checker options are supplied to: `on_load`, `on_click`, `page_weight`,
 | 
			
		||||
`seo`, `broken_links`, `asset_count` **in order**.
 | 
			
		||||
 | 
			
		||||
Example 1: Disable `on_load`, enable the rest  
 | 
			
		||||
command: `check https://website 0`
 | 
			
		||||
 | 
			
		||||
Example 2: Disable `asset_count`, enable the rest  
 | 
			
		||||
command: `check https//website 1 1 1 1 1 0`
 | 
			
		||||
 | 
			
		||||
Example 3: Disable `on_load` and `page_weight`, enable the rest  
 | 
			
		||||
command: `check https://website 0 1 0`
 | 
			
		||||
 | 
			
		||||
So for instance, if you wanted to disable `asset_count`, you have
 | 
			
		||||
to supply every params before it.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
{
 | 
			
		||||
  "request": {
 | 
			
		||||
    "api_url": "https://monkeytest.it/test",
 | 
			
		||||
    "params": {
 | 
			
		||||
      "on_load": "true",
 | 
			
		||||
      "seo": "true",
 | 
			
		||||
      "secret": "None",
 | 
			
		||||
      "broken_links": "true",
 | 
			
		||||
      "url": "https://website.com",
 | 
			
		||||
      "on_click": "true",
 | 
			
		||||
      "page_weight": "true",
 | 
			
		||||
      "asset_count": "true"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "response": {
 | 
			
		||||
    "results_url": "https://monkeytest.it/test/33ffc164-cccd-4466-8008-3de00ba787e8",
 | 
			
		||||
    "status": "tests_failed",
 | 
			
		||||
    "enabled_checkers": {
 | 
			
		||||
      "seo": true,
 | 
			
		||||
      "asset_count": true,
 | 
			
		||||
      "on_click": true,
 | 
			
		||||
      "on_load": true,
 | 
			
		||||
      "page_weight": true,
 | 
			
		||||
      "broken_links": true
 | 
			
		||||
    },
 | 
			
		||||
    "failures": {
 | 
			
		||||
      "seo": {
 | 
			
		||||
        "Images missing alt": [
 | 
			
		||||
          "div#site-header > header > div > div.logo.box > a > img",
 | 
			
		||||
          "div#site-header > header > div > div.menu-button.box > a > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div.slick-slide.slick-cloned > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div.slick-slide.slick-cloned > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div.slick-slide.slick-current.slick-active.slick-center > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div:nth-child(4) > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div:nth-child(5) > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div.slick-slide.slick-cloned.slick-center > img",
 | 
			
		||||
          "div#homeTemplateCarousel > div > div > div.slick-slide.slick-cloned > img"
 | 
			
		||||
        ],
 | 
			
		||||
        "Too many H1 tags": [
 | 
			
		||||
          "div#banner > div > h1",
 | 
			
		||||
          "html > body > div.ui-loader.ui-corner-all.ui-body-a.ui-loader-default > h1"
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "response-headers": {
 | 
			
		||||
    "Content-Type":"application/json",
 | 
			
		||||
    "Server":"cloudflare",
 | 
			
		||||
    "Date":"Tue, 02 Jan 2018 14:29:18 GMT",
 | 
			
		||||
    "Content-Length":"1280",
 | 
			
		||||
    "CF-RAY":"3d6e6815a83817bc-SIN",
 | 
			
		||||
    "Connection":"keep-alive",
 | 
			
		||||
    "Set-Cookie":"__cfduid=dd7e2a746cf1abadd1348ba6411ad21391514903325; expires=Wed, 02-Jan-19 14:28:45 GMT; path=/; domain=.monkeytest.it; HttpOnly"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
{
 | 
			
		||||
  "request": {
 | 
			
		||||
    "api_url": "https://monkeytest.it/test",
 | 
			
		||||
    "params": {
 | 
			
		||||
      "on_load": "true",
 | 
			
		||||
      "seo": "true",
 | 
			
		||||
      "secret": "None",
 | 
			
		||||
      "broken_links": "true",
 | 
			
		||||
      "url": "https://website.com",
 | 
			
		||||
      "on_click": "true",
 | 
			
		||||
      "page_weight": "true",
 | 
			
		||||
      "asset_count": "true"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "response": {
 | 
			
		||||
    "enabled_checkers":{
 | 
			
		||||
      "asset_count":false,
 | 
			
		||||
      "broken_links":true,
 | 
			
		||||
      "on_click":false,
 | 
			
		||||
      "on_load":false,
 | 
			
		||||
      "page_weight":false,
 | 
			
		||||
      "seo":false
 | 
			
		||||
    },
 | 
			
		||||
    "status":"success",
 | 
			
		||||
    "test_id":"a7c33bc6-35de-468c-81c1-7317162c02ab"
 | 
			
		||||
  },
 | 
			
		||||
  "response-headers": {
 | 
			
		||||
    "Content-Type":"application/json",
 | 
			
		||||
    "Server":"cloudflare",
 | 
			
		||||
    "Date":"Tue, 02 Jan 2018 15:08:03 GMT",
 | 
			
		||||
    "Transfer-Encoding":"chunked",
 | 
			
		||||
    "CF-RAY":"3d6e9f90c8c5080b-SIN",
 | 
			
		||||
    "Connection":"keep-alive",
 | 
			
		||||
    "Content-Encoding":"gzip",
 | 
			
		||||
    "Set-Cookie":"__cfduid=d709afa5ead1c50719f24ddf7266655791514905597; expires=Wed, 02-Jan-19 15:06:37 GMT; path=/; domain=.monkeytest.it; HttpOnly"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										28
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/extract.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/extract.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
"""This module fetches the report from the website by doing a get request to
 | 
			
		||||
the predefined url. The result is then parsed to JSON for further management
 | 
			
		||||
in report.py
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
import requests
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fetch(options: dict):
 | 
			
		||||
    """Makes a request then returns the dictionary version of the response
 | 
			
		||||
 | 
			
		||||
    :param options: Options dictionary containing the payload for the request
 | 
			
		||||
    :return: A dictionary containing keys and values to be managed by report.py
 | 
			
		||||
    :raises JSONDecodeError: if the get is unsuccessful. This could mean
 | 
			
		||||
            faulty link or any other causes.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    res = requests.get("https://monkeytest.it/test", params=options)
 | 
			
		||||
 | 
			
		||||
    if "server timed out" in res.text:
 | 
			
		||||
        return {"error": "The server timed out before sending a response to "
 | 
			
		||||
                         "the request. Report is available at "
 | 
			
		||||
                         "[Test Report History]"
 | 
			
		||||
                         "(https://monkeytest.it/dashboard)."}
 | 
			
		||||
 | 
			
		||||
    return json.loads(res.text)
 | 
			
		||||
							
								
								
									
										72
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/parse.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/parse.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
"""Used to parse message and return a dictionary containing a payload
 | 
			
		||||
for extract.py
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from json.decoder import JSONDecodeError
 | 
			
		||||
from typing import Text
 | 
			
		||||
 | 
			
		||||
from zulip_bots.bots.monkeytestit.lib import extract
 | 
			
		||||
from zulip_bots.bots.monkeytestit.lib import report
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def execute(message: Text, apikey: Text) -> Text:
 | 
			
		||||
    """Parses message and returns a dictionary
 | 
			
		||||
 | 
			
		||||
    :param message: The message
 | 
			
		||||
    :param apikey: A MonkeyTestit api key, presumably in the config file
 | 
			
		||||
    :return: A response string
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    params = message.split(" ")
 | 
			
		||||
    command = params[0]
 | 
			
		||||
 | 
			
		||||
    if "check" in command.lower():
 | 
			
		||||
        len_params = len(params)
 | 
			
		||||
 | 
			
		||||
        if len_params < 2:
 | 
			
		||||
            return failed("You **must** provide at least an URL to perform a "
 | 
			
		||||
                          "check.")
 | 
			
		||||
 | 
			
		||||
        options = {"secret": apikey, "url": params[1], "on_load": "true",
 | 
			
		||||
                   "on_click": "true", "page_weight": "true", "seo": "true",
 | 
			
		||||
                   "broken_links": "true", "asset_count": "true"}
 | 
			
		||||
 | 
			
		||||
        # Set the options only if supplied
 | 
			
		||||
 | 
			
		||||
        if len_params >= 3:
 | 
			
		||||
            options["on_load"] = "true" if params[2] == "1" else "false"
 | 
			
		||||
        if len_params >= 4:
 | 
			
		||||
            options["on_click"] = "true" if params[3] == "1" else "false"
 | 
			
		||||
        if len_params >= 5:
 | 
			
		||||
            options["page_weight"] = "true" if params[4] == "1" else "false"
 | 
			
		||||
        if len_params >= 6:
 | 
			
		||||
            options["seo"] = "true" if params[5] == "1" else "false"
 | 
			
		||||
        if len_params >= 7:
 | 
			
		||||
            options["broken_links"] = "true" if params[6] == "1" else "false"
 | 
			
		||||
        if len_params >= 8:
 | 
			
		||||
            options["asset_count"] = "true" if params[7] == "1" else "false"
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            fetch_result = extract.fetch(options)
 | 
			
		||||
        except JSONDecodeError:
 | 
			
		||||
            return failed("Cannot decode a JSON response. "
 | 
			
		||||
                          "Perhaps faulty link. Link must start "
 | 
			
		||||
                          "with `http://` or `https://`.")
 | 
			
		||||
 | 
			
		||||
        return report.compose(fetch_result)
 | 
			
		||||
 | 
			
		||||
        # The disadvantage here is that the user has to supply every params if
 | 
			
		||||
        # the user needs to modify the asset_count. There are probably ways
 | 
			
		||||
        # to counteract this, but I think this is more fast to run.
 | 
			
		||||
    else:
 | 
			
		||||
        return "Unknown command. Available commands: `check <website> " \
 | 
			
		||||
               "[params]`"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def failed(message: Text) -> Text:
 | 
			
		||||
    """Simply attaches a failed marker to a message
 | 
			
		||||
 | 
			
		||||
    :param message: The message
 | 
			
		||||
    :return: String
 | 
			
		||||
    """
 | 
			
		||||
    return "Failed: " + message
 | 
			
		||||
							
								
								
									
										128
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,128 @@
 | 
			
		|||
"""Used to mainly compose a decorated report for the user
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from typing import Dict, Text, List
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compose(results: Dict) -> Text:
 | 
			
		||||
    """Composes a report based on test results
 | 
			
		||||
 | 
			
		||||
    An example would be:
 | 
			
		||||
 | 
			
		||||
    Status: tests_failed
 | 
			
		||||
    Enabled checkers: seo
 | 
			
		||||
    Failures from checkers: seo (3)
 | 
			
		||||
    More info: https://monkeytest.it/...
 | 
			
		||||
 | 
			
		||||
    This function assumes that the result dict is valid and does not contain
 | 
			
		||||
    any "errors" like bad url
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing the full report
 | 
			
		||||
    """
 | 
			
		||||
    if "error" in results:
 | 
			
		||||
        return "Error: {}".format(results['error'])
 | 
			
		||||
 | 
			
		||||
    response = ""
 | 
			
		||||
 | 
			
		||||
    response += "{}\n".format(print_status(results))
 | 
			
		||||
 | 
			
		||||
    if "success" in response.lower():
 | 
			
		||||
        response += "{}".format(print_test_id(results))
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
    response += "{}\n".format(print_enabled_checkers(results))
 | 
			
		||||
    response += "{}\n".format(print_failures_checkers(results))
 | 
			
		||||
    response += "{}".format(print_more_info_url(results))
 | 
			
		||||
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_more_info_url(results: Dict) -> Text:
 | 
			
		||||
    """Creates info for the test URL from monkeytest.it
 | 
			
		||||
 | 
			
		||||
    Example:
 | 
			
		||||
 | 
			
		||||
    More info: https://monkeytest.it/test/...
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing the url info
 | 
			
		||||
    """
 | 
			
		||||
    return "More info: {}".format(results['results_url'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_test_id(results: Dict) -> Text:
 | 
			
		||||
    """Prints the test-id with attached to the url
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing the test id
 | 
			
		||||
    """
 | 
			
		||||
    return "Test: https://monkeytest.it/test/{}".format(results['test_id'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_failures_checkers(results: Dict) -> Text:
 | 
			
		||||
    """Creates info for failures in enabled checkers
 | 
			
		||||
 | 
			
		||||
    Example:
 | 
			
		||||
 | 
			
		||||
    Failures from checkers: broken_links (3), seo (5)
 | 
			
		||||
 | 
			
		||||
    This means that the check has 8 section failures, 3 sections in
 | 
			
		||||
    broken_links and the other 5 are in seo.
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing number of failures in each enabled
 | 
			
		||||
             checkers
 | 
			
		||||
    """
 | 
			
		||||
    failures_checkers = [(checker, len(results['failures'][checker]))
 | 
			
		||||
                         for checker in get_enabled_checkers(results)
 | 
			
		||||
                         if checker in results['failures']]  # [('seo', 3), ..]
 | 
			
		||||
 | 
			
		||||
    failures_checkers_messages = ["{} ({})".format(fail_checker[0],
 | 
			
		||||
                                  fail_checker[1]) for fail_checker in
 | 
			
		||||
                                  failures_checkers]
 | 
			
		||||
 | 
			
		||||
    failures_checkers_message = ", ".join(failures_checkers_messages)
 | 
			
		||||
    return "Failures from checkers: {}".format(failures_checkers_message)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_enabled_checkers(results: Dict) -> List:
 | 
			
		||||
    """Gets enabled checkers
 | 
			
		||||
 | 
			
		||||
    For example, if enabled_checkers: {'seo' : True, 'broken_links' : False,
 | 
			
		||||
    'page_weight' : true}, it will return ['seo'. 'page_weight']
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A list containing enabled checkers
 | 
			
		||||
    """
 | 
			
		||||
    checkers = results['enabled_checkers']
 | 
			
		||||
    enabled_checkers = []
 | 
			
		||||
    for checker in checkers.keys():
 | 
			
		||||
        if checkers[checker]:  # == True/False
 | 
			
		||||
            enabled_checkers.append(checker)
 | 
			
		||||
    return enabled_checkers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_enabled_checkers(results: Dict) -> Text:
 | 
			
		||||
    """Creates info for enabled checkers. This joins the list of enabled
 | 
			
		||||
    checkers and format it with the current string response
 | 
			
		||||
 | 
			
		||||
    For example, if get_enabled_checkers = ['seo', 'page_weight'] then it would
 | 
			
		||||
    return "Enabled checkers: seo, page_weight"
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing enabled checkers
 | 
			
		||||
    """
 | 
			
		||||
    return "Enabled checkers: {}".format(", "
 | 
			
		||||
                                         .join(get_enabled_checkers(results)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def print_status(results: Dict) -> Text:
 | 
			
		||||
    """Creates info for the check status.
 | 
			
		||||
 | 
			
		||||
    Example: Status: tests_failed
 | 
			
		||||
 | 
			
		||||
    :param results: A dictionary containing the results of a check
 | 
			
		||||
    :return: A response string containing check status
 | 
			
		||||
    """
 | 
			
		||||
    return "Status: {}".format(results['status'])
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
[monkeytestit]
 | 
			
		||||
api_key = <api key here>
 | 
			
		||||
							
								
								
									
										52
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/monkeytestit.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/monkeytestit.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
import logging
 | 
			
		||||
from typing import Dict, Any
 | 
			
		||||
 | 
			
		||||
from zulip_bots.bots.monkeytestit.lib import parse
 | 
			
		||||
from zulip_bots.lib import NoBotConfigException
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MonkeyTestitBot(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.api_key = "None"
 | 
			
		||||
        self.config = None
 | 
			
		||||
 | 
			
		||||
    def usage(self):
 | 
			
		||||
        return "Remember to set your api_key first in the config. After " \
 | 
			
		||||
               "that, to perform a check, mention me and add the website.\n\n" \
 | 
			
		||||
               "Check doc.md for more options and setup instructions."
 | 
			
		||||
 | 
			
		||||
    def initialize(self, bot_handler: Any) -> None:
 | 
			
		||||
        try:
 | 
			
		||||
            self.config = bot_handler.get_config_info('monkeytestit')
 | 
			
		||||
        except NoBotConfigException:
 | 
			
		||||
            bot_handler.quit("Quitting because there's no config file "
 | 
			
		||||
                             "supplied. See doc.md for a guide on setting up "
 | 
			
		||||
                             "one. If you already know the drill, just create "
 | 
			
		||||
                             "a .conf file with \"monkeytestit\" as the "
 | 
			
		||||
                             "section header and api_key = <your key> for "
 | 
			
		||||
                             "the api key.")
 | 
			
		||||
 | 
			
		||||
        self.api_key = self.config.get('api_key')
 | 
			
		||||
 | 
			
		||||
        if not self.api_key:
 | 
			
		||||
            bot_handler.quit("Config file exists, but can't find api_key key "
 | 
			
		||||
                             "or value. Perhaps it is misconfigured. Check "
 | 
			
		||||
                             "doc.md for details on how to setup the config.")
 | 
			
		||||
 | 
			
		||||
        logging.info("Checking validity of API key. This will take a while.")
 | 
			
		||||
 | 
			
		||||
        if "wrong secret" in parse.execute("check https://website",
 | 
			
		||||
                                           self.api_key).lower():
 | 
			
		||||
            bot_handler.quit("API key exists, but it is not valid. Reconfigure"
 | 
			
		||||
                             " your api_key value and try again.")
 | 
			
		||||
 | 
			
		||||
    def handle_message(self, message: Dict[str, str],
 | 
			
		||||
                       bot_handler: Any) -> None:
 | 
			
		||||
        content = message['content']
 | 
			
		||||
 | 
			
		||||
        response = parse.execute(content, self.api_key)
 | 
			
		||||
 | 
			
		||||
        bot_handler.send_reply(message, response)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
handler_class = MonkeyTestitBot
 | 
			
		||||
							
								
								
									
										46
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/test_monkeytestit.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								zulip_bots/zulip_bots/bots/monkeytestit/test_monkeytestit.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
from unittest import mock
 | 
			
		||||
 | 
			
		||||
import zulip_bots.bots.monkeytestit.monkeytestit
 | 
			
		||||
from zulip_bots.test_lib import BotTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestMonkeyTestitBot(BotTestCase):
 | 
			
		||||
    bot_name = "monkeytestit"
 | 
			
		||||
 | 
			
		||||
    def test_bot_responds_to_empty_message(self):
 | 
			
		||||
        message = dict(
 | 
			
		||||
            content='',
 | 
			
		||||
            type='stream',
 | 
			
		||||
        )
 | 
			
		||||
        with mock.patch.object(
 | 
			
		||||
                zulip_bots.bots.monkeytestit.monkeytestit.MonkeyTestitBot,
 | 
			
		||||
                'initialize', return_value=None):
 | 
			
		||||
            with self.mock_config_info({'api_key': "magic"}):
 | 
			
		||||
                res = self.get_response(message)
 | 
			
		||||
                self.assertTrue("Unknown command" in res['content'])
 | 
			
		||||
 | 
			
		||||
    def test_website_fail(self):
 | 
			
		||||
        message = dict(
 | 
			
		||||
            content='check https://website.com',
 | 
			
		||||
            type='stream',
 | 
			
		||||
        )
 | 
			
		||||
        with mock.patch.object(
 | 
			
		||||
                zulip_bots.bots.monkeytestit.monkeytestit.MonkeyTestitBot,
 | 
			
		||||
                'initialize', return_value=None):
 | 
			
		||||
            with self.mock_config_info({'api_key': "magic"}):
 | 
			
		||||
                with self.mock_http_conversation('website_result_fail'):
 | 
			
		||||
                    res = self.get_response(message)
 | 
			
		||||
                    self.assertTrue("Status: tests_failed" in res['content'])
 | 
			
		||||
 | 
			
		||||
    def test_website_success(self):
 | 
			
		||||
        message = dict(
 | 
			
		||||
            content='check https://website.com',
 | 
			
		||||
            type='stream',
 | 
			
		||||
        )
 | 
			
		||||
        with mock.patch.object(
 | 
			
		||||
                zulip_bots.bots.monkeytestit.monkeytestit.MonkeyTestitBot,
 | 
			
		||||
                'initialize', return_value=None):
 | 
			
		||||
            with self.mock_config_info({'api_key': "magic"}):
 | 
			
		||||
                with self.mock_http_conversation('website_result_success'):
 | 
			
		||||
                    res = self.get_response(message)
 | 
			
		||||
                    self.assertTrue("success" in res['content'])
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue