test_empty_stock_when_no_ticker_was_provided()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chemaclass\StockTickerTests\Unit\Domain\Crawler;
6
7
use Chemaclass\StockTicker\Domain\Crawler\CrawlResult;
8
use Chemaclass\StockTicker\Domain\Crawler\Mapper\CrawledInfoMapper;
9
use Chemaclass\StockTicker\Domain\Crawler\Mapper\CrawledInfoMapperInterface;
10
use Chemaclass\StockTicker\Domain\Crawler\QuoteCrawler;
11
use Chemaclass\StockTicker\Domain\Crawler\SiteCrawlerInterface;
12
use Chemaclass\StockTicker\Domain\ReadModel\Site;
13
use Chemaclass\StockTicker\Domain\ReadModel\Symbol;
14
use Chemaclass\StockTicker\Domain\WriteModel\CompanyName;
15
use Chemaclass\StockTicker\Domain\WriteModel\Quote;
16
use Chemaclass\StockTickerTests\Unit\WithFakeHttpClient;
17
use PHPUnit\Framework\TestCase;
18
use Symfony\Contracts\HttpClient\HttpClientInterface;
19
20
final class QuoteCrawlerTest extends TestCase
21
{
22
    use WithFakeHttpClient;
23
24
    public function test_empty_stock_when_no_ticker_was_provided(): void
25
    {
26
        $companyCrawler = new QuoteCrawler(
27
            $this->mockHttpClient(),
28
            $this->createCrawledInfoMapper(),
29
            $this->mockSiteCrawler('key1', 'value1'),
30
        );
31
32
        self::assertEquals(new CrawlResult([]), $companyCrawler->crawlStock());
33
    }
34
35
    public function test_crawl_stock_for_one_ticker_and_multiple_crawlers(): void
36
    {
37
        $companyCrawler = new QuoteCrawler(
38
            $this->mockHttpClient(),
39
            $this->createCrawledInfoMapper(static function (array $info): array {
40
                $info['companyName']['longName'] = $info['longName'];
41
42
                return $info;
43
            }),
44
            $this->mockSiteCrawler('symbol', 'SYMBOL'),
45
            $this->mockSiteCrawler('longName', 'Company Name, Inc.'),
46
        );
47
48
        $actual = $companyCrawler->crawlStock('SYMBOL');
49
50
        self::assertEquals(new CrawlResult([
51
            'SYMBOL' => (new Quote())
52
                ->setSymbol('SYMBOL')
53
                ->setCompanyName((new CompanyName())
54
                    ->setLongName('Company Name, Inc.')),
55
        ]), $actual);
56
    }
57
58
    public function tCrawlStockForMultipleTickerSymbols(): void
59
    {
60
        $companyCrawler = new QuoteCrawler(
61
            $this->mockHttpClient(),
62
            $this->createCrawledInfoMapper(),
63
            $this->mockSiteCrawler('key1', 'value1'),
64
        );
65
66
        $actual = $companyCrawler->crawlStock('SYMBOL_1', 'SYMBOL_2');
67
68
        self::assertEquals(new CrawlResult([
69
            'SYMBOL_1' => (new Quote())
70
                ->setSymbol('SYMBOL_1'),
71
            'SYMBOL_2' => (new Quote())
72
                ->setSymbol('SYMBOL_2'),
73
        ]), $actual);
74
    }
75
76
    private function createCrawledInfoMapper(?callable $map = null): CrawledInfoMapperInterface
77
    {
78
        return new CrawledInfoMapper($map);
79
    }
80
81
    private function mockSiteCrawler(string $crawlerKey, string $extractedValue): SiteCrawlerInterface
82
    {
83
        return new class($crawlerKey, $extractedValue) implements SiteCrawlerInterface {
84
            private string $crawlerKey;
85
86
            private string $extractedValue;
87
88
            public function __construct(string $crawlerKey, string $extractedValue)
89
            {
90
                $this->crawlerKey = $crawlerKey;
91
                $this->extractedValue = $extractedValue;
92
            }
93
94
            public function crawl(HttpClientInterface $httpClient, Symbol $symbol): Site
95
            {
96
                return new Site([$this->crawlerKey => $this->extractedValue]);
97
            }
98
        };
99
    }
100
}
101