3
3
* Copyright © Magento, Inc. All rights reserved.
4
4
* See COPYING.txt for license details.
5
5
*/
6
+ declare (strict_types=1 );
7
+
6
8
namespace Magento \Catalog \Controller \Product ;
7
9
10
+ use Magento \Catalog \Api \ProductRepositoryInterface ;
11
+ use Magento \Catalog \Model \Product ;
12
+ use Magento \Eav \Model \AttributeSetSearchResults ;
13
+ use Magento \Eav \Model \Entity \Attribute \Set ;
14
+ use Magento \Framework \Api \SearchCriteriaBuilder ;
15
+ use Magento \Framework \Api \SortOrderBuilder ;
16
+ use Magento \Framework \App \Filesystem \DirectoryList ;
17
+ use Magento \Framework \Data \Collection ;
18
+ use Magento \Catalog \Api \AttributeSetRepositoryInterface ;
19
+ use Magento \Eav \Model \Entity \Type ;
20
+ use Magento \Framework \Filesystem ;
21
+ use Magento \Framework \Filesystem \Directory \WriteInterface ;
22
+ use Magento \TestFramework \Helper \Bootstrap ;
23
+
8
24
/**
9
- * @magentoDataFixture Magento/Catalog/controllers/_files/products.php
10
- * @magentoDbIsolation disabled
25
+ * Integration test for product view front action.
26
+ *
27
+ * @magentoAppArea frontend
11
28
*/
12
29
class ViewTest extends \Magento \TestFramework \TestCase \AbstractController
13
30
{
14
31
/**
32
+ * @var string
33
+ */
34
+ private $ systemLogFileName = 'system.log ' ;
35
+
36
+ /**
37
+ * @var ProductRepositoryInterface $productRepository
38
+ */
39
+ private $ productRepository ;
40
+
41
+ /**
42
+ * @var AttributeSetRepositoryInterface $attributeSetRepository
43
+ */
44
+ private $ attributeSetRepository ;
45
+
46
+ /**
47
+ * @var Type $productEntityType
48
+ */
49
+ private $ productEntityType ;
50
+
51
+ /**
52
+ * @inheritdoc
53
+ */
54
+ protected function setUp ()
55
+ {
56
+ parent ::setUp ();
57
+
58
+ $ this ->productRepository = $ this ->_objectManager ->create (ProductRepositoryInterface::class);
59
+ $ this ->attributeSetRepository = $ this ->_objectManager ->create (AttributeSetRepositoryInterface::class);
60
+ $ this ->productEntityType = $ this ->_objectManager ->create (Type::class)
61
+ ->loadByCode (Product::ENTITY );
62
+ }
63
+
64
+ /**
65
+ * @magentoDbIsolation disabled
66
+ * @magentoDataFixture Magento/Catalog/controllers/_files/products.php
15
67
* @magentoConfigFixture current_store catalog/seo/product_canonical_tag 1
68
+ * @return void
16
69
*/
17
- public function testViewActionWithCanonicalTag ()
70
+ public function testViewActionWithCanonicalTag (): void
18
71
{
19
72
$ this ->markTestSkipped (
20
73
'MAGETWO-40724: Canonical url from tests sometimes does not equal canonical url from action '
@@ -26,4 +79,176 @@ public function testViewActionWithCanonicalTag()
26
79
$ this ->getResponse ()->getBody ()
27
80
);
28
81
}
82
+
83
+ /**
84
+ * View product with custom attribute when attribute removed from it.
85
+ *
86
+ * It tests that after changing product attribute set from Default to Custom
87
+ * there are no waring messages in log in case Custom not contains attribute from Default.
88
+ *
89
+ * @magentoDataFixture Magento/Catalog/_files/product_simple_with_country_of_manufacture.php
90
+ * @magentoDataFixture Magento/Catalog/_files/attribute_set_based_on_default_without_country_of_manufacture.php
91
+ * @magentoDbIsolation disabled
92
+ * @return void
93
+ */
94
+ public function testViewActionCustomAttributeSetWithoutCountryOfManufacture (): void
95
+ {
96
+ $ product = $ this ->getProductBySku ('simple_with_com ' );
97
+ $ attributeSetCustom = $ this ->getProductAttributeSetByName ('custom_attribute_set_wout_com ' );
98
+
99
+ $ product ->setAttributeSetId ($ attributeSetCustom ->getAttributeSetId ());
100
+ $ this ->productRepository ->save ($ product );
101
+
102
+ $ this ->dispatch (sprintf ('catalog/product/view/id/%s/ ' , $ product ->getId ()));
103
+ $ message = 'Attempt to load value of nonexistent EAV attribute ' ;
104
+ $ this ->assertFalse (
105
+ $ this ->checkSystemLogForMessage ($ message ),
106
+ sprintf ("Warning message found in %s: %s " , $ this ->systemLogFileName , $ message )
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Check system log file for error message.
112
+ *
113
+ * @param string $message
114
+ * @return bool
115
+ */
116
+ private function checkSystemLogForMessage (string $ message ): bool
117
+ {
118
+ $ content = $ this ->getSystemLogContent ();
119
+ $ pos = strpos ($ content , $ message );
120
+
121
+ return $ pos !== false ;
122
+ }
123
+
124
+ /**
125
+ * Get product instance by sku.
126
+ *
127
+ * @param string $sku
128
+ * @return Product
129
+ */
130
+ private function getProductBySku (string $ sku ): Product
131
+ {
132
+ $ product = $ this ->productRepository ->get ($ sku );
133
+
134
+ return $ product ;
135
+ }
136
+
137
+ /**
138
+ * Get product attribute set by name.
139
+ *
140
+ * @param string $attributeSetName
141
+ * @return Set|null
142
+ */
143
+ private function getProductAttributeSetByName (string $ attributeSetName ): ?Set
144
+ {
145
+ /** @var SortOrderBuilder $sortOrderBuilder */
146
+ $ sortOrderBuilder = $ this ->_objectManager ->create (SortOrderBuilder::class);
147
+ /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
148
+ $ searchCriteriaBuilder = $ this ->_objectManager ->get (SearchCriteriaBuilder::class);
149
+ $ searchCriteriaBuilder ->addFilter ('attribute_set_name ' , $ attributeSetName );
150
+ $ searchCriteriaBuilder ->addFilter ('entity_type_id ' , $ this ->productEntityType ->getId ());
151
+ $ attributeSetIdSortOrder = $ sortOrderBuilder
152
+ ->setField ('attribute_set_id ' )
153
+ ->setDirection (Collection::SORT_ORDER_DESC )
154
+ ->create ();
155
+ $ searchCriteriaBuilder ->addSortOrder ($ attributeSetIdSortOrder );
156
+ $ searchCriteriaBuilder ->setPageSize (1 );
157
+ $ searchCriteriaBuilder ->setCurrentPage (1 );
158
+
159
+ /** @var AttributeSetSearchResults $searchResult */
160
+ $ searchResult = $ this ->attributeSetRepository ->getList ($ searchCriteriaBuilder ->create ());
161
+ $ items = $ searchResult ->getItems ();
162
+
163
+ if (count ($ items ) > 0 ) {
164
+ return reset ($ items );
165
+ }
166
+
167
+ return null ;
168
+ }
169
+
170
+ /**
171
+ * Get system log content.
172
+ *
173
+ * @return string
174
+ */
175
+ private function getSystemLogContent (): string
176
+ {
177
+ $ logDir = $ this ->getLogDirectoryWrite ();
178
+ $ logFullFileName = $ logDir ->getAbsolutePath ($ this ->systemLogFileName );
179
+ $ content = $ this ->tail ($ logFullFileName , 10 );
180
+
181
+ return $ content ;
182
+ }
183
+
184
+ /**
185
+ * Get file tail.
186
+ *
187
+ * @param string $filename
188
+ * @param int $lines
189
+ * @param int $buffer
190
+ * @return false|string
191
+ */
192
+ private function tail (string $ filename , int $ lines = 10 , int $ buffer = 4096 )
193
+ {
194
+ // Open the file
195
+ $ f = fopen ($ filename , "rb " );
196
+
197
+ // Jump to last character
198
+ fseek ($ f , -1 , SEEK_END );
199
+
200
+ // Read it and adjust line number if necessary
201
+ // (Otherwise the result would be wrong if file doesn't end with a blank line)
202
+ if (fread ($ f , 1 ) != "\n" ) {
203
+ $ lines --;
204
+ }
205
+
206
+ // Start reading
207
+ $ output = '' ;
208
+ $ chunk = '' ;
209
+
210
+ // While we would like more
211
+ while (ftell ($ f ) > 0 && $ lines >= 0 ) {
212
+ // Figure out how far back we should jump
213
+ $ seek = min (ftell ($ f ), $ buffer );
214
+
215
+ // Do the jump (backwards, relative to where we are)
216
+ fseek ($ f , -$ seek , SEEK_CUR );
217
+
218
+ // Read a chunk and prepend it to our output
219
+ $ output = ($ chunk = fread ($ f , $ seek )) . $ output ;
220
+
221
+ // Jump back to where we started reading
222
+ fseek ($ f , -mb_strlen ($ chunk , '8bit ' ), SEEK_CUR );
223
+
224
+ // Decrease our line counter
225
+ $ lines -= substr_count ($ chunk , "\n" );
226
+ }
227
+
228
+ // While we have too many lines
229
+ // (Because of buffer size we might have read too many)
230
+ while ($ lines ++ < 0 ) {
231
+ // Find first newline and remove all text before that
232
+ $ output = substr ($ output , strpos ($ output , "\n" ) + 1 );
233
+ }
234
+
235
+ // Close file and return
236
+ fclose ($ f );
237
+
238
+ return $ output ;
239
+ }
240
+
241
+ /**
242
+ * Get current LOG directory write.
243
+ *
244
+ * @return WriteInterface
245
+ */
246
+ private function getLogDirectoryWrite ()
247
+ {
248
+ /** @var Filesystem $filesystem */
249
+ $ filesystem = $ this ->_objectManager ->create (Filesystem::class);
250
+ $ logDirectory = $ filesystem ->getDirectoryWrite (DirectoryList::LOG );
251
+
252
+ return $ logDirectory ;
253
+ }
29
254
}
0 commit comments