Issues (334)

unit-tests/Tests/Version4/Orders.php (10 issues)

Labels
Severity
1
<?php
2
/**
3
 * Orders REST API tests.
4
 *
5
 * @package Automattic/WooCommerce/RestApi/Tests
6
 */
7
8
namespace Automattic\WooCommerce\RestApi\UnitTests\Tests\Version4;
9
10
defined( 'ABSPATH' ) || exit;
11
12
use Automattic\WooCommerce\RestApi\UnitTests\AbstractRestApiTest;
13
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
14
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
15
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\CustomerHelper;
16
17
/**
18
 * Abstract Rest API Test Class
19
 *
20
 * @extends AbstractRestApiTest
21
 */
22
class Orders extends AbstractRestApiTest {
23
	/**
24
	 * Routes that this endpoint creates.
25
	 *
26
	 * @var array
27
	 */
28
	protected $routes = [
29
		'/wc/v4/orders',
30
		'/wc/v4/orders/(?P<id>[\d]+)',
31
		'/wc/v4/orders/batch',
32
	];
33
34
	/**
35
	 * The endpoint schema.
36
	 *
37
	 * @var array Keys are property names, values are supported context.
38
	 */
39
	protected $properties = [
40
		'id'                   => array( 'view', 'edit' ),
41
		'parent_id'            => array( 'view', 'edit' ),
42
		'number'               => array( 'view', 'edit' ),
43
		'order_key'            => array( 'view', 'edit' ),
44
		'created_via'          => array( 'view', 'edit' ),
45
		'version'              => array( 'view', 'edit' ),
46
		'status'               => array( 'view', 'edit' ),
47
		'currency'             => array( 'view', 'edit' ),
48
		'currency_symbol'      => array( 'view', 'edit' ),
49
		'date_created'         => array( 'view', 'edit' ),
50
		'date_created_gmt'     => array( 'view', 'edit' ),
51
		'date_modified'        => array( 'view', 'edit' ),
52
		'date_modified_gmt'    => array( 'view', 'edit' ),
53
		'discount_total'       => array( 'view', 'edit' ),
54
		'discount_tax'         => array( 'view', 'edit' ),
55
		'shipping_total'       => array( 'view', 'edit' ),
56
		'shipping_tax'         => array( 'view', 'edit' ),
57
		'cart_tax'             => array( 'view', 'edit' ),
58
		'total'                => array( 'view', 'edit' ),
59
		'total_tax'            => array( 'view', 'edit' ),
60
		'prices_include_tax'   => array( 'view', 'edit' ),
61
		'customer_id'          => array( 'view', 'edit' ),
62
		'customer_ip_address'  => array( 'view', 'edit' ),
63
		'customer_user_agent'  => array( 'view', 'edit' ),
64
		'customer_note'        => array( 'view', 'edit' ),
65
		'billing'              => array( 'view', 'edit' ),
66
		'shipping'             => array( 'view', 'edit' ),
67
		'payment_method'       => array( 'view', 'edit' ),
68
		'payment_method_title' => array( 'view', 'edit' ),
69
		'transaction_id'       => array( 'view', 'edit' ),
70
		'date_paid'            => array( 'view', 'edit' ),
71
		'date_paid_gmt'        => array( 'view', 'edit' ),
72
		'date_completed'       => array( 'view', 'edit' ),
73
		'date_completed_gmt'   => array( 'view', 'edit' ),
74
		'cart_hash'            => array( 'view', 'edit' ),
75
		'meta_data'            => array( 'view', 'edit' ),
76
		'line_items'           => array( 'view', 'edit' ),
77
		'tax_lines'            => array( 'view', 'edit' ),
78
		'shipping_lines'       => array( 'view', 'edit' ),
79
		'fee_lines'            => array( 'view', 'edit' ),
80
		'coupon_lines'         => array( 'view', 'edit' ),
81
		'refunds'              => array( 'view', 'edit' ),
82
		'set_paid'             => array( 'edit' ),
83
	];
84
85
	/**
86
	 * Test create.
87
	 */
88
	public function test_create() {
89
		$product = ProductHelper::create_simple_product();
90
		$data    = [
91
			'currency'             => 'ZAR',
92
			'customer_id'          => 1,
93
			'customer_note'        => 'I am a note',
94
			'transaction_id'       => 'test',
95
			'payment_method'       => 'bacs',
96
			'payment_method_title' => 'Direct Bank Transfer',
97
			'set_paid'             => true,
98
			'billing'              => array(
99
				'first_name' => 'John',
100
				'last_name'  => 'Doe',
101
				'company'    => '',
102
				'address_1'  => '969 Market',
103
				'address_2'  => '',
104
				'city'       => 'San Francisco',
105
				'state'      => 'CA',
106
				'postcode'   => '94103',
107
				'country'    => 'US',
108
				'email'      => '[email protected]',
109
				'phone'      => '(555) 555-5555',
110
			),
111
			'shipping'             => array(
112
				'first_name' => 'John',
113
				'last_name'  => 'Doe',
114
				'company'    => '',
115
				'address_1'  => '969 Market',
116
				'address_2'  => '',
117
				'city'       => 'San Francisco',
118
				'state'      => 'CA',
119
				'postcode'   => '94103',
120
				'country'    => 'US',
121
			),
122
			'line_items'           => array(
123
				array(
124
					'product_id' => $product->get_id(),
125
					'quantity'   => 2,
126
				),
127
			),
128
			'shipping_lines'       => array(
129
				array(
130
					'method_id'    => 'flat_rate',
131
					'method_title' => 'Flat rate',
132
					'total'        => '10.00',
133
				),
134
			),
135
		];
136
		$response = $this->do_request( '/wc/v4/orders', 'POST', $data );
137
		$this->assertExpectedResponse( $response, 201, $data );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

137
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 201, $data );
Loading history...
138
	}
139
140
		/**
141
	 * Test the sanitization of the payment_method_title field through the API.
142
	 *
143
	 * @since 3.5.2
144
	 */
145
	public function test_create_update_order_payment_method_title_sanitize() {
146
		$product = ProductHelper::create_simple_product();
147
		$data    = [
148
			'payment_method'       => 'bacs',
149
			'payment_method_title' => '<h1>Sanitize this <script>alert(1);</script></h1>',
150
			'set_paid'             => true,
151
			'billing'              => array(
152
				'first_name' => 'John',
153
				'last_name'  => 'Doe',
154
				'address_1'  => '969 Market',
155
				'address_2'  => '',
156
				'city'       => 'San Francisco',
157
				'state'      => 'CA',
158
				'postcode'   => '94103',
159
				'country'    => 'US',
160
				'email'      => '[email protected]',
161
				'phone'      => '(555) 555-5555',
162
			),
163
			'shipping'             => array(
164
				'first_name' => 'John',
165
				'last_name'  => 'Doe',
166
				'address_1'  => '969 Market',
167
				'address_2'  => '',
168
				'city'       => 'San Francisco',
169
				'state'      => 'CA',
170
				'postcode'   => '94103',
171
				'country'    => 'US',
172
			),
173
			'line_items'           => array(
174
				array(
175
					'product_id' => $product->get_id(),
176
					'quantity'   => 2,
177
				),
178
			),
179
			'shipping_lines'       => array(
180
				array(
181
					'method_id'    => 'flat_rate',
182
					'method_title' => 'Flat rate',
183
					'total'        => '10',
184
				),
185
			),
186
		];
187
		$response = $this->do_request( '/wc/v4/orders', 'POST', $data );
188
		$order    = wc_get_order( $response->data['id'] );
189
		$this->assertExpectedResponse( $response, 201 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

189
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 201 );
Loading history...
190
		$this->assertEquals( $order->get_payment_method(), $response->data['payment_method'] );
191
		$this->assertEquals( $order->get_payment_method_title(), 'Sanitize this' );
192
193
		// Test when updating order.
194
		$response = $this->do_request(
195
			'/wc/v4/orders/' . $response->data['id'],
196
			'POST', [
197
				'payment_method'       => 'bacs',
198
				'payment_method_title' => '<h1>Sanitize this too <script>alert(1);</script></h1>',
199
			]
200
		);
201
		$order    = wc_get_order( $response->data['id'] );
202
		$this->assertExpectedResponse( $response, 200 );
203
		$this->assertEquals( $order->get_payment_method(), $response->data['payment_method'] );
204
		$this->assertEquals( $order->get_payment_method_title(), 'Sanitize this too' );
205
	}
206
207
	/**
208
	 * Tests creating an order without required fields.
209
	 * @since 3.5.0
210
	 */
211
	public function test_create_order_invalid_fields() {
212
		$product = ProductHelper::create_simple_product();
213
		$data    = [
214
			'payment_method'       => 'bacs',
215
			'payment_method_title' => 'Direct Bank Transfer',
216
			'set_paid'             => true,
217
			'customer_id'          => 99999,
218
			'billing'              => array(
219
				'first_name' => 'John',
220
				'last_name'  => 'Doe',
221
				'address_1'  => '969 Market',
222
				'address_2'  => '',
223
				'city'       => 'San Francisco',
224
				'state'      => 'CA',
225
				'postcode'   => '94103',
226
				'country'    => 'US',
227
				'email'      => '[email protected]',
228
				'phone'      => '(555) 555-5555',
229
			),
230
			'shipping'             => array(
231
				'first_name' => 'John',
232
				'last_name'  => 'Doe',
233
				'address_1'  => '969 Market',
234
				'address_2'  => '',
235
				'city'       => 'San Francisco',
236
				'state'      => 'CA',
237
				'postcode'   => '94103',
238
				'country'    => 'US',
239
			),
240
			'line_items'           => array(
241
				array(
242
					'product_id' => $product->get_id(),
243
					'quantity'   => 2,
244
				),
245
			),
246
			'shipping_lines'       => array(
247
				array(
248
					'method_id'    => 'flat_rate',
249
					'method_title' => 'Flat rate',
250
					'total'        => 10,
251
				),
252
			),
253
		];
254
		$response = $this->do_request( '/wc/v4/orders', 'POST', $data );
255
		$this->assertExpectedResponse( $response, 400 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

255
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 400 );
Loading history...
256
	}
257
258
	/**
259
	 * Test read.
260
	 */
261
	public function test_read() {
262
		$product  = ProductHelper::create_simple_product();
263
		$product->set_regular_price( 10.95 );
264
		$product->set_sale_price( false );
0 ignored issues
show
false of type false is incompatible with the type string expected by parameter $price of WC_Product::set_sale_price(). ( Ignorable by Annotation )

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

264
		$product->set_sale_price( /** @scrutinizer ignore-type */ false );
Loading history...
265
		$product->save();
266
		$customer = CustomerHelper::create_customer();
267
		$orders   = [];
268
		$orders[] = OrderHelper::create_order( $customer->get_id(), $product );
269
270
		// Create orders.
271
		for ( $i = 0; $i < 9; $i++ ) {
272
			$orders[] = OrderHelper::create_order( $this->user );
0 ignored issues
show
$this->user of type Automattic\WooCommerce\RestApi\UnitTests\WP_User is incompatible with the type integer expected by parameter $customer_id of Automattic\WooCommerce\R...rHelper::create_order(). ( Ignorable by Annotation )

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

272
			$orders[] = OrderHelper::create_order( /** @scrutinizer ignore-type */ $this->user );
Loading history...
273
		}
274
275
		$orders[5]->set_status( 'on-hold' );
276
		$orders[5]->save();
277
		$orders[6]->set_status( 'on-hold' );
278
		$orders[6]->save();
279
		$orders[0]->calculate_totals();
280
		$orders[0]->save();
281
282
		// Collection.
283
		$response = $this->do_request( '/wc/v4/orders', 'GET' );
284
		$this->assertExpectedResponse( $response, 200 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

284
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 200 );
Loading history...
285
		$this->assertEquals( 10, count( $response->data ) );
286
287
		// Collection args.
288
		$response = $this->do_request( '/wc/v4/orders', 'GET', [ 'status' => 'on-hold' ] );
289
		$this->assertExpectedResponse( $response, 200 );
290
		$this->assertEquals( 2, count( $response->data ) );
291
292
		$response = $this->do_request( '/wc/v4/orders', 'GET', [ 'number' => (string) $orders[0]->get_id() ] );
293
		$this->assertExpectedResponse( $response, 200 );
294
		$this->assertEquals( 1, count( $response->data ) );
295
296
		$response = $this->do_request( '/wc/v4/orders', 'GET', [ 'customer' => $customer->get_id() ] );
297
		$this->assertExpectedResponse( $response, 200 );
298
		$this->assertEquals( 1, count( $response->data ) );
299
300
		$response = $this->do_request( '/wc/v4/orders', 'GET', [ 'product' => $product->get_id() ] );
301
		$this->assertExpectedResponse( $response, 200 );
302
		$this->assertEquals( 1, count( $response->data ) );
303
304
		// Single collection args.
305
		$response = $this->do_request( '/wc/v4/orders/' . $orders[0]->get_id(), 'GET', [ 'dp' => 0 ] );
306
		$this->assertEquals( '54', $response->data['total'] );
307
		$response = $this->do_request( '/wc/v4/orders/' . $orders[0]->get_id(), 'GET', [ 'dp' => 2 ] );
308
		$this->assertEquals( '53.80', $response->data['total'] );
309
310
		// Single.
311
		$response = $this->do_request( '/wc/v4/orders/' . $orders[0]->get_id(), 'GET' );
312
		$this->assertExpectedResponse( $response, 200 );
313
314
		foreach ( $this->get_properties( 'view' ) as $property ) {
315
			$this->assertArrayHasKey( $property, $response->data );
316
		}
317
318
		// Invalid.
319
		$response = $this->do_request( '/wc/v4/orders/0', 'GET' );
320
		$this->assertExpectedResponse( $response, 404 );
321
	}
322
323
	/**
324
	 * Test update.
325
	 */
326
	public function test_update() {
327
		// Invalid.
328
		$response = $this->do_request( '/wc/v4/orders/0', 'POST', [ 'payment_method' => 'test' ] );
329
		$this->assertExpectedResponse( $response, 404 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

329
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 404 );
Loading history...
330
331
		// Update existing.
332
		$order    = OrderHelper::create_order();
333
		$data     = [
334
			'payment_method' => 'test-update',
335
			'billing'        => array(
336
				'first_name' => 'Fish',
337
				'last_name'  => 'Face',
338
			),
339
		];
340
		$response = $this->do_request(
341
			'/wc/v4/orders/' . $order->get_id(),
342
			'POST',
343
			$data
344
		);
345
		$this->assertExpectedResponse( $response, 200, $data );
346
347
		foreach ( $this->get_properties( 'view' ) as $property ) {
348
			$this->assertArrayHasKey( $property, $response->data );
349
		}
350
	}
351
352
	/**
353
	 * Test delete.
354
	 */
355
	public function test_delete() {
356
		// Invalid.
357
		$result = $this->do_request( '/wc/v4/orders/0', 'DELETE', [ 'force' => false ] );
358
		$this->assertEquals( 404, $result->status );
359
360
		// Trash.
361
		$order  = OrderHelper::create_order();
362
		$result = $this->do_request( '/wc/v4/orders/' . $order->get_id(), 'DELETE', [ 'force' => false ] );
363
		$this->assertEquals( 200, $result->status );
364
		$this->assertEquals( 'trash', get_post_status( $order->get_id() ) );
365
366
		// Force.
367
		$order  = OrderHelper::create_order();
368
		$result = $this->do_request( '/wc/v4/orders/' . $order->get_id(), 'DELETE', [ 'force' => true ] );
369
		$this->assertEquals( 200, $result->status );
370
		$this->assertEquals( false, get_post( $order->get_id() ) );
371
	}
372
373
	/**
374
	 * Test read.
375
	 */
376
	public function test_guest_create() {
377
		wp_set_current_user( 0 );
378
		$product = ProductHelper::create_simple_product();
379
		$data    = [
380
			'currency'             => 'ZAR',
381
			'customer_id'          => 1,
382
			'customer_note'        => 'I am a note',
383
			'transaction_id'       => 'test',
384
			'payment_method'       => 'bacs',
385
			'payment_method_title' => 'Direct Bank Transfer',
386
			'set_paid'             => true,
387
			'billing'              => array(
388
				'first_name' => 'John',
389
				'last_name'  => 'Doe',
390
				'company'    => '',
391
				'address_1'  => '969 Market',
392
				'address_2'  => '',
393
				'city'       => 'San Francisco',
394
				'state'      => 'CA',
395
				'postcode'   => '94103',
396
				'country'    => 'US',
397
				'email'      => '[email protected]',
398
				'phone'      => '(555) 555-5555',
399
			),
400
			'shipping'             => array(
401
				'first_name' => 'John',
402
				'last_name'  => 'Doe',
403
				'company'    => '',
404
				'address_1'  => '969 Market',
405
				'address_2'  => '',
406
				'city'       => 'San Francisco',
407
				'state'      => 'CA',
408
				'postcode'   => '94103',
409
				'country'    => 'US',
410
			),
411
			'line_items'           => array(
412
				array(
413
					'product_id' => $product->get_id(),
414
					'quantity'   => 2,
415
				),
416
			),
417
			'shipping_lines'       => array(
418
				array(
419
					'method_id'    => 'flat_rate',
420
					'method_title' => 'Flat rate',
421
					'total'        => '10',
422
				),
423
			),
424
		];
425
		$response = $this->do_request( '/wc/v4/orders', 'POST', $data );
426
		$this->assertExpectedResponse( $response, 401, $data );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

426
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 401, $data );
Loading history...
427
	}
428
429
	/**
430
	 * Test read.
431
	 */
432
	public function test_guest_read() {
433
		wp_set_current_user( 0 );
434
		$response = $this->do_request( '/wc/v4/orders', 'GET' );
435
		$this->assertExpectedResponse( $response, 401 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

435
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 401 );
Loading history...
436
	}
437
438
	/**
439
	 * Test update.
440
	 */
441
	public function test_guest_update() {
442
		wp_set_current_user( 0 );
443
		$order    = OrderHelper::create_order();
444
		$data     = [
445
			'payment_method' => 'test-update',
446
			'billing'        => array(
447
				'first_name' => 'Fish',
448
				'last_name'  => 'Face',
449
			),
450
		];
451
		$response = $this->do_request(
452
			'/wc/v4/orders/' . $order->get_id(),
453
			'POST',
454
			$data
455
		);
456
		$this->assertExpectedResponse( $response, 401 );
0 ignored issues
show
$response of type object is incompatible with the type array expected by parameter $response of Automattic\WooCommerce\R...ssertExpectedResponse(). ( Ignorable by Annotation )

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

456
		$this->assertExpectedResponse( /** @scrutinizer ignore-type */ $response, 401 );
Loading history...
457
	}
458
459
	/**
460
	 * Test delete.
461
	 */
462
	public function test_guest_delete() {
463
		wp_set_current_user( 0 );
464
		$order    = OrderHelper::create_order();
465
		$response = $this->do_request( '/wc/v4/orders/' . $order->get_id(), 'DELETE', [ 'force' => true ] );
466
		$this->assertEquals( 401, $response->status );
467
	}
468
469
	/**
470
	 * Test validation.
471
	 */
472
	public function test_enums() {
473
		$order    = OrderHelper::create_order();
474
475
		$response = $this->do_request(
476
			'/wc/v4/orders/' . $order->get_id(),
477
			'POST',
478
			[
479
				'status' => 'invalid',
480
			]
481
		);
482
		$this->assertEquals( 400, $response->status );
483
		$this->assertEquals( 'Invalid parameter(s): status', $response->data['message'] );
484
485
		$response = $this->do_request(
486
			'/wc/v4/orders/' . $order->get_id(),
487
			'POST',
488
			[
489
				'currency' => 'invalid',
490
			]
491
		);
492
		$this->assertEquals( 400, $response->status );
493
		$this->assertEquals( 'Invalid parameter(s): currency', $response->data['message'] );
494
	}
495
496
	/**
497
	 * Test a batch update.
498
	 */
499
	public function test_batch() {
500
		$order1 = OrderHelper::create_order();
501
		$order2 = OrderHelper::create_order();
502
		$order3 = OrderHelper::create_order();
503
504
		$result = $this->do_request(
505
			'/wc/v4/orders/batch',
506
			'POST',
507
			array(
508
				'update' => array(
509
					array(
510
						'id'             => $order1->get_id(),
511
						'payment_method' => 'updated',
512
					),
513
				),
514
				'delete' => array(
515
					$order2->get_id(),
516
					$order3->get_id(),
517
				),
518
			)
519
		);
520
		$this->assertEquals( 'updated', $result->data['update'][0]['payment_method'] );
521
		$this->assertEquals( $order2->get_id(), $result->data['delete'][0]['previous']['id'] );
522
		$this->assertEquals( $order3->get_id(), $result->data['delete'][1]['previous']['id'] );
523
524
		$result = $this->do_request( '/wc/v4/orders' );
525
		$this->assertEquals( 1, count( $result->data ) );
526
	}
527
528
	/**
529
	 * Tests updating an order and removing items.
530
	 *
531
	 * @since 3.5.0
532
	 */
533
	public function test_update_order_remove_items() {
534
		$order = OrderHelper::create_order();
535
		$fee   = new \WC_Order_Item_Fee();
536
		$fee->set_props(
537
			array(
538
				'name'       => 'Some Fee',
539
				'tax_status' => 'taxable',
540
				'total'      => '100',
541
				'tax_class'  => '',
542
			)
543
		);
544
		$order->add_item( $fee );
545
		$order->save();
546
547
		$fee_data = current( $order->get_items( 'fee' ) );
548
		$response = $this->do_request(
549
			'/wc/v4/orders/' . $order->get_id(),
550
			'PUT',
551
			[
552
				'fee_lines' => array(
553
					array(
554
						'id'   => $fee_data->get_id(),
555
						'name' => null,
556
					),
557
				),
558
			]
559
		);
560
		$this->assertEquals( 200, $response->status );
561
		$this->assertTrue( empty( $response->data['fee_lines'] ) );
562
	}
563
564
	/**
565
	 * Tests updating an order and adding a coupon.
566
	 *
567
	 * @since 3.5.0
568
	 */
569
	public function test_update_order_add_coupons() {
570
		$order      = OrderHelper::create_order();
571
		$order_item = current( $order->get_items() );
572
		$coupon     = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\CouponHelper::create_coupon( 'fake-coupon' );
573
		$coupon->set_amount( 5 );
574
		$coupon->save();
575
576
		$response = $this->do_request(
577
			'/wc/v4/orders/' . $order->get_id(),
578
			'PUT',
579
			[
580
				'coupon_lines' => array(
581
					array(
582
						'code' => 'fake-coupon',
583
					),
584
				),
585
			]
586
		);
587
		$this->assertEquals( 200, $response->status );
588
		$this->assertCount( 1, $response->data['coupon_lines'] );
589
		$this->assertEquals( '45.00', $response->data['total'] );
590
	}
591
592
	/**
593
	 * Tests updating an order and removing a coupon.
594
	 *
595
	 * @since 3.5.0
596
	 */
597
	public function test_update_order_remove_coupons() {
598
		$order      = OrderHelper::create_order();
599
		$order_item = current( $order->get_items() );
600
		$coupon     = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\CouponHelper::create_coupon( 'fake-coupon' );
601
		$coupon->set_amount( 5 );
602
		$coupon->save();
603
		$order->apply_coupon( $coupon );
604
		$order->save();
605
606
		// Check that the coupon is applied.
607
		$this->assertEquals( '45.00', $order->get_total() );
608
609
		$coupon_data = current( $order->get_items( 'coupon' ) );
610
		$response    = $this->do_request(
611
			'/wc/v4/orders/' . $order->get_id(),
612
			'PUT',
613
			[
614
				'coupon_lines' => array(
615
					array(
616
						'id'   => $coupon_data->get_id(),
617
						'code' => null,
618
					),
619
				),
620
				'line_items'   => array(
621
					array(
622
						'id'         => $order_item->get_id(),
623
						'product_id' => $order_item->get_product_id(),
624
						'total'      => '40.00',
625
					),
626
				),
627
			]
628
		);
629
		$this->assertEquals( 200, $response->status );
630
		$this->assertTrue( empty( $response->data['coupon_lines'] ) );
631
		$this->assertEquals( '50.00', $response->data['total'] );
632
	}
633
634
	/**
635
	 * Tests updating an order with an invalid coupon.
636
	 *
637
	 * @since 3.5.0
638
	 */
639
	public function test_invalid_coupon() {
640
		$order    = OrderHelper::create_order();
641
		$response = $this->do_request(
642
			'/wc/v4/orders/' . $order->get_id(),
643
			'PUT',
644
			[
645
				'coupon_lines' => array(
646
					array(
647
						'code' => 'NON_EXISTING_COUPON',
648
					),
649
				),
650
			]
651
		);
652
		$this->assertEquals( 400, $response->status );
653
		$this->assertEquals( 'woocommerce_rest_invalid_coupon', $response->data['code'] );
654
		$this->assertEquals( 'Coupon "non_existing_coupon" does not exist!', $response->data['message'] );
655
	}
656
}
657