00ade5a5ac9f7f666bd28efe237a0891ec97bcb7
[yaffs-website] / web / core / modules / contextual / src / Tests / ContextualDynamicContextTest.php
1 <?php
2
3 namespace Drupal\contextual\Tests;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Url;
7 use Drupal\language\Entity\ConfigurableLanguage;
8 use Drupal\simpletest\WebTestBase;
9 use Drupal\Core\Template\Attribute;
10
11 /**
12  * Tests if contextual links are showing on the front page depending on
13  * permissions.
14  *
15  * @group contextual
16  */
17 class ContextualDynamicContextTest extends WebTestBase {
18
19   /**
20    * A user with permission to access contextual links and edit content.
21    *
22    * @var \Drupal\user\UserInterface
23    */
24   protected $editorUser;
25
26   /**
27    * An authenticated user with permission to access contextual links.
28    *
29    * @var \Drupal\user\UserInterface
30    */
31   protected $authenticatedUser;
32
33   /**
34    * A simulated anonymous user with access only to node content.
35    *
36    * @var \Drupal\user\UserInterface
37    */
38   protected $anonymousUser;
39
40   /**
41    * Modules to enable.
42    *
43    * @var array
44    */
45   public static $modules = ['contextual', 'node', 'views', 'views_ui', 'language', 'menu_test'];
46
47   protected function setUp() {
48     parent::setUp();
49
50     $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
51     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
52
53     ConfigurableLanguage::createFromLangcode('it')->save();
54     $this->rebuildContainer();
55
56     $this->editorUser = $this->drupalCreateUser(['access content', 'access contextual links', 'edit any article content']);
57     $this->authenticatedUser = $this->drupalCreateUser(['access content', 'access contextual links']);
58     $this->anonymousUser = $this->drupalCreateUser(['access content']);
59   }
60
61   /**
62    * Tests contextual links with different permissions.
63    *
64    * Ensures that contextual link placeholders always exist, even if the user is
65    * not allowed to use contextual links.
66    */
67   public function testDifferentPermissions() {
68     $this->drupalLogin($this->editorUser);
69
70     // Create three nodes in the following order:
71     // - An article, which should be user-editable.
72     // - A page, which should not be user-editable.
73     // - A second article, which should also be user-editable.
74     $node1 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]);
75     $node2 = $this->drupalCreateNode(['type' => 'page', 'promote' => 1]);
76     $node3 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]);
77
78     // Now, on the front page, all article nodes should have contextual links
79     // placeholders, as should the view that contains them.
80     $ids = [
81       'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime() . '&langcode=en',
82       'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime() . '&langcode=en',
83       'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=en',
84       'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1&langcode=en',
85     ];
86
87     // Editor user: can access contextual links and can edit articles.
88     $this->drupalGet('node');
89     for ($i = 0; $i < count($ids); $i++) {
90       $this->assertContextualLinkPlaceHolder($ids[$i]);
91     }
92     $this->renderContextualLinks([], 'node');
93     $this->assertResponse(400);
94     $this->assertRaw('No contextual ids specified.');
95     $response = $this->renderContextualLinks($ids, 'node');
96     $this->assertResponse(200);
97     $json = Json::decode($response);
98     $this->assertIdentical($json[$ids[0]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/1/edit">Edit</a></li></ul>');
99     $this->assertIdentical($json[$ids[1]], '');
100     $this->assertIdentical($json[$ids[2]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/3/edit">Edit</a></li></ul>');
101     $this->assertIdentical($json[$ids[3]], '');
102
103     // Verify that link language is properly handled.
104     $node3->addTranslation('it')->set('title', $this->randomString())->save();
105     $id = 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=it';
106     $this->drupalGet('node', ['language' => ConfigurableLanguage::createFromLangcode('it')]);
107     $this->assertContextualLinkPlaceHolder($id);
108
109     // Authenticated user: can access contextual links, cannot edit articles.
110     $this->drupalLogin($this->authenticatedUser);
111     $this->drupalGet('node');
112     for ($i = 0; $i < count($ids); $i++) {
113       $this->assertContextualLinkPlaceHolder($ids[$i]);
114     }
115     $this->renderContextualLinks([], 'node');
116     $this->assertResponse(400);
117     $this->assertRaw('No contextual ids specified.');
118     $response = $this->renderContextualLinks($ids, 'node');
119     $this->assertResponse(200);
120     $json = Json::decode($response);
121     $this->assertIdentical($json[$ids[0]], '');
122     $this->assertIdentical($json[$ids[1]], '');
123     $this->assertIdentical($json[$ids[2]], '');
124     $this->assertIdentical($json[$ids[3]], '');
125
126     // Anonymous user: cannot access contextual links.
127     $this->drupalLogin($this->anonymousUser);
128     $this->drupalGet('node');
129     for ($i = 0; $i < count($ids); $i++) {
130       $this->assertNoContextualLinkPlaceHolder($ids[$i]);
131     }
132     $this->renderContextualLinks([], 'node');
133     $this->assertResponse(403);
134     $this->renderContextualLinks($ids, 'node');
135     $this->assertResponse(403);
136
137     // Get a page where contextual links are directly rendered.
138     $this->drupalGet(Url::fromRoute('menu_test.contextual_test'));
139     $this->assertEscaped("<script>alert('Welcome to the jungle!')</script>");
140     $this->assertRaw('<li class="menu-testcontextual-hidden-manage-edit"><a href="' . base_path() . 'menu-test-contextual/1/edit" class="use-ajax" data-dialog-type="modal" data-is-something>Edit menu - contextual</a></li>');
141   }
142
143   /**
144    * Asserts that a contextual link placeholder with the given id exists.
145    *
146    * @param string $id
147    *   A contextual link id.
148    *
149    * @return bool
150    *   The result of the assertion.
151    */
152   protected function assertContextualLinkPlaceHolder($id) {
153     return $this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
154   }
155
156   /**
157    * Asserts that a contextual link placeholder with the given id does not exist.
158    *
159    * @param string $id
160    *   A contextual link id.
161    *
162    * @return bool
163    *   The result of the assertion.
164    */
165   protected function assertNoContextualLinkPlaceHolder($id) {
166     return $this->assertNoRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id does not exist.', ['@id' => $id]));
167   }
168
169   /**
170    * Get server-rendered contextual links for the given contextual link ids.
171    *
172    * @param array $ids
173    *   An array of contextual link ids.
174    * @param string $current_path
175    *   The Drupal path for the page for which the contextual links are rendered.
176    *
177    * @return string
178    *   The response body.
179    */
180   protected function renderContextualLinks($ids, $current_path) {
181     $post = [];
182     for ($i = 0; $i < count($ids); $i++) {
183       $post['ids[' . $i . ']'] = $ids[$i];
184     }
185     return $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => $current_path]]);
186   }
187
188 }