summaryrefslogtreecommitdiff
path: root/modules/menu/menu.test
blob: 45dd980dc6623f25e24a475460115981eed09c30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
<?php
// $Id$

class MenuTestCase extends DrupalWebTestCase {
  protected $big_user;
  protected $std_user;
  protected $menu;
  protected $items;

  function getInfo() {
    return array(
      'name' => t('Menu item creation/deletion'),
      'description' => t('Add a custom menu, add menu items to the custom menu and Navigation menu, check their data, and delete them using the menu module UI.'),
      'group' => t('Menu')
    );
  }

  function setUp() {
    parent::setUp('menu');
    // Create users.
    $this->big_user = $this->drupalCreateUser(array('access administration pages', 'administer blocks', 'administer menu', 'create article content'));
    $this->std_user = $this->drupalCreateUser(array());
  }

  /**
   * Login users, add menus and menu items, and test menu functionality through the admin and user interfaces.
   */
  function testMenu() {
    // Login the user.
    $this->drupalLogin($this->big_user);
    $this->items = array();

    // Do standard menu tests.
    $this->doStandardMenuTests();

    // Do custom menu tests.
    $this->doCustomMenuTests();

    // Do standard user tests.
    // Login the user.
    $this->drupalLogin($this->std_user);
    $this->verifyAccess(403);
    foreach ($this->items as $item) {
      $node = node_load(substr($item['link_path'], 5)); // Paths were set as 'node/$nid'.
      $this->verifyMenuItem($item, $node);
    }

    // Login the user.
    $this->drupalLogin($this->big_user);

    // Delete menu items.
    foreach ($this->items as $item) {
      $this->deleteMenuItem($item);
    }

    // Delete custom menu.
    $this->deleteCustomMenu($this->menu);

    // Modify and reset a standard menu item.
    $item = $this->getStandardMenuItem();
    $old_title = $item['link_title'];
    $this->modifyMenuItem($item);
    $item = menu_link_load($item['mlid']);
    $this->resetMenuItem($item, $old_title);
  }

  /**
   * Test standard menu functionality using navigation menu.
   *
   */
  function doStandardMenuTests() {
    $this->doMenuTests();
    $this->addInvalidMenuItem();
  }

  /**
   * Test custom menu functionality using navigation menu.
   *
   */
  function doCustomMenuTests() {
    $this->menu = $this->addCustomMenu();
    $this->doMenuTests($this->menu['menu_name']);
    $this->addInvalidMenuItem($this->menu['menu_name']);
  }

  /**
   * Add custom menu.
   *
   */
  function addCustomMenu() {
    // Add custom menu.
    $this->drupalGet('admin/build/menu/add');
    $menu_name = substr(md5($this->randomName(16)), 0, 20);
    $title = $this->randomName(16);
    $edit = array (
      'menu_name' => $menu_name,
      'description' => '',
      'title' =>  $title,
    );
    $this->drupalPost('admin/build/menu/add', $edit, t('Save'));
    // Unlike most other modules, there is no confirmation message displayed.
//    $this->assertText(t('The menu settings have been updated.'), t('Menu link was added'));

    $this->drupalGet('admin/build/menu');
    $this->assertText($title, 'Menu created');

    // Enable the custom menu block.
    $menu_name = 'menu-' . $menu_name; // Drupal prepends the name with 'menu-'.
    $edit = array();
    $edit['menu_' . $menu_name . '[region]'] = 'left';
    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
    $this->assertResponse(200);
    $this->assertText(t('The block settings have been updated.'), t('Custom menu block was enabled'));

    return menu_load($menu_name);
  }

  /**
   * Delete custom menu.
   *
   * @param string $menu_name Custom menu name.
   */
  function deleteCustomMenu($menu) {
    $menu_name = $this->menu['menu_name'];
    $title = $this->menu['title'];

    // Delete custom menu.
    $this->drupalPost("admin/build/menu-customize/$menu_name/delete", array(), t('Delete'));
    $this->assertResponse(200);
    $this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $title)), t('Custom menu was deleted'));
    $this->assertFalse(menu_load($menu_name), 'Custom menu was deleted');
  }

  /**
   * Test menu functionality using navigation menu.
   *
   */
  function doMenuTests($menu_name = 'navigation') {
    // Add nodes to use as links for menu items.
    $node1 = $this->drupalCreateNode(array('type' => 'article', 'uid' => $this->big_user->uid));
    $node2 = $this->drupalCreateNode(array('type' => 'article', 'uid' => $this->big_user->uid));

    // Add menu items.
    $item1 = $this->addMenuItem(0, 'node/' . $node1->nid, $menu_name);
    $item2 = $this->addMenuItem($item1['mlid'], 'node/' . $node2->nid, $menu_name);

    // Verify menu items.
    $this->verifyMenuItem($item1, $node1);
    $this->verifyMenuItem($item2, $node2, $item1, $node1);

    // Modify menu items.
    $this->modifyMenuItem($item1);
    $this->modifyMenuItem($item2);

    // Toggle menu items.
    $this->toggleMenuItem($item1);
    $this->toggleMenuItem($item2);

    // Save menu items for later tests.
    $this->items[] = $item1;
    $this->items[] = $item2;
  }

  /**
   * Add a menu item using the menu module UI.
   *
   * @param integer $plid Parent menu link id.
   * @param string $link Link path.
   * @param string $menu_name Menu name.
   * @return object Menu item created.
   */
  function addMenuItem($plid = 0, $link = '<front>', $menu_name = 'navigation') {
    // View add menu item page.
    $this->drupalGet("admin/build/menu-customize/$menu_name/add");
    $this->assertResponse(200);

    $title = '!link_' . $this->randomName(16);
    $edit = array (
      'menu[link_path]' => $link,
      'menu[link_title]' => $title,
      'menu[description]' => '',
      'menu[enabled]' => TRUE, // Use this to disable the menu and test.
      'menu[expanded]' => TRUE, // Setting this to true should test whether it works when we do the std_user tests.
      'menu[parent]' =>  $menu_name . ':' . $plid,
      'menu[weight]' => '0',
    );

    // Add menu item.
    $this->drupalPost("admin/build/menu-customize/$menu_name/add", $edit, t('Save'));
    $this->assertResponse(200);
    // Unlike most other modules, there is no confirmation message displayed.
//    $this->assertText(t('The menu item %title has been added.', array('%title' => $title)), t('Menu item was added'));
    $this->assertText($title, 'Menu item was added');

    // Retrieve menu item.
    $item = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE link_title = '%s'", $title));

    // Check the structure in the DB of the two menu items.
    // In general, if $n = $item['depth'] then $item['p'. $n] == $item['mlid'] and $item['p' . ($n - 1)] == $item['plid'] (unless depth == 0).
    // All $item['p' . $n] for $n > depth must be 0.
    // We know link1 is at the top level, so $item1['deptj'] == 1 and $item1['plid'] == 0.
    // We know that the parent of link2 is link1, so $item2['plid'] == $item1['mlid'].
    // Both menu items were created in the navigation menu.
    $this->assertTrue($item['menu_name'] == $menu_name && $item['plid'] == $plid && $item['link_path'] == $link && $item['link_title'] == $title, 'Menu item has correct data');
    if ($plid == 0) {
      $this->assertTrue($item['depth'] == 1 && !$item['has_children'] && $item['p1'] == $item['mlid'] && $item['p2'] == 0, 'Menu item has correct data');
    }
    else {
      $this->assertTrue($item['depth'] == 2 && !$item['has_children'] && $item['p1'] == $plid && $item['p2'] == $item['mlid'], 'Menu item has correct data');
    }

    return $item;
  }

  /**
   * Attempt to add menu item with invalid path or no access permission.
   *
   * @param string $menu_name Menu name.
   */
  function addInvalidMenuItem($menu_name = 'navigation') {
    foreach (array('-&-', 'admin/user/permissions') as $link_path) {
      $edit = array (
        'menu[link_path]' => $link_path,
        'menu[link_title]' => 'title',
      );
      $this->drupalPost("admin/build/menu-customize/$menu_name/add", $edit, t('Save'));
      $this->assertRaw(t("The path '@path' is either invalid or you do not have access to it.", array('@path' => $link_path)), 'Menu item was not created');
    }
  }

  /**
   * Verify a menu item using the menu module UI.
   *
   * @param object $item Menu item.
   * @param object $item_node Menu item content node.
   * @param object $parent Parent menu item.
   * @param object $parent_node Parent menu item content node.
   */
  function verifyMenuItem($item, $item_node, $parent = NULL, $parent_node = NULL) {
    // View home page.
    $this->drupalGet('');
    $this->assertResponse(200);

    // Verify parent menu item.
    if (isset($parent)) {
      // Verify menu item.
      $title = $parent['link_title'];
      $this->assertText($title, 'Parent menu item was displayed');

      // Verify menu item link.
      $this->clickLink($title);
      $title = $parent_node->title;
      $this->assertTitle(t("@title | Drupal", array('@title' => $title)), t('Parent menu item link target was correct'));
    }

    // Verify menu item.
    $title = $item['link_title'];
    $this->assertText($title, 'Menu item was displayed');

    // Verify menu item link.
    $this->clickLink($title);
    $title = $item_node->title;
    $this->assertTitle(t("@title | Drupal", array('@title' => $title)), t('Menu item link target was correct'));
  }

  /**
   * Modify a menu item using the menu module UI.
   *
   * @param object &$item Menu item passed by reference.
   */
  function modifyMenuItem(&$item) {
    $item['link_title'] = $this->randomName(16);

    $mlid = $item['mlid'];
    $title = $item['link_title'];

    // Edit menu item.
    $edit = array();
    $edit['menu[link_title]'] = $title;
    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
    $this->assertResponse(200);
    // Unlike most other modules, there is no confirmation message displayed.
//    $this->assertRaw(t('The menu item %title has been updated.', array('%title' => $title)), t('Menu item was edited'));

    // Verify menu item.
    $this->drupalGet('admin/build/menu-customize/' . $item['menu_name']);
    $this->assertText($title, 'Menu item was edited');
  }

  /**
   * Reset a standard menu item using the menu module UI.
   *
   * @param object $item Menu item.
   * @param string $old_title Original title for menu item.
   */
  function resetMenuItem($item, $old_title) {
    $mlid = $item['mlid'];
    $title = $item['link_title'];

    // Reset menu item.
    $this->drupalPost("admin/build/menu/item/$mlid/reset", array(), t('Reset'));
    $this->assertResponse(200);
    $this->assertRaw(t('The menu item was reset to its default settings.'), t('Menu item was reset'));

    // Verify menu item.
    $this->drupalGet('');
    $this->assertNoText($title, 'Menu item was reset');

    // Verify menu item.
    $this->drupalGet('');
    $this->assertText($old_title, 'Menu item was reset');
  }

  /**
   * Delete a menu item using the menu module UI.
   *
   * @param object $item Menu item.
   */
  function deleteMenuItem($item) {
    $mlid = $item['mlid'];
    $title = $item['link_title'];

    // Delete menu item.
    $this->drupalPost("admin/build/menu/item/$mlid/delete", array(), t('Confirm'));
    $this->assertResponse(200);
    $this->assertRaw(t('The menu item %title has been deleted.', array('%title' => $title)), t('Menu item was deleted'));

    // Verify deletion.
    $this->drupalGet('');
    $this->assertNoText($title, 'Menu item was deleted');
  }

  /**
   * Alternately disable and enable a menu item.
   *
   * @param object $item Menu item.
   */
  function toggleMenuItem($item) {
    $mlid = $item['mlid'];
    $title = $item['link_title'];

    // Edit menu item.
    $edit = array();
    $edit['menu[enabled]'] = FALSE;
    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
    $this->assertResponse(200);
    // Unlike most other modules, there is no confirmation message displayed.
//    $this->assertRaw(t('The menu item %title has been updated.', array('%title' => $title)), t('Menu item was edited'));

    // Verify menu item.
    $this->drupalGet('');
    $this->assertNoText($title, 'Menu item was not displayed');

    // Edit menu item.
    $edit['menu[enabled]'] = TRUE;
    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
    $this->assertResponse(200);

    // Verify menu item.
    $this->drupalGet('');
    $this->assertText($title, 'Menu item was displayed');
  }

  /**
   * Get standard menu item.
   *
   */
  private function getStandardMenuItem() {
    // Retrieve menu link id of the Log out menu item, which will always be on the front page.
    $mlid = db_query("SELECT mlid FROM {menu_links} WHERE module = 'system' AND router_path = 'user/logout'")->fetchField();
    $this->assertTrue($mlid > 0, 'Standard menu link id was found');
    // Load menu item.
    // Use api function so that link is translated for rendering.
    $item = menu_link_load($mlid);
    $this->assertTrue((bool)$item, 'Standard menu item was loaded');
    return $item;
  }

  /**
   * Verify the logged in user has the desired access to the various menu nodes.
   *
   * @param integer $response HTTP response code.
   */
  private function verifyAccess($response = 200) {
    // View menu help node.
    $this->drupalGet('admin/help/menu');
    $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Menu'), t('Menu help was displayed'));
    }

    // View menu build overview node.
    $this->drupalGet('admin/build/menu');
    $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Menus'), t('Menu build overview node was displayed'));
    }

    // View navigation menu customization node.
    $this->drupalGet('admin/build/menu-customize/navigation');
        $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Navigation'), t('Navigation menu node was displayed'));
    }

    // View menu edit node.
    $item = $this->getStandardMenuItem();
    $this->drupalGet('admin/build/menu/item/' . $item['mlid'] . '/edit');
    $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Edit menu item'), t('Menu edit node was displayed'));
    }

    // View menu settings node.
    $this->drupalGet('admin/build/menu/settings');
    $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Menus'), t('Menu settings node was displayed'));
    }

    // View add menu node.
    $this->drupalGet('admin/build/menu/add');
    $this->assertResponse($response);
    if ($response == 200) {
      $this->assertText(t('Menus'), t('Add menu node was displayed'));
    }
  }
}