test_blueprints.py 7.74 KB
Newer Older
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
1
2
import os
import logging
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
3

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
4
from senpy.extensions import Senpy
5
from senpy import models
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
6
from flask import Flask
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
7
from unittest import TestCase
8
from itertools import product
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
9

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
10

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
11
def check_dict(indic, template):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
12
    return all(item in indic.items() for item in template.items())
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
13

J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
14

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
15
def parse_resp(resp):
16
    return models.from_json(resp.data.decode('utf-8'))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
17

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
18
19

class BlueprintsTest(TestCase):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
20
21
22
23
24
    @classmethod
    def setUpClass(cls):
        """Set up only once, and re-use in every individual test"""
        cls.app = Flask("test_extensions")
        cls.client = cls.app.test_client()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
25
        cls.senpy = Senpy(default_plugins=True)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
26
27
28
29
30
31
        cls.senpy.init_app(cls.app)
        cls.dir = os.path.join(os.path.dirname(__file__), "..")
        cls.senpy.add_folder(cls.dir)
        cls.senpy.activate_plugin("Dummy", sync=True)
        cls.senpy.activate_plugin("DummyRequired", sync=True)
        cls.senpy.default_plugin = 'Dummy'
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
32

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
33
34
35
    def setUp(self):
        self.app.config['TESTING'] = True  # Tell Flask not to catch Exceptions

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
36
37
    def assertCode(self, resp, code):
        self.assertEqual(resp.status_code, code)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
38

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
39
40
    def test_playground(self):
        resp = self.client.get("/")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
41
        assert "main.js" in resp.get_data(as_text=True)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
42

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
43
    def test_home(self):
44
45
46
        """
        Calling with no arguments should ask the user for more arguments
        """
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
47
        self.app.config['TESTING'] = False  # Errors are expected in this case
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
48
        resp = self.client.get("/api/")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
49
        self.assertCode(resp, 400)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
50
51
        js = parse_resp(resp)
        logging.debug(js)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
52
        assert js["status"] == 400
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
53
        atleast = {
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
54
            "status": 400,
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
55
56
            "message": "Missing or invalid parameters",
        }
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
57
        assert check_dict(js, atleast)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
58

59
    def test_analysis(self):
60
61
62
63
        """
        The dummy plugin returns an empty response,\
        it should contain the context
        """
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
64
        resp = self.client.get("/api/?i=My aloha mohame&with_parameters=True")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
65
66
67
68
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        logging.debug("Got response: %s", js)
        assert "@context" in js
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
69
        assert "entries" in js
70

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
71
72
    def test_analysis_extra(self):
        """
73
        Extra params that have a default should use it
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
74
        """
75
        resp = self.client.get("/api/?i=My aloha mohame&algo=Dummy&with_parameters=true")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
76
77
78
79
80
81
82
83
84
85
86
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        logging.debug("Got response: %s", js)
        assert "@context" in js
        assert "entries" in js

    def test_analysis_extra_required(self):
        """
        Extra params that have a required argument that does not
        have a default should raise an error.
        """
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
87
        self.app.config['TESTING'] = False  # Errors are expected in this case
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
88
89
90
91
92
        resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired")
        self.assertCode(resp, 400)
        js = parse_resp(resp)
        logging.debug("Got response: %s", js)
        assert isinstance(js, models.Error)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
93
94
95
96
        resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired&example=notvalid")
        self.assertCode(resp, 400)
        resp = self.client.get("/api/?i=My aloha mohame&algo=DummyRequired&example=a")
        self.assertCode(resp, 200)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    def test_analysis_url(self):
        """
        The algorithm can also be specified as part of the URL
        """
        self.app.config['TESTING'] = False  # Errors are expected in this case
        resp = self.client.get("/api/DummyRequired?i=My aloha mohame")
        self.assertCode(resp, 400)
        js = parse_resp(resp)
        logging.debug("Got response: %s", js)
        assert isinstance(js, models.Error)
        resp = self.client.get("/api/DummyRequired?i=My aloha mohame&example=notvalid")
        self.assertCode(resp, 400)
        resp = self.client.get("/api/DummyRequired?i=My aloha mohame&example=a")
        self.assertCode(resp, 200)

    def test_analysis_chain(self):
        """
        More than one algorithm can be specified. Plugins will then be chained
        """
        resp = self.client.get("/api/Dummy?i=My aloha mohame")
        js = parse_resp(resp)
        assert len(js['analysis']) == 1
        assert js['entries'][0]['nif:isString'] == 'My aloha mohame'[::-1]

        resp = self.client.get("/api/Dummy/Dummy?i=My aloha mohame")
        # Calling dummy twice, should return the same string
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        assert len(js['analysis']) == 2
        assert js['entries'][0]['nif:isString'] == 'My aloha mohame'

        resp = self.client.get("/api/Dummy+Dummy?i=My aloha mohame")
        # Same with pluses instead of slashes
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        assert len(js['analysis']) == 2
        assert js['entries'][0]['nif:isString'] == 'My aloha mohame'

136
137
138
139
140
    def test_error(self):
        """
        The dummy plugin returns an empty response,\
        it should contain the context
        """
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
141
        self.app.config['TESTING'] = False  # Errors are expected in this case
142
143
144
145
146
147
        resp = self.client.get("/api/?i=My aloha mohame&algo=DOESNOTEXIST")
        self.assertCode(resp, 404)
        js = parse_resp(resp)
        logging.debug("Got response: %s", js)
        assert isinstance(js, models.Error)

148
149
    def test_list(self):
        """ List the plugins """
Ignacio Corcuera's avatar
Ignacio Corcuera committed
150
        resp = self.client.get("/api/plugins/")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
151
152
153
154
155
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        logging.debug(js)
        assert 'plugins' in js
        plugins = js['plugins']
156
157
        assert len(plugins) > 1
        assert list(p for p in plugins if p['name'] == "Dummy")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
158
        assert "@context" in js
159
160

    def test_headers(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
161
        for i, j in product(["/api/plugins/?nothing=", "/api/?i=test&"],
162
                            ["inHeaders"]):
Ignacio Corcuera's avatar
Ignacio Corcuera committed
163
            resp = self.client.get("%s" % (i))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
164
165
            js = parse_resp(resp)
            assert "@context" in js
Ignacio Corcuera's avatar
Ignacio Corcuera committed
166
            resp = self.client.get("%s&%s=0" % (i, j))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
167
            js = parse_resp(resp)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
168
            assert "@context" in js
Ignacio Corcuera's avatar
Ignacio Corcuera committed
169
            resp = self.client.get("%s&%s=1" % (i, j))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
170
            js = parse_resp(resp)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
171
            assert "@context" not in js
Ignacio Corcuera's avatar
Ignacio Corcuera committed
172
            resp = self.client.get("%s&%s=true" % (i, j))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
173
            js = parse_resp(resp)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
174
            assert "@context" not in js
175
176
177

    def test_detail(self):
        """ Show only one plugin"""
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
178
        resp = self.client.get("/api/plugins/Dummy/")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
179
180
181
182
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        logging.debug(js)
        assert "@id" in js
J. Fernando Sánchez's avatar
WIP    
J. Fernando Sánchez committed
183
        assert js["@id"] == "endpoint:plugins/Dummy_0.1"
184

185
186
    def test_default(self):
        """ Show only one plugin"""
187
        resp = self.client.get("/api/plugins/default/")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
188
189
190
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        logging.debug(js)
J. Fernando Sánchez's avatar
YAPFed    
J. Fernando Sánchez committed
191
        assert "@id" in js
J. Fernando Sánchez's avatar
WIP    
J. Fernando Sánchez committed
192
        assert js["@id"] == "endpoint:plugins/Dummy_0.1"
193
194
195

    def test_context(self):
        resp = self.client.get("/api/contexts/context.jsonld")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
196
197
198
        self.assertCode(resp, 200)
        js = parse_resp(resp)
        assert "@context" in js
199
        assert check_dict(
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
200
            js["@context"],
201
202
203
204
            {"marl": "http://www.gsi.dit.upm.es/ontologies/marl/ns#"})

    def test_schema(self):
        resp = self.client.get("/api/schemas/definitions.json")
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
205
        self.assertCode(resp, 200)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
206
        assert "$schema" in resp.data.decode()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
207
208
209
210
211

    def test_help(self):
        resp = self.client.get("/api/?help=true")
        self.assertCode(resp, 200)
        js = parse_resp(resp)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
212
213
        assert "valid_parameters" in js
        assert "help" in js["valid_parameters"]
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
214
215

    def test_conversion(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
216
        self.app.config['TESTING'] = False  # Errors are expected in this case
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
217
218
        resp = self.client.get("/api/?input=hello&algo=emoRand&emotionModel=DOES NOT EXIST")
        self.assertCode(resp, 404)