magento2-docker/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/VarnishTest.php

303 lines
12 KiB
PHP

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\GraphQl\PageCache;
use Magento\GraphQlCache\Model\CacheId\CacheIdCalculator;
/**
* Test that caching works properly for Varnish when using the X-Magento-Cache-Id
*/
class VarnishTest extends GraphQLPageCacheAbstract
{
/**
* Test that we obtain cache MISS/HIT when expected for a guest.
*
* @magentoConfigFixture default/system/full_page_cache/caching_application 2
* @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php
*/
public function testCacheResultForGuest()
{
$productSku='simple2';
$query = $this->getProductQuery($productSku);
// Obtain the X-Magento-Cache-Id from the response which will be used as the cache key
$response = $this->graphQlQueryWithResponseHeaders($query);
$this->assertArrayHasKey(CacheIdCalculator::CACHE_ID_HEADER, $response['headers']);
$cacheId = $response['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we obtain a cache MISS the first time we search the cache using this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $cacheId]);
// Verify we obtain a cache HIT the second time around for this X-Magento-Cache-Id
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $cacheId]);
}
/**
* Test that changing the Store header returns different cache results.
*
* @magentoConfigFixture default/system/full_page_cache/caching_application 2
* @magentoApiDataFixture Magento/Store/_files/second_store.php
* @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php
*/
public function testCacheResultForGuestWithStoreHeader()
{
$productSku = 'simple2';
$query = $this->getProductQuery($productSku);
// Verify caching works as expected without a Store header
$response = $this->graphQlQueryWithResponseHeaders($query);
$this->assertArrayHasKey(CacheIdCalculator::CACHE_ID_HEADER, $response['headers']);
$defaultStoreCacheId = $response['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we obtain a cache MISS the first time we search the cache using this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultStoreCacheId]);
// Verify we obtain a cache HIT the second time we search the cache using this X-Magento-Cache-Id
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultStoreCacheId]);
// Obtain a new X-Magento-Cache-Id using after updating the Store header
$secondStoreResponse = $this->graphQlQueryWithResponseHeaders(
$query,
[],
'',
[
CacheIdCalculator::CACHE_ID_HEADER => $defaultStoreCacheId,
'Store' => 'fixture_second_store'
]
);
$secondStoreCacheId = $secondStoreResponse['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we obtain a cache MISS the first time we search by this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $secondStoreCacheId,
'Store' => 'fixture_second_store'
]);
// Verify we obtain a cache HIT the second time around with the Store header
$this->assertCacheHitAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $secondStoreCacheId,
'Store' => 'fixture_second_store'
]);
// Verify we still obtain a cache HIT for the default store
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultStoreCacheId]);
}
/**
* Test that changing the Content-Currency header returns different cache results.
*
* @magentoConfigFixture default/system/full_page_cache/caching_application 2
* @magentoApiDataFixture Magento/Store/_files/multiple_currencies.php
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
*/
public function testCacheResultForGuestWithCurrencyHeader()
{
$productSku = 'simple_product';
$query = $this->getProductQuery($productSku);
// Verify caching works as expected without a Content-Currency header
$response = $this->graphQlQueryWithResponseHeaders($query);
$this->assertArrayHasKey(CacheIdCalculator::CACHE_ID_HEADER, $response['headers']);
$defaultCurrencyCacheId = $response['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we obtain a cache MISS the first time we search the cache using this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse(
$query,
[CacheIdCalculator::CACHE_ID_HEADER => $defaultCurrencyCacheId]
);
// Verify we obtain a cache HIT the second time we search the cache using this X-Magento-Cache-Id
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultCurrencyCacheId]);
// Obtain a new X-Magento-Cache-Id using after updating the Content-Currency header
$secondCurrencyResponse = $this->graphQlQueryWithResponseHeaders(
$query,
[],
'',
[
CacheIdCalculator::CACHE_ID_HEADER => $defaultCurrencyCacheId,
'Content-Currency' => 'EUR'
]
);
$secondCurrencyCacheId = $secondCurrencyResponse['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we obtain a cache MISS the first time we search by this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $secondCurrencyCacheId,
'Content-Currency' => 'EUR'
]);
// Verify we obtain a cache HIT the second time around with the changed currency header
$this->assertCacheHitAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $secondCurrencyCacheId,
'Content-Currency' => 'EUR'
]);
// Verify we still obtain a cache HIT for the default currency ( no Content-Currency header)
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultCurrencyCacheId]);
}
/**
* Test that a request with a cache id which differs from the one returned by the response is not cacheable.
*
* @magentoConfigFixture default/system/full_page_cache/caching_application 2
* @magentoApiDataFixture Magento/Store/_files/second_store.php
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
*/
public function testCacheResultForGuestWithOutdatedCacheId()
{
$productSku = 'simple_product';
$query = $this->getProductQuery($productSku);
// Verify caching with no headers in the request
$response = $this->graphQlQueryWithResponseHeaders($query);
$this->assertArrayHasKey(CacheIdCalculator::CACHE_ID_HEADER, $response['headers']);
$defaultCacheId = $response['headers'][CacheIdCalculator::CACHE_ID_HEADER];
$this->assertCacheMissAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultCacheId]);
$this->assertCacheHitAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $defaultCacheId]);
// Obtain a new X-Magento-Cache-Id using after updating the request with Store header
$responseWithStore = $this->graphQlQueryWithResponseHeaders(
$query,
[],
'',
[
CacheIdCalculator::CACHE_ID_HEADER => $defaultCacheId,
'Store' => 'fixture_second_store'
]
);
$storeCacheId = $responseWithStore['headers'][CacheIdCalculator::CACHE_ID_HEADER];
// Verify we still get a cache MISS since the cache id in the request doesn't match the cache id from response
$this->assertCacheMissAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $defaultCacheId,
'Store' => 'fixture_second_store'
]);
// Verify we get a cache MISS first time with the updated cache id
$this->assertCacheMissAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $storeCacheId,
'Store' => 'fixture_second_store'
]);
// Verify we obtain a cache HIT second time around with the updated cache id
$this->assertCacheHitAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $storeCacheId,
'Store' => 'fixture_second_store'
]);
}
/**
* Test that we obtain cache MISS/HIT when expected for a customer.
*
* @magentoConfigFixture default/system/full_page_cache/caching_application 2
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
*/
public function testCacheResultForCustomer()
{
$productSku = 'simple_product';
$query = $this->getProductQuery($productSku);
$email = 'customer@example.com';
$password = 'password';
$generateToken = $this->generateCustomerToken($email, $password);
$tokenResponse = $this->graphQlMutationWithResponseHeaders($generateToken);
// Obtain the X-Magento-Cache-id from the response and authorization token - customer logs in
$this->assertArrayHasKey(CacheIdCalculator::CACHE_ID_HEADER, $tokenResponse['headers']);
$cacheIdCustomer = $tokenResponse['headers'][CacheIdCalculator::CACHE_ID_HEADER];
$customerToken = $tokenResponse['body']['generateCustomerToken']['token'];
// Verify we obtain cache MISS the first time we search by this X-Magento-Cache-Id
$this->assertCacheMissAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $cacheIdCustomer,
'Authorization' => 'Bearer ' . $customerToken
]);
// Verify we obtain cache HIT second time using the same X-Magento-Cache-Id
$this->assertCacheHitAndReturnResponse($query, [
CacheIdCalculator::CACHE_ID_HEADER => $cacheIdCustomer,
'Authorization' => 'Bearer ' . $customerToken
]);
$revokeTokenQuery = $this->revokeCustomerToken();
// Verify that once customer logs out, X-Magento-Cache-Id will be that of an unregistered user
$revokeTokenResponse = $this->graphQlMutationWithResponseHeaders(
$revokeTokenQuery,
[],
'',
[
CacheIdCalculator::CACHE_ID_HEADER => $cacheIdCustomer,
'Authorization' => 'Bearer ' . $customerToken
]
);
$cacheIdGuest = $revokeTokenResponse['headers'][CacheIdCalculator::CACHE_ID_HEADER];
$this->assertNotEquals($cacheIdCustomer, $cacheIdGuest);
//Verify that omitting the Auth token doesn't send cached content for a logged-in customer
$this->assertCacheMissAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $cacheIdCustomer]);
$this->assertCacheMissAndReturnResponse($query, [CacheIdCalculator::CACHE_ID_HEADER => $cacheIdCustomer]);
}
/**
* Get product query
*
* @param string $productSku
* @return string
*/
private function getProductQuery(string $productSku): string
{
$productQuery = <<<QUERY
{
products(filter: {sku: {eq: "{$productSku}"}})
{
items {
id
name
sku
}
}
}
QUERY;
return $productQuery;
}
/**
* @param string $email
* @param string $password
* @return string
*/
private function generateCustomerToken(string $email, string $password) : string
{
return <<<MUTATION
mutation {
generateCustomerToken(
email: "{$email}"
password: "{$password}"
) {
token
}
}
MUTATION;
}
/**
* @return string
*/
private function revokeCustomerToken() : string
{
return <<<MUTATION
mutation {
revokeCustomerToken
{ result }
}
MUTATION;
}
}