Skip to content

Commit 4068f09

Browse files
authored
Merge pull request #26 from tarosky/fix/php-version-message
PHPバージョンメッセージ修正 & テスト追加
2 parents 61b25fa + 6f5b4b8 commit 4068f09

File tree

6 files changed

+248
-7
lines changed

6 files changed

+248
-7
lines changed

.github/workflows/test.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ jobs:
4141
php_version: ${{ matrix.php }}
4242
wp_version: ${{ matrix.wp }}
4343

44+
coverage:
45+
name: Code Coverage
46+
needs: [ test ]
47+
uses: tarosky/workflows/.github/workflows/wp-unit-test.yml@main
48+
with:
49+
php_version: '8.0'
50+
wp_version: latest
51+
coverage: true
52+
4453
assets:
4554
name: Check Assets
4655
uses: tarosky/workflows/.github/workflows/npm.yml@main

includes/functions.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ function tscp_get_expired_posts() {
5454
] );
5555
}
5656

57+
/**
58+
* Sanitize post types option value.
59+
*
60+
* @param mixed $value Raw option value.
61+
* @return string[] Filtered array of valid post type names.
62+
*/
63+
function tscp_sanitize_post_types( $value ) {
64+
return array_filter( (array) $value, function ( $v ) {
65+
return is_string( $v ) && post_type_exists( $v );
66+
} );
67+
}
68+
5769
/**
5870
* Check if post will be expired.
5971
*

includes/setting.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ function () {
5050
// Automatic save.
5151
register_setting( 'reading', 'tscp_post_types', [
5252
'type' => 'array',
53-
'sanitize_callback' => function ( $value ) {
54-
return array_filter( (array) $value, function ( $v ) {
55-
return is_string( $v ) && post_type_exists( $v );
56-
} );
57-
},
53+
'sanitize_callback' => 'tscp_sanitize_post_types',
5854
] );
5955
} );

taro-clockwork-post.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ function tscp_plugins_loaded() {
4545
* @package tscp
4646
*/
4747
function tscp_plugin_notice() {
48-
/* translators: %s current php version */
49-
$message = sprintf( __( '[Taro Clockwork Post] This plugin requires PHP 5.6.0 and over but your %s.', 'taro-clockwork-post' ), phpversion() );
48+
/* translators: %1$s required php version, %2$s current php version */
49+
$message = sprintf( __( '[Taro Clockwork Post] This plugin requires PHP %1$s and over but your %2$s.', 'taro-clockwork-post' ), '7.4', phpversion() );
5050
printf( '<div class="error"><p>%s</p></div>', esc_html( $message ) );
5151
}
5252

tests/test-rest-api.php

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
/**
3+
* REST API test
4+
*
5+
* @package tscp
6+
*/
7+
8+
/**
9+
* REST API test case.
10+
*/
11+
class Tscp_Rest_Api_Test extends WP_UnitTestCase {
12+
13+
/**
14+
* REST Server
15+
*
16+
* @var WP_REST_Server
17+
*/
18+
protected $server;
19+
20+
/**
21+
* Set up test fixtures.
22+
*/
23+
public function set_up() {
24+
parent::set_up();
25+
global $wp_rest_server;
26+
$wp_rest_server = new WP_REST_Server();
27+
$this->server = $wp_rest_server;
28+
do_action( 'rest_api_init' );
29+
}
30+
31+
/**
32+
* Tear down test fixtures.
33+
*/
34+
public function tear_down() {
35+
global $wp_rest_server;
36+
$wp_rest_server = null;
37+
parent::tear_down();
38+
}
39+
40+
/**
41+
* Test route is registered.
42+
*/
43+
public function test_route_registered() {
44+
$routes = $this->server->get_routes();
45+
$this->assertArrayHasKey( '/clockwork/v1/(?P<post_type>[^/]+)/(?P<post_id>\\d+)/expiration', $routes );
46+
}
47+
48+
/**
49+
* Test GET expiration returns defaults for new post.
50+
*/
51+
public function test_get_expiration_defaults() {
52+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
53+
wp_set_current_user( $user_id );
54+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
55+
56+
$request = new WP_REST_Request( 'GET', '/clockwork/v1/post/' . $post_id . '/expiration' );
57+
$response = $this->server->dispatch( $request );
58+
59+
$this->assertEquals( 200, $response->get_status() );
60+
$data = $response->get_data();
61+
$this->assertFalse( $data['should_expires'] );
62+
$this->assertEmpty( $data['expires'] );
63+
}
64+
65+
/**
66+
* Test POST saves expiration data with zero-padded date.
67+
*/
68+
public function test_post_expiration() {
69+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
70+
wp_set_current_user( $user_id );
71+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
72+
73+
$request = new WP_REST_Request( 'POST', '/clockwork/v1/post/' . $post_id . '/expiration' );
74+
$request->set_body_params( [
75+
'should' => true,
76+
'expires' => '2099-12-31 23:59:59',
77+
] );
78+
$response = $this->server->dispatch( $request );
79+
80+
$this->assertEquals( 200, $response->get_status() );
81+
$data = $response->get_data();
82+
$this->assertNotEmpty( $data['should_expires'] );
83+
$this->assertEquals( '2099-12-31 23:59:59', $data['expires'] );
84+
// Verify meta is saved.
85+
$this->assertEquals( '2099-12-31 23:59:59', get_post_meta( $post_id, '_tscp_expires', true ) );
86+
}
87+
88+
/**
89+
* Test POST with non-zero-padded date returns error (WP 6.9 bug scenario).
90+
*/
91+
public function test_post_non_padded_date_rejected() {
92+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
93+
wp_set_current_user( $user_id );
94+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
95+
96+
$request = new WP_REST_Request( 'POST', '/clockwork/v1/post/' . $post_id . '/expiration' );
97+
$request->set_body_params( [
98+
'should' => true,
99+
'expires' => '2026-4-3 14:55:59',
100+
] );
101+
$response = $this->server->dispatch( $request );
102+
103+
$this->assertEquals( 400, $response->get_status() );
104+
}
105+
106+
/**
107+
* Test POST with empty date succeeds (disabling expiration).
108+
*/
109+
public function test_post_empty_date() {
110+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
111+
wp_set_current_user( $user_id );
112+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
113+
114+
$request = new WP_REST_Request( 'POST', '/clockwork/v1/post/' . $post_id . '/expiration' );
115+
$request->set_body_params( [
116+
'should' => false,
117+
'expires' => '',
118+
] );
119+
$response = $this->server->dispatch( $request );
120+
121+
$this->assertEquals( 200, $response->get_status() );
122+
}
123+
124+
/**
125+
* Test unauthorized user cannot access.
126+
*/
127+
public function test_unauthorized_access() {
128+
wp_set_current_user( 0 );
129+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
130+
131+
$request = new WP_REST_Request( 'GET', '/clockwork/v1/post/' . $post_id . '/expiration' );
132+
$response = $this->server->dispatch( $request );
133+
134+
$this->assertEquals( 401, $response->get_status() );
135+
}
136+
137+
/**
138+
* Test invalid post type returns error.
139+
*/
140+
public function test_invalid_post_type() {
141+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
142+
wp_set_current_user( $user_id );
143+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
144+
145+
$request = new WP_REST_Request( 'GET', '/clockwork/v1/page/' . $post_id . '/expiration' );
146+
$response = $this->server->dispatch( $request );
147+
148+
$this->assertEquals( 400, $response->get_status() );
149+
}
150+
151+
/**
152+
* Test GET returns saved expiration data.
153+
*/
154+
public function test_get_saved_expiration() {
155+
$user_id = $this->factory()->user->create( [ 'role' => 'editor' ] );
156+
wp_set_current_user( $user_id );
157+
$post_id = $this->factory()->post->create( [ 'post_status' => 'publish' ] );
158+
159+
update_post_meta( $post_id, '_tscp_should_expire', 1 );
160+
update_post_meta( $post_id, '_tscp_expires', '2099-06-15 10:30:00' );
161+
162+
$request = new WP_REST_Request( 'GET', '/clockwork/v1/post/' . $post_id . '/expiration' );
163+
$response = $this->server->dispatch( $request );
164+
165+
$this->assertEquals( 200, $response->get_status() );
166+
$data = $response->get_data();
167+
$this->assertTrue( $data['should_expires'] );
168+
$this->assertEquals( '2099-06-15 10:30:00', $data['expires'] );
169+
}
170+
}

tests/test-settings.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* Settings test
4+
*
5+
* @package tscp
6+
*/
7+
8+
/**
9+
* Settings sanitize callback test case.
10+
*/
11+
class Tscp_Settings_Test extends WP_UnitTestCase {
12+
13+
/**
14+
* Test sanitize_callback filters invalid post types.
15+
*/
16+
public function test_sanitize_post_types() {
17+
$result = tscp_sanitize_post_types( [ 'post', 'nonexistent_type', 123, 'page' ] );
18+
19+
$this->assertContains( 'post', $result );
20+
$this->assertContains( 'page', $result );
21+
$this->assertNotContains( 'nonexistent_type', $result );
22+
$this->assertNotContains( 123, $result );
23+
}
24+
25+
/**
26+
* Test sanitize_callback with empty input.
27+
*/
28+
public function test_sanitize_empty_input() {
29+
$result = tscp_sanitize_post_types( [] );
30+
31+
$this->assertIsArray( $result );
32+
$this->assertEmpty( $result );
33+
}
34+
35+
/**
36+
* Test sanitize_callback with null input.
37+
*/
38+
public function test_sanitize_null_input() {
39+
$result = tscp_sanitize_post_types( null );
40+
41+
$this->assertIsArray( $result );
42+
$this->assertEmpty( $result );
43+
}
44+
45+
/**
46+
* Test sanitize_callback with all invalid values.
47+
*/
48+
public function test_sanitize_all_invalid() {
49+
$result = tscp_sanitize_post_types( [ 'fake_type', 42, true, '' ] );
50+
51+
$this->assertIsArray( $result );
52+
$this->assertEmpty( $result );
53+
}
54+
}

0 commit comments

Comments
 (0)