 tests/src/Functional/CommentTest.php      |  9 +++-
 tests/src/Functional/ResourceTestBase.php | 78 +++++++++++++++++++------------
 tests/src/Functional/TermTest.php         | 16 +++++--
 tests/src/Functional/UserTest.php         | 13 ++++--
 tests/src/Functional/VocabularyTest.php   |  4 ++
 5 files changed, 83 insertions(+), 37 deletions(-)

diff --git a/tests/src/Functional/CommentTest.php b/tests/src/Functional/CommentTest.php
index faa5f40..2ae8661 100644
--- a/tests/src/Functional/CommentTest.php
+++ b/tests/src/Functional/CommentTest.php
@@ -6,6 +6,7 @@ use Drupal\comment\Entity\Comment;
 use Drupal\comment\Entity\CommentType;
 use Drupal\comment\Tests\CommentTestTrait;
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Url;
 use Drupal\entity_test\Entity\EntityTest;
@@ -294,7 +295,9 @@ class CommentTest extends ResourceTestBase {
     $this->setUpAuthorization('POST');
 
     $url = Url::fromRoute(sprintf('jsonapi.%s.collection', static::$resourceTypeName));
-    $request_options = $this->getAuthenticationRequestOptions('POST');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST'));
 
     $remove_field = function(array $normalization, $type, $attribute_name) {
       unset($normalization['data'][$type][$attribute_name]);
@@ -340,7 +343,9 @@ class CommentTest extends ResourceTestBase {
     $this->setUpAuthorization('POST');
 
     // Create request.
-    $request_options = $this->getAuthenticationRequestOptions('POST');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST'));
     $request_options[RequestOptions::BODY] = Json::encode($this->getNormalizedPostEntity());
 
     $url = Url::fromRoute('jsonapi.comment--comment.collection');
diff --git a/tests/src/Functional/ResourceTestBase.php b/tests/src/Functional/ResourceTestBase.php
index ab47175..88960fa 100644
--- a/tests/src/Functional/ResourceTestBase.php
+++ b/tests/src/Functional/ResourceTestBase.php
@@ -184,22 +184,25 @@ abstract class ResourceTestBase extends BrowserTestBase {
         ->setTranslatable(FALSE)
         ->save();
 
-      // Add multi-value field.
-      FieldStorageConfig::create([
-        'entity_type' => static::$entityTypeId,
-        'field_name' => 'field_rest_test_multivalue',
-        'type' => 'string',
-      ])
-        ->setCardinality(3)
-        ->save();
-      FieldConfig::create([
-        'entity_type' => static::$entityTypeId,
-        'field_name' => 'field_rest_test_multivalue',
-        'bundle' => $this->entity->bundle(),
-      ])
-        ->setLabel('Test field: multi-value')
-        ->setTranslatable(FALSE)
-        ->save();
+      // @todo Do this unconditionally when JSON API requires Drupal 8.5 or newer.
+      if (floatval(\Drupal::VERSION) >= 8.5) {
+        // Add multi-value field.
+        FieldStorageConfig::create([
+          'entity_type' => static::$entityTypeId,
+          'field_name' => 'field_rest_test_multivalue',
+          'type' => 'string',
+        ])
+          ->setCardinality(3)
+          ->save();
+        FieldConfig::create([
+          'entity_type' => static::$entityTypeId,
+          'field_name' => 'field_rest_test_multivalue',
+          'bundle' => $this->entity->bundle(),
+        ])
+          ->setLabel('Test field: multi-value')
+          ->setTranslatable(FALSE)
+          ->save();
+      }
 
       // Reload entity so that it has the new field.
       $reloaded_entity = $this->entityStorage->loadUnchanged($this->entity->id());
@@ -209,7 +212,10 @@ abstract class ResourceTestBase extends BrowserTestBase {
 
         // Set a default value on the fields.
         $this->entity->set('field_rest_test', ['value' => 'All the faith he had had had had no effect on the outcome of his life.']);
-        $this->entity->set('field_rest_test_multivalue', [['value' => 'One'], ['value' => 'Two']]);
+        // @todo Do this unconditionally when JSON API requires Drupal 8.5 or newer.
+        if (floatval(\Drupal::VERSION) >= 8.5) {
+          $this->entity->set('field_rest_test_multivalue', [['value' => 'One'], ['value' => 'Two']]);
+        }
         $this->entity->save();
       }
     }
@@ -582,7 +588,9 @@ abstract class ResourceTestBase extends BrowserTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
     /* $url = $this->entity->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('GET');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('GET'));
 
     // DX: 403 when unauthorized.
     $response = $this->request('GET', $url, $request_options);
@@ -738,19 +746,20 @@ abstract class ResourceTestBase extends BrowserTestBase {
     */
     // @codingStandardsIgnoreEnd
 
-    // DX: 404 when GETting non-existing entity, but HTML response.
+    // DX: 404 when GETting non-existing entity.
     $random_uuid = \Drupal::service('uuid')->generate();
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $random_uuid]);
     $response = $this->request('GET', $url, $request_options);
-    $this->assertSame(404, $response->getStatusCode());
-    $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
-
-    // DX: 404 JSON API response if the ?_format query string is present.
-    $url->setOption('query', ['_format' => 'api_json']);
-    $response = $this->request('GET', $url, $request_options);
-    $path = str_replace($random_uuid, '{' . static::$entityTypeId . '}', $url->setAbsolute()->setOptions(['base_url' => '', 'query' => []])->toString());
+    $message_url = clone $url;
+    $path = str_replace($random_uuid, '{' . static::$entityTypeId . '}', $message_url->setAbsolute()->setOptions(['base_url' => '', 'query' => []])->toString());
     $message = 'The "' . static::$entityTypeId . '" parameter was not converted for the path "' . $path . '" (route name: "jsonapi.' . static::$resourceTypeName . '.individual")';
     $this->assertResourceErrorResponse(404, $message, $response);
+
+    // DX: when Accept request header is missing, still 404, but HTML response.
+    unset($request_options[RequestOptions::HEADERS]['Accept']);
+    $response = $this->request('GET', $url, $request_options);
+    $this->assertSame(404, $response->getStatusCode());
+    $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
   }
 
   /**
@@ -778,7 +787,9 @@ abstract class ResourceTestBase extends BrowserTestBase {
     //   error responses provide a good DX
     // - to eventually result in a well-formed request that succeeds.
     $url = Url::fromRoute(sprintf('jsonapi.%s.collection', static::$resourceTypeName));
-    $request_options = $this->getAuthenticationRequestOptions('POST');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST'));
 
     // @todo Uncomment in https://www.drupal.org/project/jsonapi/issues/2943170.
     // @codingStandardsIgnoreStart
@@ -984,7 +995,9 @@ abstract class ResourceTestBase extends BrowserTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
     /* $url = $this->entity->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('PATCH'));
 
     // @todo Uncomment in https://www.drupal.org/project/jsonapi/issues/2943170.
     // @codingStandardsIgnoreStart
@@ -1202,6 +1215,11 @@ abstract class ResourceTestBase extends BrowserTestBase {
     // is not sent in the PATCH request.
     $this->assertSame('All the faith he had had had had no effect on the outcome of his life.', $updated_entity->get('field_rest_test')->value);
 
+    // @todo Remove this when JSON API requires Drupal 8.5 or newer.
+    if (floatval(\Drupal::VERSION) < 8.5) {
+      return;
+    }
+
     // Multi-value field: remove item 0. Then item 1 becomes item 0.
     $normalization_multi_value_tests = $this->getNormalizedPatchEntity();
     $normalization_multi_value_tests['data']['attributes']['field_rest_test_multivalue'] = $this->entity->get('field_rest_test_multivalue')->getValue();
@@ -1244,7 +1262,9 @@ abstract class ResourceTestBase extends BrowserTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
     /* $url = $this->entity->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('DELETE'));
 
     // DX: 403 when unauthorized.
     $response = $this->request('DELETE', $url, $request_options);
diff --git a/tests/src/Functional/TermTest.php b/tests/src/Functional/TermTest.php
index 745421a..2e0034a 100644
--- a/tests/src/Functional/TermTest.php
+++ b/tests/src/Functional/TermTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\jsonapi\Functional;
 
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Url;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\taxonomy\Entity\Vocabulary;
@@ -286,16 +287,18 @@ class TermTest extends ResourceTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
     /* $url = $this->entity->toUrl('jsonapi'); */
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('GET'));
 
     // GET term's current normalization.
-    $response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET'));
+    $response = $this->request('GET', $url, $request_options);
     $normalization = Json::decode((string) $response->getBody());
 
     // Change term's path alias.
     $normalization['data']['attributes']['path']['alias'] .= 's-rule-the-world';
 
     // Create term PATCH request.
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
     $request_options[RequestOptions::BODY] = Json::encode($normalization);
 
     // PATCH request: 200.
@@ -335,6 +338,11 @@ class TermTest extends ResourceTestBase {
    * @dataProvider providerTestGetIndividualTermWithParent
    */
   public function testGetIndividualTermWithParent(array $parent_term_ids) {
+    if (floatval(\Drupal::VERSION) < 8.6) {
+      $this->markTestSkipped('The "parent" field on terms is only available for normalization in Drupal 8.6 and later.');
+      return;
+    }
+
     // Create all possible parent terms.
     Term::create(['vid' => Vocabulary::load('camelids')->id()])
       ->setName('Lamoids')
@@ -349,7 +357,9 @@ class TermTest extends ResourceTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
     /* $url = $this->entity->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('GET');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('GET'));
     $this->setUpAuthorization('GET');
     $response = $this->request('GET', $url, $request_options);
     $expected = $this->getExpectedNormalizedEntity();
diff --git a/tests/src/Functional/UserTest.php b/tests/src/Functional/UserTest.php
index 67d2af4..8567e00 100644
--- a/tests/src/Functional/UserTest.php
+++ b/tests/src/Functional/UserTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\jsonapi\Functional;
 
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Url;
 use Drupal\jsonapi\Normalizer\HttpExceptionNormalizer;
 use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
@@ -183,7 +184,9 @@ class UserTest extends ResourceTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.user--user.individual'), ['user' => $this->account->uuid()]);
     /* $url = $this->account->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('PATCH'));
 
     // Test case 1: changing email.
     $normalization = $original_normalization;
@@ -261,7 +264,9 @@ class UserTest extends ResourceTestBase {
 
     // Update password in $this->account, prepare for future requests.
     $this->account->passRaw = $new_password;
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('PATCH'));
 
     // Test case 3: changing name.
     $normalization = $original_normalization;
@@ -335,7 +340,9 @@ class UserTest extends ResourceTestBase {
     // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
     $url = Url::fromRoute(sprintf('jsonapi.user--user.individual'), ['user' => $this->account->uuid()]);
     /* $url = $this->account->toUrl('jsonapi'); */
-    $request_options = $this->getAuthenticationRequestOptions('PATCH');
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('PATCH'));
 
     $normalization = $original_normalization;
     $normalization['data']['attributes']['mail'] = 'new-email@example.com';
diff --git a/tests/src/Functional/VocabularyTest.php b/tests/src/Functional/VocabularyTest.php
index 608da5f..dad5f32 100644
--- a/tests/src/Functional/VocabularyTest.php
+++ b/tests/src/Functional/VocabularyTest.php
@@ -104,6 +104,10 @@ class VocabularyTest extends ResourceTestBase {
    */
   protected function getExpectedUnauthorizedAccessMessage($method) {
     if ($method === 'GET') {
+      // @todo Remove this when JSON API requires Drupal 8.5 or newer.
+      if (floatval(\Drupal::VERSION) < 8.5) {
+        return parent::getExpectedUnauthorizedAccessMessage($method);
+      }
       return "The following permissions are required: 'access taxonomy overview' OR 'administer taxonomy'.";
     }
     return parent::getExpectedUnauthorizedAccessMessage($method);
