Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
18 | class OfferCustomElementsGeneratorTest extends AbstractGeneratorTest |
||
19 | { |
||
20 | const CDATA_TEST_STRING = '<p>Simple HTML</p></description></offer><![CDATA['; |
||
21 | const OFFER_COUNT = 2; |
||
22 | |||
23 | /** |
||
24 | * Test generate |
||
25 | */ |
||
26 | public function testGenerate() |
||
27 | { |
||
28 | // Don't call $this->validateFileWithDtd() here because custom elements are not included into the default DTD |
||
29 | $this->generateFile(); |
||
30 | $this->checkCustomElements(); |
||
31 | } |
||
32 | |||
33 | /** |
||
34 | * Need to override parent::createOffers() in order to avoid setting description |
||
35 | * after calling self::createOffer() |
||
36 | * |
||
37 | * {@inheritdoc} |
||
38 | * |
||
39 | * @see \Bukashk0zzz\YmlGenerator\Tests\AbstractGeneratorTest::createOffers() |
||
40 | */ |
||
41 | protected function createOffers() |
||
42 | { |
||
43 | $offers = []; |
||
44 | foreach (\range(1, self::OFFER_COUNT) as $id) { |
||
45 | $offers[] = |
||
46 | $this->createOffer() |
||
47 | ->setId($id) |
||
48 | ->setCategoryId($id) |
||
49 | ; |
||
50 | } |
||
51 | |||
52 | return $offers; |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * Set the test description with CDATA here |
||
57 | * |
||
58 | * {@inheritdoc} |
||
59 | * |
||
60 | * @see \Bukashk0zzz\YmlGenerator\Tests\AbstractGeneratorTest::createOffer() |
||
61 | */ |
||
62 | protected function createOffer() |
||
63 | { |
||
64 | $offer = (new OfferSimple()) |
||
65 | ->setAvailable($this->faker->boolean) |
||
66 | ->setUrl($this->faker->url) |
||
67 | ->setPrice($this->faker->numberBetween(1, 9999)) |
||
68 | ->setOldPrice($this->faker->numberBetween(1, 9999)) |
||
69 | ->setWeight($this->faker->numberBetween(1, 9999)) |
||
70 | ->setCurrencyId('UAH') |
||
71 | ->setDelivery($this->faker->boolean) |
||
72 | ->setLocalDeliveryCost($this->faker->numberBetween(1, 9999)) |
||
73 | ->setSalesNotes($this->faker->text(45)) |
||
74 | ->setManufacturerWarranty($this->faker->boolean) |
||
75 | ->setCountryOfOrigin('Украина') |
||
76 | ->setDownloadable($this->faker->boolean) |
||
77 | ->setAdult($this->faker->boolean) |
||
78 | ->setMarketCategory($this->faker->word) |
||
79 | ->setCpa($this->faker->numberBetween(0, 1)) |
||
80 | ->setBarcodes([$this->faker->ean13, $this->faker->ean13]) |
||
81 | |||
82 | ->setName($this->faker->name) |
||
83 | ->setVendor($this->faker->company) |
||
84 | ->setDescription($this->faker->sentence) |
||
85 | ->setVendorCode(null) |
||
86 | ->setPickup(true) |
||
87 | ->setGroupId($this->faker->numberBetween()) |
||
88 | ->addPicture('http://example.com/example.jpeg') |
||
89 | ->addBarcode($this->faker->ean13) |
||
90 | |||
91 | ->setCustomElements(['custom_element' => [100500, 'string value']]) |
||
92 | ->addCustomElement('custom_element', true) |
||
93 | ->addCustomElement('custom_element', false) |
||
94 | ->addCustomElement('custom_element', null) // Should not be written |
||
95 | ->addCustomElement('custom_element', $cdata = new Cdata(self::CDATA_TEST_STRING)) |
||
96 | ->addCustomElement('stock_quantity', 100) // https://rozetka.com.ua/sellerinfo/pricelist/ |
||
97 | ; |
||
98 | |||
99 | $this->assertSame([100500, 'string value', true, false, $cdata], $offer->getCustomElementByType('custom_element')); |
||
100 | $this->assertSame([100], $offer->getCustomElementByType('stock_quantity')); |
||
101 | $this->assertSame([], $offer->getCustomElementByType('non_existent_element')); |
||
102 | |||
103 | return $offer; |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Load generated XML file and check custom elements |
||
108 | */ |
||
109 | private function checkCustomElements() |
||
110 | { |
||
111 | // Much easier to test with SimpleXML tahn with DOM |
||
112 | $yml = \simplexml_load_file($this->settings->getOutputFile()); |
||
113 | |||
114 | $offers = $yml->shop->offers->offer; |
||
115 | $this->assertNotEmpty($offers); |
||
116 | $this->assertEquals(self::OFFER_COUNT, \count($offers)); |
||
117 | |||
118 | foreach ($offers as $offer) { |
||
119 | $prop = 'stock_quantity'; |
||
120 | $this->assertSame(100, (int) $offer->$prop); // Can't use $offer->stock_quantity because of CS rules |
||
121 | |||
122 | $prop = 'custom_element'; |
||
123 | $multipleElements = $offer->$prop; // Can't use $offer->custom_element because of CS rules |
||
124 | $this->assertNotEmpty($multipleElements); |
||
125 | |||
126 | // Verity each added value |
||
127 | $this->assertSame(100500, (int) $multipleElements[0]); |
||
128 | $this->assertSame('string value', (string) $multipleElements[1]); |
||
129 | $this->assertSame('true', (string) $multipleElements[2]); |
||
130 | $this->assertSame('false', (string) $multipleElements[3]); |
||
131 | |||
132 | // ->addCustomElement('custom_element', null) must not produce an element |
||
133 | |||
134 | $this->assertSame(self::CDATA_TEST_STRING, (string) $multipleElements[4]); |
||
135 | } |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Create instance of Cdata class with a predefined test string |
||
140 | * |
||
141 | * @return \Bukashk0zzz\YmlGenerator\Cdata |
||
142 | */ |
||
143 | private function makeDescription() |
||
144 | { |
||
145 | return new Cdata(self::CDATA_TEST_STRING); |
||
146 | } |
||
147 | } |
||
148 |