Passed
Push — master ( 76f984...df9ead )
by Marc
02:14
created

theOpenGraphDataShouldNotSatisfyFullRequirements()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 4
c 1
b 1
f 0
nc 1
nop 1
dl 0
loc 7
rs 10
1
<?php declare(strict_types=1);
2
3
namespace MOrtola\BehatSEOContexts\Context;
4
5
use InvalidArgumentException;
6
use Webmozart\Assert\Assert;
7
8
class SocialContext extends BaseContext
9
{
10
    /**
11
     * @Then /^the (Twitter|Facebook) Open Graph data should not satisfy minimum requirements$/
12
     */
13
    public function theOpenGraphDataShouldNotSatisfyRequirements(string $socialNetworkName): void
14
    {
15
        $this->assertInverse(
16
            function () use ($socialNetworkName) {
17
                $this->theOpenGraphDataShouldSatisfyRequirements($socialNetworkName);
18
            },
19
            sprintf('The %s OG Data satisfies minimum requirements.', $socialNetworkName)
20
        );
21
    }
22
23
    /**
24
     * @Then /^the (Twitter|Facebook) Open Graph data should not satisfy full requirements$/
25
     */
26
    public function theOpenGraphDataShouldNotSatisfyFullRequirements(string $socialNetworkName): void
27
    {
28
        $this->assertInverse(
29
            function () use ($socialNetworkName) {
30
                $this->theOpenGraphDataShouldSatisfyFullRequirements($socialNetworkName);
31
            },
32
            sprintf('The %s OG Data satisfies full requirements.', $socialNetworkName)
33
        );
34
    }
35
36
    /**
37
     * @Then /^the (Twitter|Facebook) Open Graph data should satisfy minimum requirements$/
38
     */
39
    public function theOpenGraphDataShouldSatisfyRequirements(string $socialNetworkName): void
40
    {
41
        switch ($socialNetworkName) {
42
            case 'Twitter':
43
                $this->validateTwitterOpenGraphData();
44
45
                break;
46
            case 'Facebook':
47
                $this->validateFacebookOpenGraphData();
48
49
                break;
50
            default:
51
                throw new InvalidArgumentException(
52
                    sprintf('%s open graph simple validation is not allowed.', $socialNetworkName)
53
                );
54
        }
55
    }
56
57
    /**
58
     * @Then /^the (Twitter|Facebook) Open Graph data should satisfy full requirements$/
59
     */
60
    public function theOpenGraphDataShouldSatisfyFullRequirements(string $socialNetworkName): void
61
    {
62
        switch ($socialNetworkName) {
63
            case 'Twitter':
64
                $this->validateFullTwitterOpenGraphData();
65
66
                break;
67
            case 'Facebook':
68
                $this->validateFullFacebookOpenGraphData();
69
70
                break;
71
            default:
72
                throw new InvalidArgumentException(
73
                    sprintf('%s open graph full validation is not allowed.', $socialNetworkName)
74
                );
75
        }
76
    }
77
78
    private function validateTwitterOpenGraphData(): void
79
    {
80
        Assert::oneOf(
81
            $this->getOGMetaContent('twitter:card'),
82
            ['summary', 'summary_large_image', 'app', 'player'],
83
            'OG meta twitter:card contains invalid content'
84
        );
85
86
        $this->getOGMetaContent('twitter:title');
87
    }
88
89
    private function validateFullTwitterOpenGraphData(): void
90
    {
91
        $this->validateTwitterOpenGraphData();
92
93
        Assert::notEmpty(
94
            filter_var($this->getOGMetaContent('twitter:image'), FILTER_VALIDATE_URL)
95
        );
96
97
        $pathInfo = pathinfo($this->getOGMetaContent('twitter:image'));
98
99
        Assert::keyExists($pathInfo, 'extension');
100
101
        if (isset($pathInfo['extension'])) {
102
            Assert::oneOf(
103
                $pathInfo['extension'],
104
                ['jpg', 'jpeg', 'webp', 'png', 'gif'],
105
                'OG meta twitter:image has valid extension. Allowed are: jpg/jpeg, png, webp, gif'
106
            );
107
        }
108
109
        $this->getOGMetaContent('twitter:description');
110
    }
111
112
    private function getOGMetaContent(string $property): string
113
    {
114
        $ogMeta = $this->getSession()->getPage()->find(
115
            'xpath',
116
            sprintf('//head/meta[@property="%1$s" or @name="%1$s"]', $property)
117
        );
118
119
        Assert::notNull(
120
            $ogMeta,
121
            sprintf('Open Graph meta %s does not exist', $property)
122
        );
123
124
        Assert::notEmpty(
125
            $ogMeta->getAttribute('content'),
126
            sprintf('Open Graph meta %s should not be empty', $property)
127
        );
128
129
        return $ogMeta->getAttribute('content') ?? '';
130
    }
131
132
    private function validateFacebookOpenGraphData(): void
133
    {
134
        Assert::notEmpty(
135
            filter_var($this->getOGMetaContent('og:url'), FILTER_VALIDATE_URL)
136
        );
137
138
        Assert::eq(
139
            $this->getOGMetaContent('og:url'),
140
            $this->getCurrentUrl(),
141
            'OG meta og:url does not match expected url'
142
        );
143
144
        $this->getOGMetaContent('og:title');
145
        $this->getOGMetaContent('og:description');
146
147
        Assert::notEmpty(
148
            filter_var($this->getOGMetaContent('og:image'), FILTER_VALIDATE_URL)
149
        );
150
151
        $pathInfo = pathinfo($this->getOGMetaContent('og:image'));
152
153
        Assert::keyExists($pathInfo, 'extension');
154
155
        if (isset($pathInfo['extension'])) {
156
            Assert::oneOf(
157
                $pathInfo['extension'],
158
                ['jpg', 'jpeg', 'png', 'gif'],
159
                'OG meta og:image has valid extension. Allowed are: jpg/jpeg, png, gif'
160
            );
161
        }
162
    }
163
164
    private function validateFullFacebookOpenGraphData(): void
165
    {
166
        $this->validateFacebookOpenGraphData();
167
168
        Assert::oneOf(
169
            $this->getOGMetaContent('og:type'),
170
            [
171
                'article',
172
                'book',
173
                'books.author',
174
                'books.book',
175
                'books.genre',
176
                'business.business',
177
                'fitness.course',
178
                'game.achievement',
179
                'music.album',
180
                'music.playlist',
181
                'music.radio_station',
182
                'music.song',
183
                'place',
184
                'product',
185
                'product.group',
186
                'product.item',
187
                'profile',
188
                'restaurant.menu',
189
                'restaurant.menu_item',
190
                'restaurant.menu_section',
191
                'restaurant.restaurant',
192
                'video.episode',
193
                'video.movie',
194
                'video.other',
195
                'video.tv_show',
196
            ],
197
            'OG meta og:type contains invalid content.'
198
        );
199
200
        Assert::regex(
201
            $this->getOGMetaContent('og:locale'),
202
            '/^[a-z]{2}_[A-Z]{2}$/',
203
            'OG meta og:locale does not follow the right format az_AZ.'
204
        );
205
    }
206
}
207