• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

funilrys / PyFunceble / 17046250819

18 Aug 2025 04:12PM UTC coverage: 96.648% (+1.9%) from 94.721%
17046250819

push

github

funilrys
Bump verstion to v4.3.0

1 of 1 new or added line in 1 file covered. (100.0%)

154 existing lines in 14 files now uncovered.

11967 of 12382 relevant lines covered (96.65%)

8.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.19
/tests/query/test_platform.py
1
"""
2
The tool to check the availability or syntax of domain, IP or URL.
3

4
::
5

6

7
    ██████╗ ██╗   ██╗███████╗██╗   ██╗███╗   ██╗ ██████╗███████╗██████╗ ██╗     ███████╗
8
    ██╔══██╗╚██╗ ██╔╝██╔════╝██║   ██║████╗  ██║██╔════╝██╔════╝██╔══██╗██║     ██╔════╝
9
    ██████╔╝ ╚████╔╝ █████╗  ██║   ██║██╔██╗ ██║██║     █████╗  ██████╔╝██║     █████╗
10
    ██╔═══╝   ╚██╔╝  ██╔══╝  ██║   ██║██║╚██╗██║██║     ██╔══╝  ██╔══██╗██║     ██╔══╝
11
    ██║        ██║   ██║     ╚██████╔╝██║ ╚████║╚██████╗███████╗██████╔╝███████╗███████╗
12
    ╚═╝        ╚═╝   ╚═╝      ╚═════╝ ╚═╝  ╚═══╝ ╚═════╝╚══════╝╚═════╝ ╚══════╝╚══════╝
13

14
Tests of the Platform query tool.
15

16
Author:
17
    Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom
18

19
Special thanks:
20
    https://pyfunceble.github.io/special-thanks.html
21

22
Contributors:
23
    https://pyfunceble.github.io/contributors.html
24

25
Project link:
26
    https://github.com/funilrys/PyFunceble
27

28
Project documentation:
29
    https://docs.pyfunceble.com
30

31
Project homepage:
32
    https://pyfunceble.github.io/
33

34
License:
35
::
36

37

38
    Copyright 2017, 2018, 2019, 2020, 2022, 2023, 2024, 2025 Nissar Chababy
39

40
    Licensed under the Apache License, Version 2.0 (the "License");
41
    you may not use this file except in compliance with the License.
42
    You may obtain a copy of the License at
43

44
        https://www.apache.org/licenses/LICENSE-2.0
45

46
    Unless required by applicable law or agreed to in writing, software
47
    distributed under the License is distributed on an "AS IS" BASIS,
48
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49
    See the License for the specific language governing permissions and
50
    limitations under the License.
51
"""
52

53
# pylint: disable=too-many-lines
54

55
import json
9✔
56
import os
9✔
57
import secrets
9✔
58
import unittest
9✔
59
import unittest.mock
9✔
60
from datetime import datetime, timezone
9✔
61

62
import requests
9✔
63
import requests.models
9✔
64

65
from PyFunceble.checker.availability.status import AvailabilityCheckerStatus
9✔
66
from PyFunceble.config.loader import ConfigLoader
9✔
67
from PyFunceble.query.platform import PlatformQueryTool
9✔
68

69

70
class TestPlatformQueryTool(unittest.TestCase):
9✔
71
    """
72
    Tests the Platform query tool.
73
    """
74

75
    def setUp(self) -> None:
9✔
76
        """
77
        Sets everything needed by the tests.
78
        """
79

80
        self.query_tool = PlatformQueryTool()
9✔
81

82
        self.response_dataset = {
9✔
83
            "subject": "example.net",
84
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
85
            "status": {
86
                "syntax": {
87
                    "latest": {
88
                        "status": "VALID",
89
                        "status_source": "SYNTAX",
90
                        "tested_at": "2021-09-28T19:32:07.167Z",
91
                        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
92
                    },
93
                    "frequent": "VALID",
94
                },
95
                "availability": {
96
                    "latest": {
97
                        "status": "ACTIVE",
98
                        "status_source": "WHOIS",
99
                        "tested_at": "2021-09-28T19:32:07.167Z",
100
                        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
101
                    },
102
                    "frequent": "ACTIVE",
103
                },
104
                "reputation": {
105
                    "latest": {
106
                        "status": "SANE",
107
                        "status_source": "REPUTATION",
108
                        "tested_at": "2021-09-28T19:32:07.167Z",
109
                        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
110
                    },
111
                    "frequent": "SANE",
112
                },
113
                "whois": {
114
                    "expiration_date": "2021-09-28T19:32:07.167Z",
115
                    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
116
                    "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
117
                },
118
            },
119
        }
120

121
        self.status_dataset = {
9✔
122
            "status": "ACTIVE",
123
            "status_source": "WHOIS",
124
            "tested_at": "2021-09-28T20:55:41.730Z",
125
            "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
126
            "subject_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
127
        }
128

129
        self.availability_status_dataset = {
9✔
130
            "checker_type": "AVAILABILITY",
131
            "dns_lookup": {"NS": ["a.iana-servers.net.", "b.iana-servers.net."]},
132
            "dns_lookup_record": {
133
                "dns_name": "example.com.",
134
                "follow_nameserver_order": True,
135
                "nameserver": "9.9.9.9",
136
                "port": 53,
137
                "preferred_protocol": "UDP",
138
                "query_record_type": "NS",
139
                "query_timeout": 5.0,
140
                "response": ["a.iana-servers.net.", "b.iana-servers.net."],
141
                "subject": "example.com",
142
                "used_protocol": "UDP",
143
            },
144
            "domain_syntax": True,
145
            "expiration_date": None,
146
            "http_status_code": None,
147
            "idna_subject": "example.com",
148
            "ip_syntax": False,
149
            "ipv4_range_syntax": False,
150
            "ipv4_syntax": False,
151
            "ipv6_range_syntax": False,
152
            "ipv6_syntax": False,
153
            "netinfo": None,
154
            "params": {
155
                "do_syntax_check_first": False,
156
                "use_dns_lookup": True,
157
                "use_extra_rules": True,
158
                "use_http_code_lookup": True,
159
                "use_netinfo_lookup": True,
160
                "use_reputation_lookup": False,
161
                "use_whois_db": True,
162
                "use_whois_lookup": False,
163
            },
164
            "second_level_domain_syntax": True,
165
            "status": "ACTIVE",
166
            "status_after_extra_rules": None,
167
            "status_before_extra_rules": None,
168
            "status_source": "DNSLOOKUP",
169
            "status_source_after_extra_rules": None,
170
            "status_source_before_extra_rules": None,
171
            "subdomain_syntax": False,
172
            "subject": "example.com",
173
            "tested_at": datetime.fromisoformat(
174
                "2021-03-09T17:42:15.771647"
175
            ).astimezone(timezone.utc),
176
            "url_syntax": False,
177
            "whois_lookup_record": {
178
                "expiration_date": None,
179
                "port": 43,
180
                "query_timeout": 5.0,
181
                "record": None,
182
                "server": None,
183
                "subject": "example.com",
184
            },
185
            "whois_record": None,
186
        }
187
        return super().setUp()
9✔
188

189
    def tearDown(self) -> None:
9✔
190
        """
191
        Destroys everything needed by the tests.
192
        """
193

194
        del self.query_tool
9✔
195
        del self.response_dataset
9✔
196
        del self.availability_status_dataset
9✔
197

198
    def test_set_token_return(self) -> None:
9✔
199
        """
200
        Tests the response from the method which let us set the token to work
201
        with.
202
        """
203

204
        given = secrets.token_urlsafe(6)
9✔
205

206
        actual = self.query_tool.set_token(given)
9✔
207

208
        self.assertIsInstance(actual, PlatformQueryTool)
9✔
209

210
    def test_set_token_method(self) -> None:
9✔
211
        """
212
        Tests the method which let us set the token to work with.
213
        """
214

215
        given = secrets.token_urlsafe(6)
9✔
216
        expected = given
9✔
217

218
        self.query_tool.set_token(given)
9✔
219
        actual = self.query_tool.token
9✔
220

221
        self.assertEqual(expected, actual)
9✔
222

223
    def test_set_token_attribute(self) -> None:
9✔
224
        """
225
        Tests the overwritting of the token attribute.
226
        """
227

228
        given = secrets.token_urlsafe(6)
9✔
229
        expected = given
9✔
230

231
        self.query_tool.token = given
9✔
232
        actual = self.query_tool.token
9✔
233

234
        self.assertEqual(expected, actual)
9✔
235

236
    def test_set_token_through_init(self) -> None:
9✔
237
        """
238
        Tests the overwritting of the token to work through the class
239
        constructor.
240
        """
241

242
        given = secrets.token_urlsafe(6)
9✔
243
        expected = given
9✔
244

245
        query_tool = PlatformQueryTool(token=given)
9✔
246
        actual = query_tool.token
9✔
247

248
        self.assertEqual(expected, actual)
9✔
249

250
    def test_set_token_through_init_environment_variable_not_given(self) -> None:
9✔
251
        """
252
        Tests the overwritting of the token to work through the class
253
        constructor.
254

255
        In this test we test the case that nothing is given or declared.
256
        """
257

258
        if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ:  # pragma: no cover
259
            del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"]
260

261
        if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ:  # pragma: no cover
262
            del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"]
263

264
        expected = ""
9✔
265

266
        query_tool = PlatformQueryTool(token=None)
9✔
267
        actual = query_tool.token
9✔
268

269
        self.assertEqual(expected, actual)
9✔
270

271
    def test_set_token_through_init_environment_variable_given(self) -> None:
9✔
272
        """
273
        Tests the overwritting of the token to work through the class
274
        constructor.
275

276
        In this test we test the case that the environment variable is given.
277
        """
278

279
        given = secrets.token_urlsafe(6)
9✔
280
        expected = given
9✔
281

282
        if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ:
9✔
UNCOV
283
            del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"]
×
284

285
        os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"] = given
9✔
286

287
        query_tool = PlatformQueryTool(token=None)
9✔
288
        actual = query_tool.token
9✔
289

290
        self.assertEqual(expected, actual)
9✔
291

292
    def test_set_token_not_str(self) -> None:
9✔
293
        """
294
        Tests the method which let us set the token to work with for the case
295
        that the given token is not a :py:class:`str`.
296
        """
297

298
        given = ["Hello", "World!"]
9✔
299

300
        self.assertRaises(TypeError, lambda: self.query_tool.set_token(given))
9✔
301

302
    def test_set_url_base_not_str(self) -> None:
9✔
303
        """
304
        Tests the method which let us set the URL to work from for the case
305
        that the given URL is not a :py:class:`str`.
306
        """
307

308
        given = ["Hello", "World!"]
9✔
309

310
        self.assertRaises(TypeError, lambda: self.query_tool.set_url_base(given))
9✔
311

312
    def test_set_url_base_not_url(self) -> None:
9✔
313
        """
314
        Tests the method which let us set the URL to work from for the case
315
        that the given URL is not a supported URL.
316
        """
317

318
        given = "example.org"
9✔
319

320
        self.assertRaises(ValueError, lambda: self.query_tool.set_url_base(given))
9✔
321

322
    def test_set_url_base_ends_with_slash(self) -> None:
9✔
323
        """
324
        Tests the method which let us set the URL to work from for the case
325
        that the given URL is not a supported URL.
326
        """
327

328
        given = "http://example.org/"
9✔
329
        expected = "http://example.org"
9✔
330

331
        self.query_tool.url_base = given
9✔
332
        actual = self.query_tool.url_base
9✔
333

334
        self.assertEqual(expected, actual)
9✔
335

336
    def test_set_preferred_status_origin_return(self) -> None:
9✔
337
        """
338
        Tests the response from the method which let us set the preferred status
339
        origin.
340
        """
341

342
        given = "latest"
9✔
343

344
        actual = self.query_tool.set_preferred_status_origin(given)
9✔
345

346
        self.assertIsInstance(actual, PlatformQueryTool)
9✔
347

348
    def test_set_preferred_status_origin_method(self) -> None:
9✔
349
        """
350
        Tests the method which let us set the preferred status origin.
351
        """
352

353
        given = "frequent"
9✔
354
        expected = given
9✔
355

356
        self.query_tool.set_preferred_status_origin(given)
9✔
357
        actual = self.query_tool.preferred_status_origin
9✔
358

359
        self.assertEqual(expected, actual)
9✔
360

361
    def test_set_preferred_status_origin_attribute(self) -> None:
9✔
362
        """
363
        Tests the overwritting of the the preferred status origin.
364
        """
365

366
        given = "latest"
9✔
367
        expected = given
9✔
368

369
        self.query_tool.preferred_status_origin = given
9✔
370
        actual = self.query_tool.preferred_status_origin
9✔
371

372
        self.assertEqual(expected, actual)
9✔
373

374
    def test_setpreferred_status_origin_through_init(self) -> None:
9✔
375
        """
376
        Tests the overwritting of the preferred status origin through the class
377
        constructor.
378
        """
379

380
        given = "frequent"
9✔
381
        expected = given
9✔
382

383
        query_tool = PlatformQueryTool(preferred_status_origin=given)
9✔
384
        actual = query_tool.preferred_status_origin
9✔
385

386
        self.assertEqual(expected, actual)
9✔
387

388
    def test_set_preferred_status_origin_through_init_none_given(self) -> None:
9✔
389
        """
390
        Tests the overwritting of the preferred status origin through the class
391
        constructor.
392

393
        In this test, we test the case that nothing is given.
394
        """
395

396
        given = None
9✔
397
        expected = "frequent"
9✔
398

399
        query_tool = PlatformQueryTool(preferred_status_origin=given)
9✔
400
        actual = query_tool.preferred_status_origin
9✔
401

402
        self.assertEqual(expected, actual)
9✔
403

404
    def test_set_preferred_status_origin_not_str(self) -> None:
9✔
405
        """
406
        Tests the method which let us set the preferred status origin for the case
407
        that the given value is not a :py:class:`str`.
408
        """
409

410
        given = ["Hello", "World!"]
9✔
411

412
        self.assertRaises(
9✔
413
            TypeError, lambda: self.query_tool.set_preferred_status_origin(given)
414
        )
415

416
    def test_set_preferred_status_origin_not_supported(self) -> None:
9✔
417
        """
418
        Tests the method which let us set the URL to work from for the case
419
        that the given URL is not a supported URL.
420
        """
421

422
        given = "hello"
9✔
423

424
        self.assertRaises(
9✔
425
            ValueError, lambda: self.query_tool.set_preferred_status_origin(given)
426
        )
427

428
    def test_guess_and_set_preferred_status_origin(self) -> None:
9✔
429
        """
430
        Tests the method which let us guess and set the preferred status origin.
431
        """
432

433
        config_loader = ConfigLoader()
9✔
434
        config_loader.set_custom_config(
9✔
435
            {"platform": {"preferred_status_origin": "latest"}}
436
        ).start()
437

438
        self.query_tool.guess_and_set_preferred_status_origin()
9✔
439

440
        expected = "latest"
9✔
441
        actual = self.query_tool.preferred_status_origin
9✔
442

443
        self.assertEqual(expected, actual)
9✔
444

445
        del config_loader
9✔
446

447
    def test_guess_and_set_preferred_status_origin_not_str(self) -> None:
9✔
448
        """
449
        Tests the method which let us guess and set the preferred status origin.
450
        """
451

452
        config_loader = ConfigLoader()
9✔
453
        config_loader.set_custom_config(
9✔
454
            {"platform": {"preferred_status_origin": None}}
455
        ).start()
456

457
        self.query_tool.guess_and_set_preferred_status_origin()
9✔
458

459
        expected = "frequent"
9✔
460
        actual = self.query_tool.preferred_status_origin
9✔
461

462
        self.assertEqual(expected, actual)
9✔
463

464
        del config_loader
9✔
465

466
    def test_set_checker_priority_return(self) -> None:
9✔
467
        """
468
        Tests the response from the method which let us set the checker priority
469
        to use.
470
        """
471

472
        given = ["reputation", "syntax", "availability"]
9✔
473

474
        actual = self.query_tool.set_checker_priority(given)
9✔
475

476
        self.assertIsInstance(actual, PlatformQueryTool)
9✔
477

478
    def test_set_checker_priority_method(self) -> None:
9✔
479
        """
480
        Tests the method which let us set the checker priority to use.
481
        """
482

483
        given = ["availability", "syntax", "reputation"]
9✔
484
        expected = given
9✔
485

486
        self.query_tool.set_checker_priority(given)
9✔
487
        actual = self.query_tool.checker_priority
9✔
488

489
        self.assertEqual(expected, actual)
9✔
490

491
    def test_set_checker_priority_attribute(self) -> None:
9✔
492
        """
493
        Tests the overwritting of the the checker priority.
494
        """
495

496
        given = ["syntax", "availability", "reputation"]
9✔
497
        expected = given
9✔
498

499
        self.query_tool.checker_priority = given
9✔
500
        actual = self.query_tool.checker_priority
9✔
501

502
        self.assertEqual(expected, actual)
9✔
503

504
    def test_checker_priority_through_init(self) -> None:
9✔
505
        """
506
        Tests the overwritting of the checker priority through the class
507
        constructor.
508
        """
509

510
        given = ["reputation", "syntax", "availability"]
9✔
511
        expected = given
9✔
512

513
        query_tool = PlatformQueryTool(checker_priority=given)
9✔
514
        actual = query_tool.checker_priority
9✔
515

516
        self.assertEqual(expected, actual)
9✔
517

518
    def test_set_checker_priority_init_none_given(self) -> None:
9✔
519
        """
520
        Tests the overwritting of the checker through the class
521
        constructor.
522

523
        In this test, we test the case that nothing is given.
524
        """
525

526
        given = None
9✔
527
        expected = ["none"]
9✔
528

529
        query_tool = PlatformQueryTool(checker_priority=given)
9✔
530
        actual = query_tool.checker_priority
9✔
531

532
        self.assertEqual(expected, actual)
9✔
533

534
    def test_set_checker_priority_not_str(self) -> None:
9✔
535
        """
536
        Tests the method which let us set the checker priority for the case
537
        that a given value is not a :py:class:`str`.
538
        """
539

540
        given = ["reputation", "syntax", 123]
9✔
541

542
        self.assertRaises(
9✔
543
            TypeError, lambda: self.query_tool.set_checker_priority(given)
544
        )
545

546
    def test_set_checker_priority_not_supported(self) -> None:
9✔
547
        """
548
        Tests the method which let us set the checker priority to work from
549
        for the case that the given checker is not supported.
550
        """
551

552
        given = ["reputation", "syntax", "hello"]
9✔
553

554
        self.assertRaises(
9✔
555
            ValueError, lambda: self.query_tool.set_checker_priority(given)
556
        )
557

558
    def test_guess_and_set_checker_priority(self) -> None:
9✔
559
        """
560
        Tests the method which let us guess and set the checker type.
561
        """
562

563
        config_loader = ConfigLoader()
9✔
564
        config_loader.set_custom_config(
9✔
565
            {"platform": {"checker_priority": ["reputation", "syntax", "availability"]}}
566
        ).start()
567

568
        self.query_tool.guess_and_set_checker_priority()
9✔
569

570
        expected = ["reputation", "syntax", "availability"]
9✔
571
        actual = self.query_tool.checker_priority
9✔
572

573
        self.assertEqual(expected, actual)
9✔
574

575
        del config_loader
9✔
576

577
    def test_guess_and_set_checker_priority_not_str(self) -> None:
9✔
578
        """
579
        Tests the method which let us guess and set the checker priority.
580
        """
581

582
        config_loader = ConfigLoader()
9✔
583
        config_loader.set_custom_config(
9✔
584
            {"platform": {"checker_priority": None}}
585
        ).start()
586

587
        self.query_tool.guess_and_set_checker_priority()
9✔
588

589
        expected = ["none"]
9✔
590
        actual = self.query_tool.checker_priority
9✔
591

592
        self.assertEqual(expected, actual)
9✔
593

594
        del config_loader
9✔
595

596
    def test_set_checker_exclude_return(self) -> None:
9✔
597
        """
598
        Tests the response from the method which let us set the checker to
599
        exclude.
600
        """
601

602
        given = ["reputation", "syntax", "availability"]
9✔
603

604
        actual = self.query_tool.set_checker_exclude(given)
9✔
605

606
        self.assertIsInstance(actual, PlatformQueryTool)
9✔
607

608
    def test_set_checker_exclude_method(self) -> None:
9✔
609
        """
610
        Tests the method which let us set the checker to exclude.
611
        """
612

613
        given = ["availability", "syntax", "reputation"]
9✔
614
        expected = given
9✔
615

616
        self.query_tool.set_checker_exclude(given)
9✔
617
        actual = self.query_tool.checker_exclude
9✔
618

619
        self.assertEqual(expected, actual)
9✔
620

621
    def test_set_checker_exclude_attribute(self) -> None:
9✔
622
        """
623
        Tests the overwritting of the checker exclude to use.
624
        """
625

626
        given = ["syntax", "availability", "reputation"]
9✔
627
        expected = given
9✔
628

629
        self.query_tool.checker_exclude = given
9✔
630
        actual = self.query_tool.checker_exclude
9✔
631

632
        self.assertEqual(expected, actual)
9✔
633

634
    def test_checker_exclude_through_init(self) -> None:
9✔
635
        """
636
        Tests the overwritting of the checker to exclude through the class
637
        constructor.
638
        """
639

640
        given = ["reputation", "syntax", "availability"]
9✔
641
        expected = given
9✔
642

643
        query_tool = PlatformQueryTool(checker_exclude=given)
9✔
644
        actual = query_tool.checker_exclude
9✔
645

646
        self.assertEqual(expected, actual)
9✔
647

648
    def test_set_checker_exclude_init_none_given(self) -> None:
9✔
649
        """
650
        Tests the overwritting of the checker through the class
651
        constructor.
652

653
        In this test, we test the case that nothing is given.
654
        """
655

656
        given = None
9✔
657
        expected = ["none"]
9✔
658

659
        query_tool = PlatformQueryTool(checker_exclude=given)
9✔
660
        actual = query_tool.checker_exclude
9✔
661

662
        self.assertEqual(expected, actual)
9✔
663

664
    def test_set_checker_exclude_not_str(self) -> None:
9✔
665
        """
666
        Tests the method which let us set the checker exclude for the case
667
        that a given value is not a :py:class:`str`.
668
        """
669

670
        given = ["reputation", "syntax", 123]
9✔
671

672
        self.assertRaises(TypeError, lambda: self.query_tool.set_checker_exclude(given))
9✔
673

674
    def test_set_checker_exclude_not_supported(self) -> None:
9✔
675
        """
676
        Tests the method which let us set the checker exclude to work with
677
        for the case that the given checker is not supported.
678
        """
679

680
        given = ["syntax", "reputation", "hello"]
9✔
681

682
        self.assertRaises(
9✔
683
            ValueError, lambda: self.query_tool.set_checker_exclude(given)
684
        )
685

686
    def test_guess_and_set_checker_exclude(self) -> None:
9✔
687
        """
688
        Tests the method which let us guess and set the checker type to exclude.
689
        """
690

691
        config_loader = ConfigLoader()
9✔
692
        config_loader.set_custom_config(
9✔
693
            {"platform": {"checker_exclude": ["syntax", "reputation", "availability"]}}
694
        ).start()
695

696
        self.query_tool.guess_and_set_checker_exclude()
9✔
697

698
        expected = ["syntax", "reputation", "availability"]
9✔
699
        actual = self.query_tool.checker_exclude
9✔
700

701
        self.assertEqual(expected, actual)
9✔
702

703
        del config_loader
9✔
704

705
    def test_guess_and_set_checker_exclude_not_str(self) -> None:
9✔
706
        """
707
        Tests the method which let us guess and set the checker to exclude.
708
        """
709

710
        config_loader = ConfigLoader()
9✔
711
        config_loader.set_custom_config({"platform": {"checker_exclude": None}}).start()
9✔
712

713
        self.query_tool.guess_and_set_checker_exclude()
9✔
714

715
        expected = ["none"]
9✔
716
        actual = self.query_tool.checker_exclude
9✔
717

718
        self.assertEqual(expected, actual)
9✔
719

720
        del config_loader
9✔
721

722
    @unittest.mock.patch.object(requests.Session, "post")
9✔
723
    def test_platform_contain(self, request_mock) -> None:
9✔
724
        """
725
        Tests the method which let us pull the subject from the platform.
726
        """
727

728
        response_dict = self.response_dataset
9✔
729
        response_dict["subject"] = "example.com"
9✔
730

731
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
732
            response_content = json.dumps(response_dict)
9✔
733

734
            response = requests.models.Response()
9✔
735
            response.url = "https://example.org/v1/search"
9✔
736
            response.status_code = 200
9✔
737

738
            # pylint: disable=protected-access
739
            response._content = str.encode(response_content)
9✔
740

741
            response.history = [response]
9✔
742

743
            return response
9✔
744

745
        self.query_tool.url_base = "https://example.org"
9✔
746
        request_mock.side_effect = mocking
9✔
747

748
        expected = True
9✔
749
        actual = "example.com" in self.query_tool
9✔
750

751
        self.assertEqual(expected, actual)
9✔
752

753
    @unittest.mock.patch.object(requests.Session, "post")
9✔
754
    def test_platform_not_contain(self, request_mock) -> None:
9✔
755
        """
756
        Tests the method which let us pull the subject from the platform.
757
        """
758

759
        response_dict = {"detail": "Invalid subject."}
9✔
760

761
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
762
            response_content = json.dumps(response_dict)
9✔
763

764
            response = requests.models.Response()
9✔
765
            response.url = "https://example.org/v1/search"
9✔
766
            response.status_code = 404
9✔
767

768
            # pylint: disable=protected-access
769
            response._content = str.encode(response_content)
9✔
770

771
            response.history = [response]
9✔
772

773
            return response
9✔
774

775
        self.query_tool.url_base = "https://example.org"
9✔
776
        request_mock.side_effect = mocking
9✔
777

778
        expected = False
9✔
779
        actual = "example.com" in self.query_tool
9✔
780

781
        self.assertEqual(expected, actual)
9✔
782

783
    @unittest.mock.patch.object(requests.Session, "post")
9✔
784
    def test_getitem(self, request_mock) -> None:
9✔
785
        """
786
        Tests the method which let us pull the subject from the platform.
787
        """
788

789
        response_dict = self.response_dataset
9✔
790
        response_dict["subject"] = "example.org"
9✔
791

792
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
793
            response_content = json.dumps(response_dict)
9✔
794

795
            response = requests.models.Response()
9✔
796
            response.url = "https://example.org/v1/search"
9✔
797
            response.status_code = 200
9✔
798

799
            # pylint: disable=protected-access
800
            response._content = str.encode(response_content)
9✔
801

802
            response.history = [response]
9✔
803

804
            return response
9✔
805

806
        self.query_tool.url_base = "https://example.org"
9✔
807
        request_mock.side_effect = mocking
9✔
808

809
        expected = response_dict
9✔
810
        actual = self.query_tool["example.org"]
9✔
811

812
        self.assertEqual(expected, actual)
9✔
813

814
    @unittest.mock.patch.object(requests.Session, "post")
9✔
815
    def test_getitem_not_found(self, request_mock) -> None:
9✔
816
        """
817
        Tests the method which let us pull the subject from the platform.
818
        """
819

820
        response_dict = {"detail": "Invalid subject."}
9✔
821

822
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
823
            response_content = json.dumps(response_dict)
9✔
824

825
            response = requests.models.Response()
9✔
826
            response.url = "https://example.org/v1/search"
9✔
827
            response.status_code = 404
9✔
828

829
            # pylint: disable=protected-access
830
            response._content = str.encode(response_content)
9✔
831

832
            response.history = [response]
9✔
833

834
            return response
9✔
835

836
        self.query_tool.url_base = "https://example.org"
9✔
837
        request_mock.side_effect = mocking
9✔
838

839
        expected = None
9✔
840
        actual = self.query_tool["example.de"]
9✔
841

842
        self.assertEqual(expected, actual)
9✔
843

844
    @unittest.mock.patch.object(requests.Session, "post")
9✔
845
    def test_pull(self, request_mock) -> None:
9✔
846
        """
847
        Tests the method which let us pull the subject from the platform.
848
        """
849

850
        response_dict = self.response_dataset
9✔
851
        response_dict["subject"] = "example.net"
9✔
852

853
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
854
            response_content = json.dumps(response_dict)
9✔
855

856
            response = requests.models.Response()
9✔
857
            response.url = "https://example.org/v1/search"
9✔
858
            response.status_code = 200
9✔
859

860
            # pylint: disable=protected-access
861
            response._content = str.encode(response_content)
9✔
862

863
            response.history = [response]
9✔
864

865
            return response
9✔
866

867
        self.query_tool.url_base = "https://example.org"
9✔
868
        request_mock.side_effect = mocking
9✔
869

870
        expected = response_dict
9✔
871
        actual = self.query_tool.pull("example.net")
9✔
872

873
        self.assertEqual(expected, actual)
9✔
874

875
    @unittest.mock.patch.object(requests.Session, "post")
9✔
876
    def test_pull_subject_not_found(self, request_mock) -> None:
9✔
877
        """
878
        Tests the method which let us pull the subject from the platform.
879

880
        In this test case we check what happens when a subject is not found.
881
        """
882

883
        response_dict = {"detail": "Invalid subject."}
9✔
884

885
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
886
            response_content = json.dumps(response_dict)
9✔
887

888
            response = requests.models.Response()
9✔
889
            response.url = "https://example.org/v1/search"
9✔
890
            response.status_code = 404
9✔
891

892
            # pylint: disable=protected-access
893
            response._content = str.encode(response_content)
9✔
894

895
            response.history = [response]
9✔
896

897
            return response
9✔
898

899
        self.query_tool.url_base = "https://example.org"
9✔
900
        request_mock.side_effect = mocking
9✔
901

902
        expected = None
9✔
903
        actual = self.query_tool.pull("example.net")
9✔
904

905
        self.assertEqual(expected, actual)
9✔
906

907
    @unittest.mock.patch.object(requests.Session, "post")
9✔
908
    def test_pull_subject_no_json_response(self, request_mock) -> None:
9✔
909
        """
910
        Tests the method which let us pull the subject from the platform.
911

912
        In this test case we check what happens when no JSON response is given.
913
        """
914

915
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
916
            response_content = "I'm a teapot."
9✔
917

918
            response = requests.models.Response()
9✔
919
            response.url = "https://example.org/v1/search"
9✔
920
            response.status_code = 418
9✔
921

922
            # pylint: disable=protected-access
923
            response._content = str.encode(response_content)
9✔
924

925
            response.history = [response]
9✔
926

927
            return response
9✔
928

929
        self.query_tool.url_base = "https://example.org"
9✔
930
        request_mock.side_effect = mocking
9✔
931

932
        expected = None
9✔
933
        actual = self.query_tool.pull("example.net")
9✔
934

935
        self.assertEqual(expected, actual)
9✔
936

937
    def test_pull_subject_not_str(self) -> None:
9✔
938
        """
939
        Tests the method which let us pull the subject from the platform.
940

941
        In this test we test the case that the given subject is not a
942
        :py:class:`str`.
943
        """
944

945
        self.query_tool.url_base = "https://example.org"
9✔
946

947
        self.assertRaises(TypeError, lambda: self.query_tool.pull(284))
9✔
948

949
    @unittest.mock.patch.object(requests.Session, "post")
9✔
950
    def test_push(self, request_mock) -> None:
9✔
951
        """
952
        Tests the method which let us push some dataset into the platform.
953
        """
954

955
        response_dict = self.response_dataset
9✔
956
        response_dict["subject"] = "example.net"
9✔
957

958
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
959
            response_content = json.dumps(response_dict)
9✔
960

961
            response = requests.models.Response()
9✔
962
            response.url = "https://example.org/v1/status/availability"
9✔
963
            response.status_code = 200
9✔
964

965
            # pylint: disable=protected-access
966
            response._content = str.encode(response_content)
9✔
967

968
            response.history = [response]
9✔
969

970
            return response
9✔
971

972
        self.query_tool.url_base = "https://example.org"
9✔
973
        self.query_tool.token = secrets.token_urlsafe(6)
9✔
974

975
        request_mock.side_effect = mocking
9✔
976

977
        expected = response_dict
9✔
978
        actual = self.query_tool.push(
9✔
979
            AvailabilityCheckerStatus(**self.availability_status_dataset)
980
        )
981

982
        self.assertEqual(expected, actual)
9✔
983

984
    @unittest.mock.patch.object(requests.Session, "post")
9✔
985
    def test_push_no_json_response(self, request_mock) -> None:
9✔
986
        """
987
        Tests the method which let us push some dataset into the platform.
988

989
        In this test case, we test the case that the response is not JSON
990
        encoded.
991
        """
992

993
        response_dict = self.response_dataset
9✔
994
        response_dict["subject"] = "example.net"
9✔
995

996
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
997
            response_content = "I'm a teapot."
×
998

999
            response = requests.models.Response()
×
UNCOV
1000
            response.url = "https://example.org/v1/status/availability"
×
UNCOV
1001
            response.status_code = 418
×
1002

1003
            # pylint: disable=protected-access
1004
            response._content = str.encode(response_content)
×
1005

1006
            response.history = [response]
×
1007

UNCOV
1008
            return response
×
1009

1010
        self.query_tool.url_base = "https://example.org"
9✔
1011
        request_mock.side_effect = mocking
9✔
1012

1013
        expected = None
9✔
1014
        actual = self.query_tool.push(
9✔
1015
            AvailabilityCheckerStatus(**self.availability_status_dataset)
1016
        )
1017

1018
        self.assertEqual(expected, actual)
9✔
1019

1020
    @unittest.mock.patch.object(requests.Session, "post")
9✔
1021
    def test_push_with_whois(self, request_mock) -> None:
9✔
1022
        """
1023
        Tests the method which let us push some dataset into the platform.
1024
        """
1025

1026
        response_dict = self.response_dataset
9✔
1027
        response_dict["subject"] = "example.net"
9✔
1028
        self.availability_status_dataset["expiration_date"] = "23-nov-2090"
9✔
1029

1030
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
1031
            response_content = json.dumps(response_dict)
9✔
1032

1033
            response = requests.models.Response()
9✔
1034
            response.url = "https://example.org/v1/status/availability"
9✔
1035
            response.status_code = 200
9✔
1036

1037
            # pylint: disable=protected-access
1038
            response._content = str.encode(response_content)
9✔
1039

1040
            response.history = [response]
9✔
1041

1042
            return response
9✔
1043

1044
        self.query_tool.url_base = "https://example.org"
9✔
1045
        self.query_tool.token = secrets.token_urlsafe(6)
9✔
1046
        request_mock.side_effect = mocking
9✔
1047

1048
        expected = response_dict
9✔
1049
        actual = self.query_tool.push(
9✔
1050
            AvailabilityCheckerStatus(**self.availability_status_dataset)
1051
        )
1052

1053
        self.assertEqual(expected, actual)
9✔
1054

1055
    @unittest.mock.patch.object(requests.Session, "post")
9✔
1056
    def test_push_with_whois_no_json_response(self, request_mock) -> None:
9✔
1057
        """
1058
        Tests the method which let us push some dataset into the platform.
1059
        """
1060

1061
        response_dict = self.response_dataset
9✔
1062
        response_dict["subject"] = "example.net"
9✔
1063
        self.availability_status_dataset["expiration_date"] = "23-nov-2090"
9✔
1064

1065
        def mocking(*args, **kwargs):  # pylint: disable=unused-argument
9✔
1066
            response_content = "I'm a teapot."
9✔
1067

1068
            response = requests.models.Response()
9✔
1069
            response.url = "https://example.org/v1/status/availability"
9✔
1070
            response.status_code = 418
9✔
1071

1072
            # pylint: disable=protected-access
1073
            response._content = str.encode(response_content)
9✔
1074

1075
            response.history = [response]
9✔
1076

1077
            return response
9✔
1078

1079
        self.query_tool.url_base = "https://example.org"
9✔
1080
        self.query_tool.token = secrets.token_urlsafe(6)
9✔
1081
        request_mock.side_effect = mocking
9✔
1082

1083
        expected = None
9✔
1084
        actual = self.query_tool.push(
9✔
1085
            AvailabilityCheckerStatus(**self.availability_status_dataset)
1086
        )
1087

1088
        self.assertEqual(expected, actual)
9✔
1089

1090
    def test_push_with_whois_token_not_given(self) -> None:
9✔
1091
        """
1092
        Tests the method which let us push some dataset into the platform.
1093

1094
        In this test, we test the case that no token is given.
1095
        """
1096

1097
        response_dict = self.response_dataset
9✔
1098
        response_dict["subject"] = "example.net"
9✔
1099
        self.availability_status_dataset["expiration_date"] = "23-nov-2090"
9✔
1100

1101
        if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ:  # pragma: no cover
1102
            del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"]
1103

1104
        if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ:  # pragma: no cover
1105
            del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"]
1106

1107
        self.query_tool.token = ""
9✔
1108

1109
        expected = None
9✔
1110
        actual = self.query_tool.push(
9✔
1111
            AvailabilityCheckerStatus(**self.availability_status_dataset)
1112
        )
1113

1114
        self.assertEqual(expected, actual)
9✔
1115

1116
    def test_push_subject_not_str(self) -> None:
9✔
1117
        """
1118
        Tests the method which let us push some dataset into the platform.
1119

1120
        In this test, we test the case that the given subject is not a string.
1121
        """
1122

1123
        self.availability_status_dataset["subject"] = 293
9✔
1124

1125
        self.assertRaises(
9✔
1126
            TypeError,
1127
            lambda: self.query_tool.push(
1128
                AvailabilityCheckerStatus(**self.availability_status_dataset)
1129
            ),
1130
        )
1131

1132
    def test_push_checker_status_not_correct(self) -> None:
9✔
1133
        """
1134
        Tests the method which let us push some dataset into the platform.
1135

1136
        In this test, we test the case that the given checker status is not
1137
        correct.
1138
        """
1139

1140
        self.availability_status_dataset["subject"] = "foo.example.org"
9✔
1141

1142
        self.assertRaises(
9✔
1143
            TypeError,
1144
            lambda: self.query_tool.push(self.availability_status_dataset),
1145
        )
1146

1147
    def test_push_subject_empty_str(self) -> None:
9✔
1148
        """
1149
        Tests the method which let us push some dataset into the platform.
1150

1151
        In this test, we test the case that the given subject is an empty string.
1152
        """
1153

1154
        self.availability_status_dataset["subject"] = ""
9✔
1155

1156
        self.assertRaises(
9✔
1157
            ValueError,
1158
            lambda: self.query_tool.push(
1159
                AvailabilityCheckerStatus(**self.availability_status_dataset)
1160
            ),
1161
        )
1162

1163
    def test_push_checker_type_not_str(self) -> None:
9✔
1164
        """
1165
        Tests the method which let us push some dataset into the platform.
1166

1167
        In this test, we test the case that the given subject is not a string.
1168
        """
1169

1170
        self.availability_status_dataset["checker_type"] = 987
9✔
1171

1172
        self.assertRaises(
9✔
1173
            TypeError,
1174
            lambda: self.query_tool.push(
1175
                AvailabilityCheckerStatus(**self.availability_status_dataset)
1176
            ),
1177
        )
1178

1179
    def test_push_checker_type_not_supported(self) -> None:
9✔
1180
        """
1181
        Tests the method which let us push some dataset into the platform.
1182

1183
        In this test, we test the case that the given subject is not a string.
1184
        """
1185

1186
        self.availability_status_dataset["checker_type"] = "GIT"
9✔
1187
        self.query_tool.token = secrets.token_urlsafe(6)
9✔
1188

1189
        self.assertRaises(
9✔
1190
            ValueError,
1191
            lambda: self.query_tool.push(
1192
                AvailabilityCheckerStatus(**self.availability_status_dataset)
1193
            ),
1194
        )
1195

1196
    def test_push_token_not_given(self) -> None:
9✔
1197
        """
1198
        Tests the method which let us push some dataset into the platform.
1199

1200
        In this test, we test the case that no token is given.
1201
        """
1202

1203
        if "PYFUNCEBLE_COLLECTION_API_TOKEN" in os.environ:  # pragma: no cover
1204
            del os.environ["PYFUNCEBLE_COLLECTION_API_TOKEN"]
1205

1206
        if "PYFUNCEBLE_PLATFORM_API_TOKEN" in os.environ:  # pragma: no cover
1207
            del os.environ["PYFUNCEBLE_PLATFORM_API_TOKEN"]
1208

1209
        self.query_tool.token = ""
9✔
1210

1211
        expected = None
9✔
1212
        actual = self.query_tool.push(
9✔
1213
            AvailabilityCheckerStatus(**self.availability_status_dataset)
1214
        )
1215

1216
        self.assertEqual(expected, actual)
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc