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 |