diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 132cc1b4..59c8dc0c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -32,6 +32,19 @@ jobs: node-version: 18 cache: 'npm' + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build Mock Image + uses: docker/build-push-action@v7 + with: + context: . + file: ./config/Dockerfile-mock-webservice + tags: tinify-mock-api:latest + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Cache node_modules uses: actions/cache@v4 with: @@ -57,7 +70,6 @@ jobs: - run: npx playwright install --with-deps if: steps.playwright-cache.outputs.cache-hit != 'true' - - name: Start WordPress uses: nick-fields/retry@v3 with: @@ -73,7 +85,6 @@ jobs: run: npm run test:playwright env: WORDPRESS_PORT: 80${{ matrix.wp }} - PHP_VERSION: ${{ matrix.php }} - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} diff --git a/bin/run-mocks b/bin/run-mocks index cf2fbc87..3aef15fe 100755 --- a/bin/run-mocks +++ b/bin/run-mocks @@ -1,8 +1,9 @@ #!/bin/bash +set -e port="$1" -docker compose -f config/mocks.docker-compose.yml up -d +docker compose -f config/mocks.docker-compose.yml up -d --wait mv src/vendor/tinify/Tinify/Client.php src/vendor/tinify/Tinify/Client.php.bak cp test/fixtures/Client.php src/vendor/tinify/Tinify/Client.php diff --git a/bin/run-wordpress b/bin/run-wordpress index 770592cd..30a7186d 100755 --- a/bin/run-wordpress +++ b/bin/run-wordpress @@ -93,11 +93,6 @@ EOF echo "Activating tinify.." docker compose -f config/docker-compose.yml run --rm wpcli wp plugin activate tiny-compress-images --allow-root -if [ "$WORDPRESS_VERSION_ENV" -ge 55 ]; then - echo "Installing compatible plugins for WordPress ${WORDPRESS_PORT}.." - docker compose -f config/docker-compose.yml run --rm --user 33 wpcli wp plugin install amazon-s3-and-cloudfront --activate --allow-root || exit 1 -fi - MAX_ATTEMPTS=10 ATTEMPT=0 until curl -s --head --fail "http://localhost:${WORDPRESS_PORT}" >/dev/null; do diff --git a/config/docker-compose.yml b/config/docker-compose.yml index 69233cba..775f9238 100755 --- a/config/docker-compose.yml +++ b/config/docker-compose.yml @@ -29,12 +29,6 @@ services: WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress WORDPRESS_DEBUG: '1' - AWS_ENDPOINT: http://localstack:4566 - AWS_USE_PATH_STYLE_ENDPOINT: true - AWS_ACCESS_KEY_ID: test_key_id - AWS_SECRET_ACCESS_KEY: test_secret_access_key - AWS_REGION: eu-central-1 - AWS_DEFAULT_REGION: eu-central-1 volumes: - wordpress_data:/var/www/html - ../:/var/www/html/wp-content/plugins/tiny-compress-images diff --git a/config/localstack-init.sh b/config/localstack-init.sh deleted file mode 100755 index d2a53e73..00000000 --- a/config/localstack-init.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -awslocal s3 mb s3://tinytest - diff --git a/config/mocks.docker-compose.yml b/config/mocks.docker-compose.yml index f09e150f..7c5b4e3c 100755 --- a/config/mocks.docker-compose.yml +++ b/config/mocks.docker-compose.yml @@ -1,13 +1,4 @@ services: - localstack: - image: localstack/localstack - volumes: - - './localstack-init.sh:/etc/localstack/init/ready.d/init-aws.sh' - ports: - - 4566:4566 - networks: - - tinify - tinify-mock-api: image: tinify-mock-api build: @@ -17,6 +8,11 @@ services: - '8100:80' volumes: - ../test/mock-tinypng-webservice:/var/www/html + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/"] + interval: 5s + timeout: 3s + retries: 3 networks: - tinify diff --git a/test/fixtures/class-tiny-config.php b/test/fixtures/class-tiny-config.php index a28419f7..4c748efb 100644 --- a/test/fixtures/class-tiny-config.php +++ b/test/fixtures/class-tiny-config.php @@ -3,10 +3,6 @@ if (! defined('TINY_DEBUG')) { define('TINY_DEBUG', null); } -define('AWS_REGION', getenv('AWS_REGION')); -define('AWS_ENDPOINT', getenv('AWS_ENDPOINT')); -define('AWS_ACCESS_KEY_ID', getenv('AWS_ACCESS_KEY_ID')); -define('AWS_SECRET_ACCESS_KEY', getenv('AWS_SECRET_ACCESS_KEY')); class Tiny_Config { @@ -17,23 +13,6 @@ class Tiny_Config const META_KEY = 'tiny_compress_images'; } -/** - * Filter for adding arguments to the AS3CF AWS client. - * Required to point the client to the LocalStack instance. - */ -add_filter('as3cf_aws_init_client_args', function ($args) { - $args['endpoint'] = AWS_ENDPOINT; - $args['use_path_style_endpoint'] = true; - $args['region'] = AWS_REGION; - return $args; -}); - -// Force all S3 URLs to use LocalStack instead of s3.amazonaws.com -add_filter('as3cf_aws_s3_url_domain', function ($domain, $bucket, $region, $expires, $args) { - // Replace any AWS domain with LocalStack - return AWS_ENDPOINT . '/' . $bucket; -}, 10, 5); - // ajax hook to delete all attachments as doing it via UI is flaky add_action( 'wp_ajax_clear_media_library', 'clear_media_library' ); function clear_media_library() { diff --git a/test/integration/compatibility.spec.ts b/test/integration/compatibility.spec.ts deleted file mode 100644 index 17f015c0..00000000 --- a/test/integration/compatibility.spec.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Page, expect, test } from '@playwright/test'; -import { activatePlugin, clearMediaLibrary, deactivatePlugin, enableCompressionSizes, getPHPVersion, getWPVersion, setAPIKey, setCompressionTiming, uploadMedia } from './utils'; - -test.describe.configure({ mode: 'serial' }); - -const TEST_BUCKETNAME = 'tinytest'; -let WPVersion = 0; - -async function setRemoveLocalMedia(page: Page, enabled: boolean) { - await page.goto('/wp-admin/options-general.php?page=amazon-s3-and-cloudfront'); - - const cfgRemoveLocal = await page.getByLabel('Remove Local Media').isChecked(); - if (cfgRemoveLocal && enabled) { - // should enable but is already enabled - return; - } - if (!cfgRemoveLocal && !enabled) { - // should disable but is already disabled - return; - } - - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/state/') && resp.status() === 200), - page.locator('label[for="remove-local-file"]').click(), - ]); - - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/settings/') && resp.status() === 200), - page.getByRole('button', { name: 'Save Changes' }).click() - ]); -} - -test.describe('as3cf', () => { - let page: Page; - - test.beforeAll(async ({ browser }) => { - page = await browser.newPage(); - WPVersion = await getWPVersion(page); - const phpVersion = getPHPVersion(); - - if (WPVersion < 5.9) { - // Skipping test as it WP Offload does not support WordPress < 5.9 - test.skip(); - return; - } - - if (phpVersion < 81) { - // Skipping test as WP Offload Media requires PHP 8.1+ - test.skip(); - return; - } - - await activatePlugin(page, 'amazon-s3-and-cloudfront'); - - await page.goto('/wp-admin/options-general.php?page=amazon-s3-and-cloudfront'); - - const isConfigured = await page.getByText('Storage provider is successfully connected and ready to offload new media.').isVisible(); - if (!isConfigured) { - await page.getByText('Enter bucket name').click(); - await page.getByPlaceholder('Enter bucket name…').fill(TEST_BUCKETNAME); - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/settings/') && resp.status() === 200), - page.getByRole('button', { name: 'Save Bucket Settings' }).click(), - ]); - } - - await setRemoveLocalMedia(page, false); - - await setAPIKey(page, 'JPG123'); - await enableCompressionSizes(page, [], true); - await setCompressionTiming(page, 'auto'); - }); - - test.afterAll(async () => { - await deactivatePlugin(page, 'amazon-s3-and-cloudfront'); - await page.close(); - }); - - test('does not show notification when local media is preserved', async () => { - await setRemoveLocalMedia(page, false); - - await page.goto('/wp-admin/options-general.php?page=tinify'); - - await expect(page.getByText(' configure WP Offload')).not.toBeVisible(); - }); - - test('shows notification when local media is not preserved', async () => { - await setCompressionTiming(page, 'background'); - await setRemoveLocalMedia(page, true); - - await page.goto('/wp-admin/options-general.php?page=tinify'); - - await expect(page.getByText(' configure WP Offload')).toBeVisible(); - }); - - test('compress image before offloading', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'auto'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size compressed')).toBeVisible(); - }); - - test('compress image asynchronously', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'background'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size compressed')).toBeVisible(); - }); - - test('compress images manually', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'manual'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size to be compressed')).toBeVisible(); - }); - - test('does not show compression button if image is not available locally', async ({ page }) => { - // Currently, we cannot support compression of images that are not available locally. - await setRemoveLocalMedia(page, true); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'manual'); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - - await expect(page.getByRole('button', { name: 'Compress', exact: true })).not.toBeVisible(); - }); -}); diff --git a/test/integration/utils.ts b/test/integration/utils.ts index 01640e24..25ca8fd3 100644 --- a/test/integration/utils.ts +++ b/test/integration/utils.ts @@ -160,18 +160,6 @@ export async function getWPVersion(page: Page): Promise { return parsedText; } -/** - * @returns {number} retrieves the current PHP version from environment variable - */ -export function getPHPVersion(): number { - const { PHP_VERSION } = process.env; - if (!PHP_VERSION) { - throw Error('PHP_VERSION is not set'); - } - - return +PHP_VERSION; -} - /** * @param {Page} page context * @param {string} pluginSlug slug of the plugin, ex 'tiny-compress-images' diff --git a/test/mock-tinypng-webservice/index.php b/test/mock-tinypng-webservice/index.php new file mode 100644 index 00000000..b3d9bbc7 --- /dev/null +++ b/test/mock-tinypng-webservice/index.php @@ -0,0 +1 @@ +