Problem/Motivation

ResourceTestBase is not usable out of the box for tests of non-entity resources. There are a number of problems one encounters:

  1. $this->serializer is declared but never set
  2. getExpectedBcUnauthorizedAccessMessage() needs to be implemented even though it is only needed for entity resources

Proposed resolution

  1. Move the initialization of $this->serializer from EntityResourceTestBase to ResourceTestBase
  2. Remove the abstract method getExpectedBcUnauthorizedAccessMessage()
  3. Implement getExpectedUnauthorizedAccessMessage generically in ResourceTestBase

Remove the abstract definition of getExpectedBcUnauthorizedAccessMessage() from ResourceTestBase.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Title: getExpectedBcUnauthorizedAccessMessage() should be on EntityResourceTestBase not on ResourceTestBase » abstract ResourceTestBase::getExpectedBcUnauthorizedAccessMessage() gets in the way of non-entity resource tests
Issue summary: View changes

Just realized that EntityResource already has a generic implementation of that method, so I think the abstract method can simply be removed.

Re-titling and updating the issue summary accordingly.

tstoeckler’s picture

Title: abstract ResourceTestBase::getExpectedBcUnauthorizedAccessMessage() gets in the way of non-entity resource tests » ResourceTestBase::getExpectedBcUnauthorizedAccessMessage() gets in the way of non-entity resource tests
Assigned: Unassigned » Wim Leers
Issue tags: -Novice

Hmmm... thinking about this more: Since generically, resources get their own permissions and only for entities we don't need that, would it make sense to move EntityResourceTestBase::getExpectedBCUnauthorizedAccessMessage() into ResourceTestBase as getExpectedUnauthorizedAccessMessage() (i.e. without the BC)?

I currently have this in my non-entity resource test:


  /**
   * {@inheritdoc}
   */
  protected function getExpectedUnauthorizedAccessMessage($method) {
    return "The 'restful " . strtolower($method) . " some_resource_plugin_id' permission is required.";
  }

  /**
   * {@inheritdoc}
   *
   * @todo Remove this when https://www.drupal.org/node/2869387 lands.
   */
  protected function getExpectedBcUnauthorizedAccessMessage($method) {
  }

We would only need the resource plugin ID to do this generically and EntityResourceTestBase could in turn have a default implementation of that since it knows the entity type ID.

Assigning to Wim Leers to shine some light on this, this is all very confusing to me.

tstoeckler’s picture

Title: ResourceTestBase::getExpectedBcUnauthorizedAccessMessage() gets in the way of non-entity resource tests » ResourceTestBase does not work for tests of non-entity resources
Assigned: Wim Leers » Unassigned
Issue summary: View changes
Status: Active » Needs review
FileSize
3.67 KB

Actually expanding scope a bit here, as I found another problem with ResourceTestBase: $this->serializer is declared, but never set.

Also unassigning @Wim Leers again until I have something more "presentable" here. So far I'm still thinking out loud.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

#4 makes sense on all counts. Thanks for the crystal-clear IS too!

P.S.: very glad to see people using these base classes!

tstoeckler’s picture

Ah, awesome thank you! :-) I will keep you posted if I find anything else ;-)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 4: 2869387-4.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
1.03 KB
4 KB

Let's try this one. ResourceTestBase::$resourceConfigId conveniently has the comment:

The REST Resource plugin ID can be calculated from this.

But, I had to search a bit to verify that my assumption of how that actually works is true, so I added a @see.

tstoeckler’s picture

+++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
@@ -62,6 +62,8 @@
+   * @see \Drupal\rest\Entity\RestResourceConfig::__construct()()

Ahh damn, double paren's...

tstoeckler’s picture

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: 2869387-11.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community
effulgentsia’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record

This issue is currently set to version 8.3.x. How important is it to commit it to that version? While I like #11, I'm concerned about introducing the corresponding BC breaks to non-entity resource tests into a patch-level release.

I think this also needs a CR for a before/after example of writing a non-entity resource test (or at least the portions of that that are affected by this patch).

Speaking of which, do we have core issues for adding test coverage for DBLogResource and UserRegistrationResource? And I wonder if independently of that, if we should also have a separate test for a test non-entity resource.

effulgentsia’s picture

Also, I'm skeptical about the title of this issue. "does not work" is a pretty strong statement. The issue summary points to some WTFs worth fixing, but is it really true that it doesn't work at all, and that therefore there are 0 contrib modules extending it? That's relevant in evaluating whether to commit it to 8.3.

Wim Leers’s picture

I'm concerned about introducing the corresponding BC breaks to non-entity resource tests into a patch-level release

  • First: there's likely zero subclasses of ResourceTestBase in contrib right now.
  • Second: this reduces the amount of methods one has to implement for ResourceTestBase subclasses, and so it'd remove the need to implement two abstract methods, which aren't called by ResourceTestBase itself. The first (ResourceTestBase::getExpectedUnauthorizedAccessMessage()) does get a default implementation that will work for 99% of REST resource plugins (it matches \Drupal\rest\Plugin\ResourceBase::permissions()). The second (ResourceTestBase::getExpectedBcUnauthorizedAccessMessage()) only ever makes sense for entity resources, see EntityResource::permissions() + https://www.drupal.org/node/2664780.

I think this also needs a CR for a before/after example of writing a non-entity resource test (or at least the portions of that that are affected by this patch).

This is becoming very onerous. (Entity)ResourceTestBase are in flux. They're designed to be in flux. They're effectively NOT an API. Because REST didn't ship with test coverage. So we need to add it now. Therefore it is in flux, while we work towards complete test coverage… it's not reasonable to provide BC. It is reasonable to be mindful of minimizing pain. This patch likely introduces zero pain.

Speaking of which, do we have core issues for adding test coverage for DBLogResource and UserRegistrationResource? And I wonder if independently of that, if we should also have a separate test for a test non-entity resource.

No. Note that there's test coverage for both: \Drupal\dblog\Tests\Rest\DbLogResourceTest +
\Drupal\Tests\user\Unit\UserRegistrationResourceTest. It's just not nearly as comprehensive as the test coverage for entities. Which makes sense, because there's a whole lot more dynamism and therefor edge cases/risk/… to test for entities + REST.

damiankloip’s picture

Are there more abstract methods on ResourceTestBase that can be moved/removed too? None of the abstract methods are actually used in the base class, and therefore don't really belong on there (unless I'm missing something)? Seems like most of this stuff is just a part of the EntityResourceTestBase implementation.

EDIT: Hmm, I guess the test traits that are meant to be used for these contain some of the concrete implementation for the abstract methods, like BasicAuthResourceTestTrait

Wim Leers’s picture

Hmm, I guess the test traits that are meant to be used for these contain some of the concrete implementation for the abstract methods, like BasicAuthResourceTestTrait

Indeed. So I don't think there's more.

tstoeckler’s picture

Not actually sure what to with this issue in terms of the title. I agree that "does not work" is not very specific, but I have a hard time finding clearer words. Because it does actually not work, I also have a hard time writing a change notice because the "before" part is not actually clear, unless we actually want to write a change notice about people being able to remove weird workarounds they had to employ before. That seems non-standard to me, though, in terms of how we generally treat change notices. I could see a legitimate change notice for the third point below, but not sure.

In any case, not really sure what to do here, but here is some more explanation of what the parts of the patch actually mean:

  1. +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
    @@ -104,6 +106,8 @@
    +    $this->serializer = $this->container->get('serializer');
    

    So this part is a legitimate bug and it constitutes the "does not work" part for me. Of course, the workaround is trivial (just add the serializer in your own setUp()) but still.

  2. +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
    @@ -182,6 +186,21 @@ protected function refreshTestStateAfterRestConfigChange() {
    +  protected function getExpectedUnauthorizedAccessMessage($method) {
    +    $resource_plugin_id = str_replace('.', ':', static::$resourceConfigId);
    +    $permission = 'restful ' . strtolower($method) . ' ' . $resource_plugin_id;
    +    return "The '$permission' permission is required.";
    +  }
    
    @@ -240,29 +259,6 @@ protected function refreshTestStateAfterRestConfigChange() {
    -  abstract protected function getExpectedUnauthorizedAccessMessage($method);
    

    This is a mere nuisance as without this ResourceTestBase is less helpful than it could be and you end up implementing this again and again for every test base class in the same way. It's not actually a bug in the strict sense, though.

  3. +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
    @@ -240,29 +259,6 @@ protected function refreshTestStateAfterRestConfigChange() {
    -  /**
    -   * Return the default expected error message if the
    -   * bc_entity_resource_permissions is true.
    -   *
    -   * @param string $method
    -   *   The HTTP method (GET, POST, PATCH, DELETE).
    -   *
    -   * @return string
    -   *   The error string.
    -   */
    -  abstract protected function getExpectedBcUnauthorizedAccessMessage($method);
    

    This is also a bug, as the whole concept of BC permissions does not make sense for non-entity resources. So you have to implement something that is not actually used. Again, the you can just implement it with return 'foo'; and be done with it, but ...

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs change record

I agree with #20, I think the same conclusion as #2869415: EntityResourceTestBase::getUrl() overrides BrowserTestBase::getUrl(), yet offers different functionality applies here: there's no point in a CR for this etc.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: 2869387-11.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community

Random fail in Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest in 8.3.x. Re-testing.

effulgentsia’s picture

Status: Reviewed & tested by the community » Needs review

I think #17 and #20 are great justifications for committing this into 8.4. I'm still not convinced by those arguments that this can safely go into 8.3. If folks here (especially @tstoeckler, who opened the issue) are willing for this to be an 8.4-only issue, then I think it's great as-is. But if there are 8.3 contrib modules that are wanting this, then I think we need to still figure out whether to adjust the patch or the communication about it to production sites.

there's likely zero subclasses of ResourceTestBase in contrib right now

On what basis can we assume this? Each of the items in #20 are easy to work around.

effulgentsia’s picture

Title: ResourceTestBase does not work for tests of non-entity resources » Subclasses of ResourceTestBase for non-entity resources are required to add pointless code

Here's my attempt at a retitle based on #20.

tstoeckler’s picture

Version: 8.3.x-dev » 8.4.x-dev
Status: Needs review » Reviewed & tested by the community

The new title is bit too forgiving for my taste, but be that as it may ;-). I don't mind this landing in 8.4.x only. If I remember correctly contrib tests on Drupal.org are run against 8.4.x anyway, so this would only be for people with their own CI on Github, etc. So marking RTBC per #24

Wim Leers’s picture

I don't mind this landing in 8.4.x only.

Me neither.

Let's do this in 8.4.x only.

  • catch committed 7626a3d on 8.4.x
    Issue #2869387 by tstoeckler, Wim Leers: Subclasses of ResourceTestBase...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.4.x, thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.