TableContext::getAsserter()   A
last analyzed

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
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Knp\FriendlyContexts\Context;
4
5
use Behat\Gherkin\Node\TableNode;
6
use Knp\FriendlyContexts\Utils\Asserter;
7
use Knp\FriendlyContexts\Utils\TextFormater;
8
9
class TableContext extends RawMinkContext
10
{
11
    /**
12
     * @Then /^I should see a table with "([^"]*)" in the "([^"]*)" column$/
13
     */
14
    public function iShouldSeeATableWithInTheNamedColumn($list, $column)
15
    {
16
        $cells = array_merge(array($column), $this->getFormater()->listToArray($list));
17
        $expected = new TableNode(array_map(function($cell) { return [$cell]; }, $cells));
18
19
        $this->iShouldSeeTheFollowingTable($expected);
20
    }
21
22
    /**
23
     * @Given /^I should see the following table:?$/
24
     */
25
    public function iShouldSeeTheFollowingTable($expected)
26
    {
27
        if ($expected instanceof TableNode) {
28
            $expected = $expected->getTable();
29
        }
30
31
        $this->iShouldSeeATable();
32
33
        $tables = $this->findTables();
34
        $exceptions = array();
35
36
        foreach ($tables as $table) {
37
            try {
38
                if (false === $extraction = $this->extractColumns(current($expected), $table)) {
39
                    $this->getAsserter()->assertArrayEquals($expected, $table, true);
40
41
                    return;
42
                }
43
                $this->getAsserter()->assertArrayEquals($expected, $extraction, true);
44
45
                return;
46
            } catch (\Exception $e) {
47
                $exceptions[] = $e;
48
            }
49
        }
50
51
        $message = implode("\n", array_map(function ($e) { return $e->getMessage(); }, $exceptions));
52
53
        throw new \Exception($message);
54
    }
55
56
    /**
57
     * @Then /^I should see the following table portion:?$/
58
     */
59
    public function iShouldSeeTheFollowingTablePortion($expected)
60
    {
61
        if ($expected instanceof TableNode) {
62
            $expected = $this->reorderArrayKeys($expected->getTable());
63
        }
64
65
        $this->iShouldSeeATable();
66
67
        $tables = $this->findTables();
68
        $exceptions = array();
69
70
        foreach ($tables as $table) {
71
            try {
72
                if (false === $extraction = $this->extractColumns(current($expected), $table)) {
73
                    $this->getAsserter()->assertArrayContains($expected, $table);
74
75
                    return;
76
                }
77
                $this->getAsserter()->assertArrayContains($expected, $extraction);
78
79
                return;
80
            } catch (\Exception $e) {
81
                $exceptions[] = $e;
82
            }
83
        }
84
85
        $message = implode("\n", array_map(function ($e) { return $e->getMessage(); }, $exceptions));
86
87
        throw new \Exception($message);
88
    }
89
90
    /**
91
     * @Then /^I should see a table with ([^"]*) rows$/
92
     * @Then /^I should see a table with ([^"]*) row$/
93
     */
94
    public function iShouldSeeATableWithRows($nbr)
95
    {
96
        $nbr = (int) $nbr;
97
98
        $this->iShouldSeeATable();
99
        $exceptions = array();
100
        $tables = $this->getSession()->getPage()->findAll('css', 'table');
101
102
        foreach ($tables as $table) {
103
            try {
104
                if (null !== $body = $table->find('css', 'tbody')) {
105
                    $table = $body;
106
                }
107
                $rows = $table->findAll('css', 'tr');
108
                $this->getAsserter()->assertEquals($nbr, count($rows), sprintf('Table with %s rows expected, table with %s rows found.', $nbr, count($rows)));
109
                return;
110
            } catch (\Exception $e) {
111
                $exceptions[] = $e;
112
            }
113
        }
114
115
        $message = implode("\n", array_map(function ($e) { return $e->getMessage(); }, $exceptions));
116
117
        throw new \Exception($message);
118
    }
119
120
    /**
121
     * @Then /^I should see a table$/
122
     */
123
    public function iShouldSeeATable()
124
    {
125
        try {
126
            $this->getSession()->wait(2000, '0 < document.getElementsByTagName("TABLE").length');
127
        } catch (\Exception $ex) {
128
            unset($ex);
129
        }
130
        $tables = $this->getSession()->getPage()->findAll('css', 'table');
131
        $this->getAsserter()->assert(0 < count($tables), 'No table found');
132
    }
133
134
    protected function extractColumns(array $headers, array $table)
135
    {
136
        if (0 == count($table) || 0 == count($headers)) {
137
            return false;
138
        }
139
140
        $columns = array();
141
        $tableHeaders = current($table);
142
        foreach ($headers as $header) {
143
            $inArray = false;
144
            foreach ($tableHeaders as $index => $thead) {
145
                if ($thead === $header) {
146
                    $columns[] = $index;
147
                    $inArray = true;
148
                }
149
            }
150
            if (false === $inArray) {
151
                return false;
152
            }
153
        }
154
155
        $result = array();
156
        foreach ($table as $row) {
157
            $node = array();
158
            foreach ($row as $index => $value) {
159
                if (in_array($index, $columns)) {
160
                    $node[] = $value;
161
                }
162
            }
163
            $result[] = $node;
164
        }
165
166
        return $result;
167
    }
168
169
    protected function findTables()
170
    {
171
        $tables = $this->getSession()->getPage()->findAll('css', 'table');
172
        $result = array();
173
174
        foreach ($tables as $table) {
175
            $node = array();
176
            $head = $table->find('css', 'thead');
177
            $body = $table->find('css', 'tbody');
178
            $foot = $table->find('css', 'tfoot');
179
            if (null !== $head || null !== $body || null !== $foot) {
180
                $this->extractDataFromPart($head, $node);
181
                $this->extractDataFromPart($body, $node);
182
                $this->extractDataFromPart($foot, $node);
183
            } else {
184
                $this->extractDataFromPart($table, $node);
185
            }
186
            $result[] = $node;
187
        }
188
189
        return $result;
190
    }
191
192
    protected function extractDataFromPart($part, &$array)
193
    {
194
        if (null === $part) {
195
196
            return;
197
        }
198
199
        foreach ($part->findAll('css', 'tr') as $row) {
200
            $array[] = $this->extractDataFromRow($row);
201
        }
202
    }
203
204
    protected function extractDataFromRow($row)
205
    {
206
        $result = array();
207
        $elements = array_merge($row->findAll('css', 'th'), $row->findAll('css', 'td'));
208
209
        foreach ($elements as $element) {
210
            $result[] = preg_replace('!\s+!', ' ', $element->getText());
211
        }
212
213
        return $result;
214
    }
215
216
    protected function reorderArrayKeys(array $subject)
217
    {
218
        $orderedArray = array();
219
220
        foreach ($subject as $key => $value) {
221
            if (is_int($key)) {
222
                $orderedArray[] = $value;
223
            } else {
224
                $orderedArray[$key] = $value;
225
            }
226
        }
227
228
        return $orderedArray;
229
    }
230
231
    protected function getAsserter()
232
    {
233
        return new Asserter($this->getFormater());
234
    }
235
236
    protected function getFormater()
237
    {
238
        return new TextFormater;
239
    }
240
}
241