Score:0

phpunit can't find node permissions

ai flag

We have a Functional test class derived from BrowserTestBase which is passing, but the output includes a deprecation notice.

Adding non-existent permissions to a role is deprecated in drupal:9.3.0 and triggers a runtime exception before drupal:10.0.0. The incorrect permissions are "edit any page content". Permissions should be defined in a permissions.yml file or a permission callback. See https://www.drupal.org/node/3193348

The class's $modules array includes the node module, as well as a custom module whose implementation of hook_install() assigns permissions to roles. One of those permissions is the "edit any page content" permission. When the module is installed on the site the permissions are assigned correctly. My understanding of the Node module is that it creates and enables the Article and Page content types by default, exposing the permissions appropriate to those content types, and that is indeed what happens on the site. But phpunit can't find those permissions, even though it knows that loading of the Node module is required. Including a call to $this->drupalCreateContentType() in setUp() doesn't eliminate the notice. Presumably if I don't figure this out the tests will start failing when we try to move to Drupal 10. We could work around the problem by backing out the code to assign the permission in the hook, and just assign it manually, but that's kind of ugly. I could also hack the hook implementation to detect when it's running under phpunit (assuming that's possible), and skip that assignment in that case, but that's also hackier than I would like.

ai flag
Thanks for the edits, @apaderno. I looked at the documentation for the "9" tag which I thought said something like "don't use this just to indicate which version of Drupal you're running." I guess I didn't understand what they were trying to say.
apaderno avatar
us flag
It is trying to convey the concept that not every question needs to use a version tag. In this case, [tag:9] is fine as Drupal 10 is the latest release and it is important to make clear you are not asking a question for Drupal 10. If I misunderstood the question, and it is a question for Drupal 10, I apologize.
ai flag
OK, thanks for the clarification. For future questions, how would I convey that the question does not apply to versions of Drupal older than 8, but might apply to any version after 7 (bearing in mind that since I haven't upgraded to 10 yet I won't know for sure that the question would be appropriate for that version, hence the "might apply" above)?
apaderno avatar
us flag
It does not apply to any version after Drupal 8, but it may apply to any version after Drupal 7, means the question is about Drupal 8 and it should be tagged [tag:8]. Do not worry too much about version tags; if it is better not to use them in a question, they will just be removed. We cannot pretend users understand every time how to use them; we just ask not to use two or more version tags in the same question.
ai flag
Sure. I was just trying to get with the program. I read the guidelines, which seemed to say I shouldn't use a version tag here, so that's what I did. Then I saw that you added the version tag, so I figured I must have misunderstood those guidelines.
Score:0
ai flag

I believe I have figured out what we need to do, and it's a sort of a variation on the second of the two workarounds I identified in the original question above. As far as I can tell, my assumption that installing the node module automatically created and enabled the article and page content types was not valid. I now think that this magic is handled by the drush site:install command, probably in connection with the default profile it uses. Since phpunit can't take advantage of that magic, the install hook implementation really does have to figure out whether it's running as part of a test (by finding out if the content types have already been created) and if so, it must itself create the type whose permission it wants to install. After adding this to the top of that hook implementation:

  $types = \Drupal::entityTypeManager()
    ->getStorage('node_type')
    ->loadMultiple();
  if (!array_key_exists('page', $types)) {
    $type = NodeType::create(['type' => 'page', 'name' => 'Basic page']);
    $type->save();
  }

... the deprecation warning is gone. The permissions are brought into existence automatically when the content type is created, but the creation of the content type does not happen just by virtue of enabling the node module.

Kevin avatar
in flag
A content type would be made using either the standard install profile, or a custom install profile that includes content type(s). Enabling the node module alone does not create any.
Kevin avatar
in flag
Having said that, no, the need to set up configuration like this to provide the conditions for testing aren't bad or hacky. It can be done via install profile, test module configurations, or doing configuration inline in the test itself (which may be more manageble than piles of yaml files just for tests).
ai flag
Yes, I don't think of the solution I hit on as a hack, as it ensures that the permissions during testing match those in effect for production use. What I would have been uncomfortable with was the workaround as I originally described it, as it would have had the opposite effect, avoiding setting a permission which would be set in normal operations in order to avoid the deprecation message (and eventual error). The approach I settled on gives us the the best of both worlds: consistent permissions without deprecated behavior.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.