diff --git a/.env.dist.testing b/.env.dist.testing index 19caaa5..0ceb7d2 100644 --- a/.env.dist.testing +++ b/.env.dist.testing @@ -7,7 +7,7 @@ TEST_SITE_TABLE_PREFIX=wp_ TEST_SITE_ADMIN_USERNAME=admin TEST_SITE_ADMIN_PASSWORD=password TEST_SITE_WP_ADMIN_PATH=/wp-admin -WP_ROOT_FOLDER="/home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress" +WP_ROOT_FOLDER="/var/www/html" WP_ENVIRONMENT_TYPE=local TEST_DB_NAME=test TEST_DB_HOST=localhost @@ -17,7 +17,7 @@ TEST_TABLE_PREFIX=wp_ TEST_SITE_WP_URL=http://127.0.0.1 TEST_SITE_WP_DOMAIN=127.0.0.1 TEST_SITE_ADMIN_EMAIL=wordpress@convertkit.local -TEST_SITE_CONFIG_FILE="/home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress/wp-content/plugins/convertkit-wordpress-libraries/tests/_support/WpunitTesterConfig.php" +TEST_SITE_CONFIG_FILE="/var/www/html/wp-content/plugins/convertkit-wordpress-libraries/tests/_support/WpunitTesterConfig.php" CONVERTKIT_API_BROADCAST_ID="8697158" CONVERTKIT_API_CUSTOM_FIELD_ID="258240" CONVERTKIT_API_FORM_ID="2765139" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ded4e07..fa5fba9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,15 +17,15 @@ jobs: # Virtual Environment to use. # @see: https://github.com/actions/virtual-environments - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest # Environment Variables. # Accessible by using ${{ env.NAME }} # Use ${{ secrets.NAME }} to include any GitHub Secrets in ${{ env.NAME }} # The base folder will always be /home/runner/work/github-repo-name/github-repo-name env: - ROOT_DIR: /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress - PLUGIN_DIR: /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress/wp-content/plugins/convertkit-wordpress-libraries + ROOT_DIR: /var/www/html + PLUGIN_DIR: /var/www/html/wp-content/plugins/convertkit-wordpress-libraries DB_NAME: test DB_USER: root DB_PASS: root @@ -51,6 +51,13 @@ jobs: # Steps to install, configure and run tests steps: + # Checkout Plugin to /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/convertkit-wordpress-libraries + # We cannot checkout to ${{ env.PLUGIN_DIR }} as GitHub Actions require it be first placed in /home/runner/work/repo/repo + - name: Checkout Plugin + uses: actions/checkout@v4 + with: + path: /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/convertkit-wordpress-libraries + - name: Start MySQL run: sudo systemctl start mysql.service @@ -65,17 +72,15 @@ jobs: # Some workflows checkout WordPress from GitHub, but that seems to bring a bunch of uncompiled files with it. # Instead download from wordpress.org stable. - - name: Download WordPress - run: wget https://wordpress.org/wordpress-${{ matrix.wp-versions }}.tar.gz - - - name: Extract WordPress - run: tar xfz wordpress-${{ matrix.wp-versions }}.tar.gz - - # Checkout (copy) this repository's Plugin to this VM. - - name: Checkout Plugin - uses: actions/checkout@v4 - with: - path: ${{ env.PLUGIN_DIR }} + - name: Download and Extract WordPress + run: | + sudo chown -R runner:docker /var/www/html + ls -la /var/www/html + cd /var/www/html + wget https://wordpress.org/wordpress-${{ matrix.wp-versions }}.tar.gz + tar xfz wordpress-${{ matrix.wp-versions }}.tar.gz + mv wordpress/* . + rm -rf wordpress wordpress-${{ matrix.wp-versions }}.tar.gz # We install WP-CLI, as it provides useful commands to setup and install WordPress through the command line. - name: Install WP-CLI @@ -97,6 +102,10 @@ jobs: working-directory: ${{ env.ROOT_DIR }} run: wp-cli plugin install ${{ env.INSTALL_PLUGINS }} + # Move Plugin + - name: Move Plugin + run: mv /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/convertkit-wordpress-libraries ${{ env.PLUGIN_DIR }} + # Install PHP version to run tests against. - name: Install PHP uses: shivammathur/setup-php@v2 diff --git a/phpcs.xml b/phpcs.xml index 1e875f4..11ae28a 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -14,8 +14,8 @@ class-convertkit-api-traits.php - - + + + - - - diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 7dc6e9e..2cf5ef8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -16,11 +16,11 @@ parameters: # Location of WordPress Plugins for PHPStan to scan, building symbols. scanDirectories: - - /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress/wp-content/plugins + - /var/www/html/wp-content/plugins # Location of constants for PHPStan to scan, building symbols. scanFiles: - - /home/runner/work/convertkit-wordpress-libraries/convertkit-wordpress-libraries/wordpress/wp-config.php + - /var/www/html/wp-config.php # Don't report unmatched ignored errors on older PHP versions (7.2, 7.3) reportUnmatchedIgnoredErrors: false diff --git a/src/class-convertkit-api-v4.php b/src/class-convertkit-api-v4.php index cfde53e..3b72f5b 100644 --- a/src/class-convertkit-api-v4.php +++ b/src/class-convertkit-api-v4.php @@ -492,6 +492,7 @@ public function get_access_token_by_api_key_and_secret( $api_key, $api_secret ) array( 'api_key' => $api_key, 'api_secret' => $api_secret, + 'client_id' => $this->client_id, ) ); diff --git a/tests/wpunit/APITest.php b/tests/wpunit/APITest.php index 27f2d03..b7531a9 100644 --- a/tests/wpunit/APITest.php +++ b/tests/wpunit/APITest.php @@ -604,6 +604,38 @@ public function testGetAccessTokenByInvalidAPIKeyAndSecret() $this->assertEquals('Authorization Failed: API Secret not valid', $result->get_error_message()); } + /** + * Test that fetching an Access Token using an invalid client ID returns a WP_Error. + * + * @since 2.0.7 + */ + public function testGetAccessTokenByAPIKeyAndSecretWithInvalidClientID() + { + $api = new ConvertKit_API_V4( 'invalidClientID', $_ENV['CONVERTKIT_OAUTH_REDIRECT_URI'] ); + $result = $api->get_access_token_by_api_key_and_secret( + $_ENV['CONVERTKIT_API_KEY'], + $_ENV['CONVERTKIT_API_SECRET'] + ); + $this->assertInstanceOf(WP_Error::class, $result); + $this->assertEquals($result->get_error_code(), $this->errorCode); + } + + /** + * Test that fetching an Access Token using a blank client ID returns a WP_Error. + * + * @since 2.0.7 + */ + public function testGetAccessTokenByAPIKeyAndSecretWithBlankClientID() + { + $api = new ConvertKit_API_V4( '', $_ENV['CONVERTKIT_OAUTH_REDIRECT_URI'] ); + $result = $api->get_access_token_by_api_key_and_secret( + $_ENV['CONVERTKIT_API_KEY'], + $_ENV['CONVERTKIT_API_SECRET'] + ); + $this->assertInstanceOf(WP_Error::class, $result); + $this->assertEquals($result->get_error_code(), $this->errorCode); + } + /** * Test that supplying valid API credentials to the API class returns the expected account information. * @@ -756,8 +788,9 @@ public function testGetGrowthStatsWithStartDate() $this->assertArrayHasKey('ending', $result['stats']); // Assert start and end dates were honored. - $this->assertEquals($result['stats']['starting'], $starting->format('Y-m-d') . 'T00:00:00-05:00'); - $this->assertEquals($result['stats']['ending'], $ending->format('Y-m-d') . 'T23:59:59-05:00'); + $timezone = ( new DateTime() )->setTimezone(new DateTimeZone('America/New_York'))->format('P'); // Gets timezone offset for New York (-04:00 during DST, -05:00 otherwise). + $this->assertEquals($result['stats']['starting'], $starting->format('Y-m-d') . 'T00:00:00' . $timezone); + $this->assertEquals($result['stats']['ending'], $ending->format('Y-m-d') . 'T23:59:59' . $timezone); } /** @@ -790,8 +823,9 @@ public function testGetGrowthStatsWithEndDate() $this->assertArrayHasKey('ending', $result['stats']); // Assert start and end dates were honored. - $this->assertEquals($result['stats']['starting'], $starting->format('Y-m-d') . 'T00:00:00-05:00'); - $this->assertEquals($result['stats']['ending'], $ending->format('Y-m-d') . 'T23:59:59-05:00'); + $timezone = ( new DateTime() )->setTimezone(new DateTimeZone('America/New_York'))->format('P'); // Gets timezone offset for New York (-04:00 during DST, -05:00 otherwise). + $this->assertEquals($result['stats']['starting'], $starting->format('Y-m-d') . 'T00:00:00' . $timezone); + $this->assertEquals($result['stats']['ending'], $ending->format('Y-m-d') . 'T23:59:59' . $timezone); } /** @@ -1249,7 +1283,7 @@ public function testGetFormSubscriptionsWithBouncedSubscriberState() */ public function testGetFormSubscriptionsWithAddedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_form_subscriptions( (int) $_ENV['CONVERTKIT_API_FORM_ID'], // Form ID. 'active', // Subscriber state. @@ -1312,7 +1346,7 @@ public function testGetFormSubscriptionsWithAddedBeforeParam() */ public function testGetFormSubscriptionsWithCreatedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_form_subscriptions( (int) $_ENV['CONVERTKIT_API_FORM_ID'], // Form ID. 'active', // Subscriber state. @@ -2272,7 +2306,7 @@ public function testGetSequenceSubscriptionsWithBouncedSubscriberState() */ public function testGetSequenceSubscriptionsWithAddedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_sequence_subscriptions( $_ENV['CONVERTKIT_API_SEQUENCE_ID'], // Sequence ID. 'active', // Subscriber state. @@ -2335,7 +2369,7 @@ public function testGetSequenceSubscriptionsWithAddedBeforeParam() */ public function testGetSequenceSubscriptionsWithCreatedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_sequence_subscriptions( $_ENV['CONVERTKIT_API_SEQUENCE_ID'], // Sequence ID. 'active', // Subscriber state. @@ -2441,7 +2475,7 @@ public function testGetSequenceSubscriptionsPagination() // Assert has_previous_page and has_next_page are correct. $this->assertTrue($result['pagination']['has_previous_page']); - $this->assertTrue($result['pagination']['has_next_page']); + $this->assertFalse($result['pagination']['has_next_page']); // Use pagination to fetch previous page. $result = $this->api->get_sequence_subscriptions( @@ -2654,7 +2688,7 @@ public function testCreateTagBlank() } /** - * Test that create_tag() returns a WP_Error when creating + * Test that create_tag() returns the expected data when creating * a tag that already exists. * * @since 1.0.0 @@ -2664,8 +2698,12 @@ public function testCreateTagBlank() public function testCreateTagThatExists() { $result = $this->api->create_tag($_ENV['CONVERTKIT_API_TAG_NAME']); - $this->assertInstanceOf(WP_Error::class, $result); - $this->assertEquals($result->get_error_code(), $this->errorCode); + + // Assert response contains correct data. + $this->assertArrayHasKey('id', $result['tag']); + $this->assertArrayHasKey('name', $result['tag']); + $this->assertArrayHasKey('created_at', $result['tag']); + $this->assertEquals($result['tag']['name'], $_ENV['CONVERTKIT_API_TAG_NAME']); } /** @@ -2734,8 +2772,8 @@ public function testCreateTagsBlank() } /** - * Test that create_tags() returns a WP_Error when creating - * tags that already exists. + * Test that create_tags() returns the expected data when creating + * tags that already exist. * * @since 2.0.0 * @@ -2750,8 +2788,10 @@ public function testCreateTagsThatExist() ] ); - // Assert failures. - $this->assertCount(2, $result['failures']); + // Assert existing tags are returned. + $this->assertCount(2, $result['tags']); + $this->assertEquals($result['tags'][1]['name'], $_ENV['CONVERTKIT_API_TAG_NAME']); + $this->assertEquals($result['tags'][0]['name'], $_ENV['CONVERTKIT_API_TAG_NAME_2']); } /** @@ -3127,7 +3167,7 @@ public function testGetTagSubscriptionsWithBouncedSubscriberState() */ public function testGetTagSubscriptionsWithTaggedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_tag_subscriptions( (int) $_ENV['CONVERTKIT_API_TAG_ID'], // Tag ID. 'active', // Subscriber state. @@ -3190,7 +3230,7 @@ public function testGetTagSubscriptionsWithTaggedBeforeParam() */ public function testGetTagSubscriptionsWithCreatedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_tag_subscriptions( (int) $_ENV['CONVERTKIT_API_TAG_ID'], // Tag ID. 'active', // Subscriber state. @@ -3450,7 +3490,7 @@ public function testGetSubscribersWithBouncedSubscriberState() */ public function testGetSubscribersWithCreatedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_subscribers( 'active', // Subscriber state. '', // Email address. @@ -3507,7 +3547,7 @@ public function testGetSubscribersWithCreatedBeforeParam() */ public function testGetSubscribersWithUpdatedAfterParam() { - $date = new \DateTime('2024-01-01'); + $date = new \DateTime('2022-01-01'); $result = $this->api->get_subscribers( 'active', // Subscriber state. '', // Email address.