Completed
Push — master ( 3c661d...2a57f9 )
by Will
26s queued 12s
created

tests/php/Cart/ShoppingCartControllerTest.php (11 issues)

1
<?php
2
3
namespace SilverShop\Tests\Cart;
4
5
use SilverShop\Cart\ShoppingCart;
6
use SilverShop\Cart\ShoppingCartController;
7
use SilverShop\Model\Variation\Variation;
8
use SilverShop\Page\Product;
9
use SilverShop\Tests\Model\Product\CustomProduct_OrderItem;
10
use SilverShop\Tests\ShopTest;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\Dev\FunctionalTest;
13
use SilverStripe\Security\SecurityToken;
14
15
/**
16
 * @link ShoppingCart_Controller
17
 *
18
 * Test manipulating via urls.
19
 */
20
class ShoppingCartControllerTest extends FunctionalTest
21
{
22
    public static $fixture_file = __DIR__ . '/../Fixtures/shop.yml';
23
24
    public static $disable_theme = true;
25
    protected static $use_draft_site = false;
26
    protected $autoFollowRedirection = false;
27
28
    // This seems to be required, because we query the OrderItem table and thus this gets included…
29
    // TODO: Remove once we figure out how to circumvent that…
30
    protected static $extra_dataobjects = [
31
        CustomProduct_OrderItem::class,
32
    ];
33
34
    /**
35
     * @var Product
36
     */
37
    protected $mp3player;
38
39
    /**
40
     * @var Product
41
     */
42
    protected $socks;
43
44
    /**
45
     * @var Product
46
     */
47
    protected $noPurchaseProduct;
48
49
    /**
50
     * @var Product
51
     */
52
    protected $draftProduct;
53
54
    /**
55
     * @var Product
56
     */
57
    protected $noPriceProduct;
58
59
    /**
60
     * @var ShoppingCart
61
     */
62
    protected $cart;
63
64
65
    public function setUp()
66
    {
67
        parent::setUp();
68
69
        ShopTest::setConfiguration(); //reset config
70
        ShoppingCart::singleton()->clear();
71
72
        // Needed, so that products can be published
73
        $this->logInWithPermission('ADMIN');
74
75
        $this->mp3player = $this->objFromFixture(Product::class, 'mp3player');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->objFromFixture(Si...ct::class, 'mp3player') of type SilverStripe\ORM\DataObject is incompatible with the declared type SilverShop\Page\Product of property $mp3player.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
76
        $this->socks = $this->objFromFixture(Product::class, 'socks');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->objFromFixture(Si...roduct::class, 'socks') of type SilverStripe\ORM\DataObject is incompatible with the declared type SilverShop\Page\Product of property $socks.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
77
        //products that can't be purchased
78
        $this->noPurchaseProduct = $this->objFromFixture(Product::class, 'beachball');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->objFromFixture(Si...ct::class, 'beachball') of type SilverStripe\ORM\DataObject is incompatible with the declared type SilverShop\Page\Product of property $noPurchaseProduct.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
79
        $this->draftProduct = $this->objFromFixture(Product::class, 'tshirt');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->objFromFixture(Si...oduct::class, 'tshirt') of type SilverStripe\ORM\DataObject is incompatible with the declared type SilverShop\Page\Product of property $draftProduct.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
80
        $this->noPriceProduct = $this->objFromFixture(Product::class, 'hdtv');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->objFromFixture(Si...Product::class, 'hdtv') of type SilverStripe\ORM\DataObject is incompatible with the declared type SilverShop\Page\Product of property $noPriceProduct.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
81
82
        //publish some products
83
        $this->mp3player->publishSingle();
84
        $this->socks->publishSingle();
85
        $this->noPurchaseProduct->publishSingle();
86
        $this->noPriceProduct->publishSingle();
87
88
        $this->cart = ShoppingCart::singleton();
89
    }
90
91
    public function testAddToCart()
92
    {
93
        // add 2 of the same items via url
94
        $this->get(ShoppingCartController::add_item_link($this->mp3player)); //add item via url
0 ignored issues
show
It seems like SilverShop\Cart\Shopping..._link($this->mp3player) can also be of type false; however, parameter $url of SilverStripe\Dev\FunctionalTest::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
        $this->get(/** @scrutinizer ignore-type */ ShoppingCartController::add_item_link($this->mp3player)); //add item via url
Loading history...
95
        $this->get(ShoppingCartController::add_item_link($this->mp3player)); //add another
96
        $this->get(ShoppingCartController::add_item_link($this->socks)); //add a different product
97
        $this->get(ShoppingCartController::add_item_link($this->noPurchaseProduct));  //add a product that you can't add
98
        $this->get(ShoppingCartController::add_item_link($this->draftProduct));  //add a product that is draft
99
        $this->get(ShoppingCartController::add_item_link($this->noPriceProduct));  //add a product that has no price
100
101
        // See what's in the cart
102
        $items = ShoppingCart::curr()->Items();
103
        $this->assertNotNull($items);
104
105
        $this->assertEquals($items->Count(), 2, 'There are 2 items in the cart');
106
        //join needed to provide ProductID
107
        $mp3playeritem = $items
108
            ->innerJoin("SilverShop_Product_OrderItem", "\"SilverShop_OrderItem\".\"ID\" = \"SilverShop_Product_OrderItem\".\"ID\"")
109
            ->find('ProductID', $this->mp3player->ID);
110
111
        $this->assertNotNull($mp3playeritem, "Mp3 player is in cart");
112
113
        // We have the product that we asserted in our fixture file, with a quantity of 2 in the cart
114
        $this->assertEquals(
115
            $mp3playeritem->ProductID,
116
            $this->mp3player->ID,
117
            'We have the correct Product ID in the cart.'
118
        );
119
        $this->assertEquals($mp3playeritem->Quantity, 2, 'We have 2 of this product in the cart.');
120
121
        // set item quantiy
122
        $this->get(
123
            ShoppingCartController::set_quantity_item_link($this->mp3player, array('quantity' => 5))
124
        ); //add item via url
125
        $items = ShoppingCart::curr()->Items();
126
        $mp3playeritem =
127
            $items->innerJoin("SilverShop_Product_OrderItem", "\"SilverShop_OrderItem\".\"ID\" = \"SilverShop_Product_OrderItem\".\"ID\"")->find(
128
                'ProductID',
129
                $this->mp3player->ID
130
            ); //join needed to provide ProductID
131
        $this->assertEquals($mp3playeritem->Quantity, 5, 'We have 5 of this product in the cart.');
132
133
        // non purchasable product checks
134
        $this->assertEquals(
135
            $this->noPurchaseProduct->canPurchase(),
136
            false,
137
            'non-purcahseable product is not purchaseable'
138
        );
139
        $this->assertArrayNotHasKey(
140
            $this->noPurchaseProduct->ID,
141
            $items->map('ProductID')->toArray(),
142
            'non-purcahable product is not in cart'
143
        );
144
        $this->assertEquals($this->draftProduct->canPurchase(), true, 'draft products can be purchased');
145
        $this->assertArrayNotHasKey(
146
            $this->draftProduct->ID,
147
            $items->map('ProductID')->toArray(),
148
            'draft product is not in cart'
149
        );
150
        $this->assertEquals($this->noPriceProduct->canPurchase(), false, 'product without price is not purchaseable');
151
        $this->assertArrayNotHasKey(
152
            $this->noPriceProduct->ID,
153
            $items->map('ProductID')->toArray(),
154
            'product without price is not in cart'
155
        );
156
157
        $this->cart->clear();
158
    }
159
160
    public function testRemoveFromCart()
161
    {
162
163
        // add items via url
164
        $this->get(ShoppingCartController::set_quantity_item_link($this->mp3player, array('quantity' => 5)));
0 ignored issues
show
It seems like SilverShop\Cart\Shopping...array('quantity' => 5)) can also be of type false; however, parameter $url of SilverStripe\Dev\FunctionalTest::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

164
        $this->get(/** @scrutinizer ignore-type */ ShoppingCartController::set_quantity_item_link($this->mp3player, array('quantity' => 5)));
Loading history...
165
        $this->assertTrue($this->cart->get($this->mp3player) !== false, "mp3player item now exists in cart");
166
        $this->get(ShoppingCartController::add_item_link($this->socks));
167
        $this->assertTrue($this->cart->get($this->socks) !== false, "socks item now exists in cart");
168
169
        // remove items via url
170
        $this->get(ShoppingCartController::remove_item_link($this->socks)); //remove one different = remove completely
171
        $this->assertFalse((bool)$this->cart->get($this->socks));
172
173
        $this->get(ShoppingCartController::remove_item_link($this->mp3player)); //remove one product = 4 left
174
175
        $mp3playeritem = $this->cart->get($this->mp3player);
176
        $this->assertNotNull($mp3playeritem, "product still exists");
177
        $this->assertEquals($mp3playeritem->Quantity, 4, "only 4 of item left");
178
179
        $items = ShoppingCart::curr()->Items();
180
        $this->assertNotNull($items, "Cart is not empty");
181
182
        $this->cart->clear(); //test clearing cart
183
        $this->assertEquals(
184
            ShoppingCart::curr(),
185
            null,
186
            'Cart is clear'
187
        ); //items is a databoject set, and will therefore be null when cart is empty.
188
    }
189
190
    public function testSecurityToken()
191
    {
192
        $enabled = SecurityToken::is_enabled();
193
        // enable security tokens
194
        SecurityToken::enable();
195
196
        $productId = $this->mp3player->ID;
197
        // link should contain the security-token
198
        $link = ShoppingCartController::add_item_link($this->mp3player);
199
        $this->assertRegExp('{^shoppingcart/add/SilverShop-Page-Product/' . $productId . '\?SecurityID=[a-f0-9]+$}', $link);
0 ignored issues
show
It seems like $link can also be of type false; however, parameter $string of PHPUnit_Framework_Assert::assertRegExp() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

199
        $this->assertRegExp('{^shoppingcart/add/SilverShop-Page-Product/' . $productId . '\?SecurityID=[a-f0-9]+$}', /** @scrutinizer ignore-type */ $link);
Loading history...
200
201
        // should redirect back to the shop
202
        $response = $this->get($link);
203
        $this->assertEquals($response->getStatusCode(), 302);
204
205
        // disable security token for cart-links
206
        Config::modify()->set(ShoppingCartController::class, 'disable_security_token', true);
207
208
        $link = ShoppingCartController::add_item_link($this->mp3player);
209
        $this->assertEquals('shoppingcart/add/SilverShop-Page-Product/' . $productId, $link);
210
211
        // should redirect back to the shop
212
        $response = $this->get($link);
0 ignored issues
show
It seems like $link can also be of type false; however, parameter $url of SilverStripe\Dev\FunctionalTest::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

212
        $response = $this->get(/** @scrutinizer ignore-type */ $link);
Loading history...
213
        $this->assertEquals($response->getStatusCode(), 302);
214
215
        SecurityToken::disable();
216
217
        Config::modify()->set(ShoppingCartController::class, 'disable_security_token', false);
218
        $link = ShoppingCartController::add_item_link($this->mp3player);
219
        $this->assertEquals('shoppingcart/add/SilverShop-Page-Product/' . $productId, $link);
220
221
        // should redirect back to the shop
222
        $response = $this->get($link);
223
        $this->assertEquals($response->getStatusCode(), 302);
224
225
        SecurityToken::enable();
226
        // should now return a 400 status
227
        $response = $this->get($link);
228
        $this->assertEquals($response->getStatusCode(), 400);
229
230
        // restore previous setting
231
        if (!$enabled) {
232
            SecurityToken::disable();
233
        }
234
    }
235
236
    public function testVariations()
237
    {
238
        $this->loadFixture(__DIR__ . '/../Fixtures/variations.yml');
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Dev\SapphireTest::loadFixture() has been deprecated: 4.0.0:5.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

238
        /** @scrutinizer ignore-deprecated */ $this->loadFixture(__DIR__ . '/../Fixtures/variations.yml');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
239
        /**
240
         * @var Product $ballRoot
241
         */
242
        $ballRoot = $this->objFromFixture(Product::class, 'ball');
243
        $ballRoot->publishSingle();
244
        /**
245
         * @var Product $ball1
246
         */
247
        $ball1 = $this->objFromFixture(Variation::class, 'redlarge');
248
        /**
249
         * @var Product $ball2
250
         */
251
        $ball2 = $this->objFromFixture(Variation::class, 'redsmall');
252
253
        $this->logInWithPermission('ADMIN');
254
        $ball1->publishSingle();
255
        $ball2->publishSingle();
256
257
        // Add the two variation items
258
        $this->get(ShoppingCartController::add_item_link($ball1));
0 ignored issues
show
It seems like SilverShop\Cart\Shopping...::add_item_link($ball1) can also be of type false; however, parameter $url of SilverStripe\Dev\FunctionalTest::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

258
        $this->get(/** @scrutinizer ignore-type */ ShoppingCartController::add_item_link($ball1));
Loading history...
259
        $this->get(ShoppingCartController::add_item_link($ball2));
260
        $items = ShoppingCart::curr()->Items();
261
        $this->assertNotNull($items);
262
        $this->assertEquals($items->Count(), 2, 'There are 2 items in the cart');
263
264
        // Remove one and see what happens
265
        $this->get(ShoppingCartController::remove_all_item_link($ball1));
266
        $this->assertEquals($items->Count(), 1, 'There is 1 item in the cart');
267
        $this->assertFalse((bool)$this->cart->get($ball1), "first item not in cart");
268
        $this->assertNotNull($this->cart->get($ball2), "second item is in cart");
269
    }
270
}
271