Passed
Pull Request — 1.x (#62)
by Kevin
02:01
created

ChoiceFormField::getLabel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Zenstruck\Browser\Dom\Field;
4
5
use Facebook\WebDriver\Exception\NoSuchElementException;
6
use Facebook\WebDriver\WebDriverSelect;
7
use Symfony\Component\DomCrawler\Field\ChoiceFormField as BaseChoiceFormField;
8
use Symfony\Component\Panther\DomCrawler\Crawler as PantherCrawler;
9
use Zenstruck\Browser\Dom;
10
11
/**
12
 * @author Kevin Bond <[email protected]>
13
 */
14
final class ChoiceFormField extends BaseChoiceFormField
15
{
16
    private BaseChoiceFormField $inner;
17
    private Dom $dom;
18
19
    public function __construct(BaseChoiceFormField $inner, Dom $dom)
20
    {
21
        $this->inner = $inner;
22
        // todo avoid need to inject crawler?
23
        $this->dom = $dom;
24
    }
25
26
    public function hasValue(): bool
27
    {
28
        return $this->inner->hasValue();
29
    }
30
31
    public function isDisabled(): bool
32
    {
33
        return $this->inner->isDisabled();
34
    }
35
36
    public function select($value): void
37
    {
38
        $this->inner->select($value);
39
    }
40
41
    public function tick(): void
42
    {
43
        if ($this->is('radio')) {
44
            $this->setValue(null);
45
46
            return;
47
        }
48
49
        $this->inner->tick();
50
    }
51
52
    public function untick(): void
53
    {
54
        if ($this->is('radio')) {
55
            throw new \InvalidArgumentException('Radio fields cannot be unchecked.');
56
        }
57
58
        $this->inner->untick();
59
    }
60
61
    public function setValue($value): void
62
    {
63
        if ($this->is('radio')) {
64
            $value = $value ?? $this->attr('value');
65
        }
66
67
        if (null === $value) {
68
            throw new \InvalidArgumentException('Value required for select form fields.');
69
        }
70
71
        if (\is_array($value) && !$this->isMultiple()) {
72
            throw new \InvalidArgumentException('Value for a single select form field cannot be an array.');
73
        }
74
75
        if (\is_array($value) && $this->isMultiple() && $this->dom->crawler() instanceof PantherCrawler) {
76
            // todo have a separate PantherCrawler to avoid the "inner" check above
77
            // with panther, unselect all before setting (otherwise existing selections will remain)
78
            (new WebDriverSelect($this->dom->getElement(0)))->deselectAll();
0 ignored issues
show
Bug introduced by
It seems like $this->dom->getElement(0) can also be of type Zenstruck\Browser\Dom; however, parameter $element of Facebook\WebDriver\WebDriverSelect::__construct() does only seem to accept Facebook\WebDriver\WebDriverElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
            (new WebDriverSelect(/** @scrutinizer ignore-type */ $this->dom->getElement(0)))->deselectAll();
Loading history...
Bug introduced by
The method getElement() does not exist on Zenstruck\Browser\Dom. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
            (new WebDriverSelect($this->dom->/** @scrutinizer ignore-call */ getElement(0)))->deselectAll();
Loading history...
79
        }
80
81
        try {
82
            $this->inner->setValue($value);
83
        } catch (NoSuchElementException $e) {
84
            // try selecting by visible text
85
            $select = new WebDriverSelect($this->dom->getElement(0));
86
87
            foreach ((array) $value as $item) {
88
                $select->selectByVisibleText($item);
89
            }
90
        }
91
    }
92
93
    /**
94
     * @param array|string $type
95
     */
96
    public function is($type): bool
97
    {
98
        return \in_array($this->getType(), (array) $type, true);
99
    }
100
101
    public function attr(string $name): ?string
102
    {
103
        return $this->dom->attr($name);
0 ignored issues
show
Bug introduced by
The method attr() does not exist on Zenstruck\Browser\Dom. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        return $this->dom->/** @scrutinizer ignore-call */ attr($name);
Loading history...
Bug Best Practice introduced by
The expression return $this->dom->attr($name) could return the type Zenstruck\Browser\Dom which is incompatible with the type-hinted return null|string. Consider adding an additional type-check to rule them out.
Loading history...
104
    }
105
106
    public function getType(): string
107
    {
108
        return $this->inner->getType();
109
    }
110
111
    public function isMultiple(): bool
112
    {
113
        return $this->inner->isMultiple();
114
    }
115
116
    public function containsOption($optionValue, $options): bool
117
    {
118
        return $this->inner->containsOption($optionValue, $options);
119
    }
120
121
    public function availableOptionValues(): array
122
    {
123
        return $this->inner->availableOptionValues();
124
    }
125
126
    public function disableValidation(): self
127
    {
128
        $this->inner->disableValidation();
129
130
        return $this;
131
    }
132
133
    public function getLabel(): ?\DOMElement
134
    {
135
        return $this->inner->getLabel();
136
    }
137
138
    public function getName(): string
139
    {
140
        return $this->inner->getName();
141
    }
142
143
    public function getValue()
144
    {
145
        return $this->inner->getValue();
146
    }
147
}
148