Completed
Pull Request — master (#360)
by
unknown
02:31
created

FixtureContext::iShouldSeeTheForm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace SilverStripe\AssetAdmin\Tests\Behat\Context;
4
5
use Behat\Mink\Element\DocumentElement;
6
use Behat\Mink\Element\NodeElement;
7
use Page;
8
use SilverStripe\Assets\Image;
9
use SilverStripe\BehatExtension\Context\FixtureContext as BaseFixtureContext;
10
11
/**
12
 * Context used to create fixtures in the SilverStripe ORM.
13
 */
14
class FixtureContext extends BaseFixtureContext
15
{
16
17
    /**
18
     * Select a gallery item by type and name
19
     *
20
     * @Given /^I (?:(?:click on)|(?:select)) the file named "([^"]+)" in the gallery$/
21
     * @param string $name
22
     */
23
    public function stepISelectGalleryItem($name)
24
    {
25
        $item = $this->getGalleryItem($name);
26
        assertNotNull($item, "File named $name could not be found");
27
        $item->click();
28
    }
29
30
    /**
31
     * Check the checkbox for a given gallery item
32
     * @Given /^I check the file named "([^"]+)" in the gallery$/
33
     * @param string $name
34
     */
35
    public function stepICheckTheGalleryItem($name)
36
    {
37
        $item = $this->getGalleryItem($name);
38
        assertNotNull($item, "File named $name could not be found");
39
        $checkbox = $item->find('css', 'input[type="checkbox"]');
40
        assertNotNull($checkbox, "Could not find checkbox for file named {$name}");
41
        $checkbox->check();
42
    }
43
44
    /**
45
     * @Then /^I should see the file named "([^"]+)" in the gallery$/
46
     * @param string $name
47
     */
48
    public function iShouldSeeTheGalleryItem($name)
49
    {
50
        $item = $this->getGalleryItem($name);
51
        assertNotNull($item, "File named {$name} could not be found");
52
    }
53
54
    /**
55
     * @Then /^I should not see the file named "([^"]+)" in the gallery$/
56
     * @param string $name
57
     */
58
    public function iShouldNotSeeTheGalleryItem($name)
59
    {
60
        $item = $this->getGalleryItem($name, 0);
61
        assertNull($item, "File named {$name} was found when it should not be visible");
62
    }
63
64
    /**
65
     * @Then /^I should see the "([^"]*)" form$/
66
     * @param string $id HTML ID of form
67
     */
68
    public function iShouldSeeTheForm($id)
69
    {
70
        /** @var DocumentElement $page */
71
        $page = $this->getSession()->getPage();
72
        $form = $this->retry(function () use ($page, $id) {
73
            return $page->find('css', "form#{$id}");
74
        });
75
        assertNotNull($form, "form with id $id could not be found");
76
        assertTrue($form->isVisible(), "form with id $id is not visible");
77
    }
78
79
    /**
80
     * @Given /^I click on the latest history item$/
81
     */
82
    public function iClickOnTheLatestHistoryItem()
83
    {
84
        $this->getSession()->wait(
85
            5000,
86
            "window.jQuery && window.jQuery('.file-history__list li').size() > 0"
87
        );
88
89
        $page = $this->getSession()->getPage();
90
91
        $elements = $page->find('css', '.file-history__list li');
92
93
        if (null === $elements) {
94
            throw new \InvalidArgumentException(sprintf('Could not find list item'));
95
        }
96
97
        $elements->click();
98
    }
99
100
    /**
101
     * @Given /^I attach the file "([^"]*)" to dropzone "([^"]*)"$/
102
     * @see MinkContext::attachFileToField()
103
     */
104
    public function iAttachTheFileToDropzone($path, $name)
105
    {
106
        // Get path
107
        $filesPath = $this->getMainContext()->getMinkParameter('files_path');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Behat\Behat\Context\ExtendedContextInterface as the method getMinkParameter() does only exist in the following implementations of said interface: Behat\MinkExtension\Context\MinkContext, Behat\MinkExtension\Context\RawMinkContext, SilverStripe\AssetAdmin\...\Context\FeatureContext, SilverStripe\BehatExtens...ext\SilverStripeContext, SilverStripe\Cms\Test\Behaviour\FeatureContext.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
108
        if ($filesPath) {
109
            $fullPath = rtrim(realpath($filesPath), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$path;
110
            if (is_file($fullPath)) {
111
                $path = $fullPath;
112
            }
113
        }
114
115
        assertFileExists($path, "$path does not exist");
116
        // Find field
117
        $selector = "input[type=\"file\"].dz-hidden-input.dz-input-{$name}";
118
119
        /** @var DocumentElement $page */
120
        $page = $this->getSession()->getPage();
121
        $input = $page->find('css', $selector);
122
        assertNotNull($input, "Could not find {$selector}");
123
124
        // Make visible temporarily while attaching
125
        $this->getSession()->executeScript(
126
            <<<EOS
127
window.jQuery('.dz-hidden-input')
128
    .css('visibility', 'visible')
129
    .width(1)
130
    .height(1);
131
EOS
132
        );
133
134
        assert($input->isVisible());
135
        // Attach via html5
136
        $input->attachFile($path);
137
    }
138
139
    /**
140
     * Checks that the message box contains specified text.
141
     *
142
     * @Then /^I should see "(?P<text>(?:[^"]|\\")*)" in the message box$/
143
     */
144
    public function assertMessageBoxContainsText($text)
145
    {
146
        /** @var FeatureContext $mainContext */
147
        $mainContext = $this->getMainContext();
148
        $mainContext
149
            ->assertSession()
150
            ->elementTextContains('css', '.message-box', str_replace('\\"', '"', $text));
151
    }
152
153
    /**
154
     * Helper for finding items in the visible gallery view
155
     *
156
     * @param string $name Title of item
157
     * @param int $timeout
158
     * @return NodeElement
159
     */
160
    protected function getGalleryItem($name, $timeout = 3)
161
    {
162
        /** @var DocumentElement $page */
163
        $page = $this->getSession()->getPage();
164
        return $this->retry(function () use ($page, $name) {
165
            // Find by cell
166
            $cell = $page->find(
167
                'xpath',
168
                "//div[contains(@class, 'gallery-item')]//div[contains(text(), '{$name}')]"
169
            );
170
            if ($cell) {
171
                return $cell;
172
            }
173
            // Find by row
174
            $row = $page->find(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $row is correct as $page->find('xpath', "//...s(text(), '{$name}')]") (which targets Behat\Mink\Element\Element::find()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
175
                'xpath',
176
                "//tr[contains(@class, 'gallery__table-row')]//div[contains(text(), '{$name}')]"
177
            );
178
            if ($row) {
179
                return $row;
180
            }
181
            return null;
182
        }, $timeout);
183
    }
184
185
    /**
186
     * Invoke $try callback for a non-empty result with a given timeout
187
     *
188
     * @param callable $try
189
     * @param int $timeout Number of seconds to retry for
190
     * @return mixed Result of invoking $try, or null if timed out
191
     */
192
    protected function retry($try, $timeout = 3)
193
    {
194
        do {
195
            $result = $try();
196
            if ($result) {
197
                return $result;
198
            }
199
            sleep(1);
200
        } while (--$timeout >= 0);
201
        return null;
202
    }
203
204
    /**
205
     * @Given /^a page "([^"]*)" containing an image "([^"]*)"$/
206
     */
207
    public function aPageContaining($page, $image)
208
    {
209
        // Find or create named image
210
        $fields = $this->prepareFixture(Image::class, $image);
211
        /** @var Image $image */
212
        $image = $this->fixtureFactory->createObject(Image::class, $image, $fields);
213
214
        // Create page
215
        $fields = $this->prepareFixture(Page::class, $page);
216
        $fields = array_merge($fields, [
217
            'Title' => $page,
218
            'Content' => sprintf(
219
                '<p>[image id="%d" width="%d" height="%d"]</p>',
220
                $image->ID,
221
                $image->getWidth(),
222
                $image->getHeight()
223
            ),
224
        ]);
225
        $this->fixtureFactory->createObject(Page::class, $page, $fields);
226
    }
227
}
228