Projet

Général

Profil

Paste
Télécharger (23 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / feeds / tests / feeds.test @ 41cc1b08

1
<?php
2

    
3
/**
4
 * @file
5
 * Common functionality for all Feeds tests.
6
 */
7

    
8
/**
9
 * Test basic Data API functionality.
10
 */
11
class FeedsWebTestCase extends DrupalWebTestCase {
12
  protected $profile = 'testing';
13

    
14
  public function setUp() {
15
    $args = func_get_args();
16

    
17
    // Build the list of required modules which can be altered by passing in an
18
    // array of module names to setUp().
19
    if (isset($args[0])) {
20
      if (is_array($args[0])) {
21
        $modules = $args[0];
22
      }
23
      else {
24
        $modules = $args;
25
      }
26
    }
27
    else {
28
      $modules = array();
29
    }
30

    
31
    $modules[] = 'taxonomy';
32
    $modules[] = 'image';
33
    $modules[] = 'file';
34
    $modules[] = 'field';
35
    $modules[] = 'field_ui';
36
    $modules[] = 'feeds';
37
    $modules[] = 'feeds_ui';
38
    $modules[] = 'feeds_tests';
39
    $modules[] = 'ctools';
40
    $modules[] = 'job_scheduler';
41
    $modules = array_unique($modules);
42
    parent::setUp($modules);
43

    
44
    // Add text formats Directly.
45
    $filtered_html_format = array(
46
      'format' => 'filtered_html',
47
      'name' => 'Filtered HTML',
48
      'weight' => 0,
49
      'filters' => array(
50
        // URL filter.
51
        'filter_url' => array(
52
          'weight' => 0,
53
          'status' => 1,
54
        ),
55
        // HTML filter.
56
        'filter_html' => array(
57
          'weight' => 1,
58
          'status' => 1,
59
        ),
60
        // Line break filter.
61
        'filter_autop' => array(
62
          'weight' => 2,
63
          'status' => 1,
64
        ),
65
        // HTML corrector filter.
66
        'filter_htmlcorrector' => array(
67
          'weight' => 10,
68
          'status' => 1,
69
        ),
70
      ),
71
    );
72
    $filtered_html_format = (object) $filtered_html_format;
73
    filter_format_save($filtered_html_format);
74

    
75
    // Build the list of required administration permissions. Additional
76
    // permissions can be passed as an array into setUp()'s second parameter.
77
    if (isset($args[1]) && is_array($args[1])) {
78
      $permissions = $args[1];
79
    }
80
    else {
81
      $permissions = array();
82
    }
83

    
84
    $permissions[] = 'access content';
85
    $permissions[] = 'administer site configuration';
86
    $permissions[] = 'administer content types';
87
    $permissions[] = 'administer nodes';
88
    $permissions[] = 'bypass node access';
89
    $permissions[] = 'administer taxonomy';
90
    $permissions[] = 'administer users';
91
    $permissions[] = 'administer feeds';
92
    $permissions[] = 'administer filters';
93

    
94
    // Create an admin user and log in.
95
    $this->admin_user = $this->drupalCreateUser($permissions);
96
    $this->drupalLogin($this->admin_user);
97

    
98
    $types = array(
99
      array(
100
        'type' => 'page',
101
        'name' => 'Basic page',
102
        'node_options[status]' => 1,
103
        'node_options[promote]' => 0,
104
      ),
105
      array(
106
        'type' => 'article',
107
        'name' => 'Article',
108
        'node_options[status]' => 1,
109
        'node_options[promote]' => 1,
110
      ),
111
    );
112
    foreach ($types as $type) {
113
      $this->drupalPost('admin/structure/types/add', $type, 'Save content type');
114
      $this->assertText("The content type " . $type['name'] . " has been added.");
115
    }
116
  }
117

    
118
  /**
119
   * Absolute path to Drupal root.
120
   */
121
  public function absolute() {
122
    return realpath(getcwd());
123
  }
124

    
125
  /**
126
   * Get the absolute directory path of the feeds module.
127
   */
128
  public function absolutePath() {
129
    return  $this->absolute() . '/' . drupal_get_path('module', 'feeds');
130
  }
131

    
132
  /**
133
   * Generate an OPML test feed.
134
   *
135
   * The purpose of this function is to create a dynamic OPML feed that points
136
   * to feeds included in this test.
137
   */
138
  public function generateOPML() {
139
    $path = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/';
140

    
141
  $output =
142
'<?xml version="1.0" encoding="utf-8"?>
143
<opml version="1.1">
144
<head>
145
    <title>Feeds test OPML</title>
146
    <dateCreated>Fri, 16 Oct 2009 02:53:17 GMT</dateCreated>
147
    <ownerName></ownerName>
148
</head>
149
<body>
150
  <outline text="Feeds test group" >
151
    <outline title="Development Seed - Technological Solutions for Progressive Organizations" text="" xmlUrl="' . $path . 'developmentseed.rss2" type="rss" />
152
    <outline title="Magyar Nemzet Online - H\'rek" text="" xmlUrl="' . $path . 'feed_without_guid.rss2" type="rss" />
153
    <outline title="Drupal planet" text="" type="rss" xmlUrl="' . $path . 'drupalplanet.rss2" />
154
  </outline>
155
</body>
156
</opml>';
157

    
158
    // UTF 8 encode output string and write it to disk
159
    $output = utf8_encode($output);
160
    $filename = file_default_scheme() . '://test-opml-' . $this->randomName() . '.opml';
161

    
162
    $filename = file_unmanaged_save_data($output, $filename);
163
    return $filename;
164
  }
165

    
166
  /**
167
   * Create an importer configuration.
168
   *
169
   * @param $name
170
   *   The natural name of the feed.
171
   * @param $id
172
   *   The persistent id of the feed.
173
   * @param $edit
174
   *   Optional array that defines the basic settings for the feed in a format
175
   *   that can be posted to the feed's basic settings form.
176
   */
177
  public function createImporterConfiguration($name = 'Syndication', $id = 'syndication') {
178
    // Create new feed configuration.
179
    $this->drupalGet('admin/structure/feeds');
180
    $this->clickLink('Add importer');
181
    $edit = array(
182
      'name' => $name,
183
      'id' => $id,
184
    );
185
    $this->drupalPost('admin/structure/feeds/create', $edit, 'Create');
186

    
187
    // Assert message and presence of default plugins.
188
    $this->assertText('Your configuration has been created with default settings.');
189
    $this->assertPlugins($id, 'FeedsHTTPFetcher', 'FeedsSyndicationParser', 'FeedsNodeProcessor');
190
    // Per default attach to page content type.
191
    $this->setSettings($id, NULL, array('content_type' => 'page'));
192
    // Per default attached to article content type.
193
    $this->setSettings($id, 'FeedsNodeProcessor', array('bundle' => 'article'));
194
  }
195

    
196
  /**
197
   * Choose a plugin for a importer configuration and assert it.
198
   *
199
   * @param $id
200
   *   The importer configuration's id.
201
   * @param $plugin_key
202
   *   The key string of the plugin to choose (one of the keys defined in
203
   *   feeds_feeds_plugins()).
204
   */
205
  public function setPlugin($id, $plugin_key) {
206
    if ($type = FeedsPlugin::typeOf($plugin_key)) {
207
      $edit = array(
208
        'plugin_key' => $plugin_key,
209
      );
210
      $this->drupalPost("admin/structure/feeds/$id/$type", $edit, 'Save');
211

    
212
      // Assert actual configuration.
213
      $config = unserialize(db_query("SELECT config FROM {feeds_importer} WHERE id = :id", array(':id' => $id))->fetchField());
214
      $this->assertEqual($config[$type]['plugin_key'], $plugin_key, 'Verified correct ' . $type . ' (' . $plugin_key . ').');
215
    }
216
  }
217

    
218
  /**
219
   * Set importer or plugin settings.
220
   *
221
   * @param $id
222
   *   The importer configuration's id.
223
   * @param $plugin
224
   *   The plugin (class) name, or NULL to set importer's settings
225
   * @param $settings
226
   *   The settings to set.
227
   */
228
  public function setSettings($id, $plugin, $settings) {
229
    $this->drupalPost('admin/structure/feeds/' . $id . '/settings/' . $plugin, $settings, 'Save');
230
    $this->assertText('Your changes have been saved.');
231
  }
232

    
233
  /**
234
   * Create a test feed node. Test user has to have sufficient permissions:
235
   *
236
   * * create [type] content
237
   * * use feeds
238
   *
239
   * Assumes that page content type has been configured with
240
   * createImporterConfiguration() as a feed content type.
241
   *
242
   * @return
243
   *   The node id of the node created.
244
   */
245
  public function createFeedNode($id = 'syndication', $feed_url = NULL, $title = '', $content_type = NULL) {
246
    if (empty($feed_url)) {
247
      $feed_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2';
248
    }
249

    
250
    // If content type not given, retrieve it.
251
    if (!$content_type) {
252
      $result= db_select('feeds_importer', 'f')
253
        ->condition('f.id', $id, '=')
254
        ->fields('f', array('config'))
255
        ->execute();
256
      $config = unserialize($result->fetchField());
257
      $content_type = $config['content_type'];
258
      $this->assertFalse(empty($content_type), 'Valid content type found: ' . $content_type);
259
    }
260

    
261
    // Create a feed node.
262
    $edit = array(
263
      'title' => $title,
264
      'feeds[FeedsHTTPFetcher][source]' => $feed_url,
265
    );
266
    $this->drupalPost('node/add/' . str_replace('_', '-', $content_type), $edit, 'Save');
267
    $this->assertText('has been created.');
268

    
269
    // Get the node id from URL.
270
    $nid = $this->getNid($this->getUrl());
271

    
272
    // Check whether feed got recorded in feeds_source table.
273
    $query = db_select('feeds_source', 's')
274
      ->condition('s.id', $id, '=')
275
      ->condition('s.feed_nid', $nid, '=');
276
    $query->addExpression("COUNT(*)");
277
    $result = $query->execute()->fetchField();
278
    $this->assertEqual(1, $result);
279

    
280
    $source = db_select('feeds_source', 's')
281
      ->condition('s.id', $id, '=')
282
      ->condition('s.feed_nid', $nid, '=')
283
      ->fields('s', array('config'))
284
      ->execute()->fetchObject();
285
    $config = unserialize($source->config);
286
    $this->assertEqual($config['FeedsHTTPFetcher']['source'], $feed_url, t('URL in DB correct.'));
287
    return $nid;
288
  }
289

    
290
  /**
291
   * Edit the configuration of a feed node to test update behavior.
292
   *
293
   * @param $nid
294
   *   The nid to edit.
295
   * @param $feed_url
296
   *   The new (absolute) feed URL to use.
297
   * @param $title
298
   *   Optional parameter to change title of feed node.
299
   */
300
  public function editFeedNode($nid, $feed_url, $title = '') {
301
    $edit = array(
302
      'title' => $title,
303
      'feeds[FeedsHTTPFetcher][source]' => $feed_url,
304
    );
305
    // Check that the update was saved.
306
    $this->drupalPost('node/' . $nid . '/edit', $edit, 'Save');
307
    $this->assertText('has been updated.');
308

    
309
    // Check that the URL was updated in the feeds_source table.
310
    $source = db_query("SELECT * FROM {feeds_source} WHERE feed_nid = :nid", array(':nid' => $nid))->fetchObject();
311
    $config = unserialize($source->config);
312
    $this->assertEqual($config['FeedsHTTPFetcher']['source'], $feed_url, t('URL in DB correct.'));
313
  }
314

    
315
  /**
316
   * Batch create a variable amount of feed nodes. All will have the
317
   * same URL configured.
318
   *
319
   * @return
320
   *   An array of node ids of the nodes created.
321
   */
322
  public function createFeedNodes($id = 'syndication', $num = 20, $content_type = NULL) {
323
    $nids = array();
324
    for ($i = 0; $i < $num; $i++) {
325
      $nids[] = $this->createFeedNode($id, NULL, $this->randomName(), $content_type);
326
    }
327
    return $nids;
328
  }
329

    
330
  /**
331
   * Import a URL through the import form. Assumes FeedsHTTPFetcher in place.
332
   */
333
  public function importURL($id, $feed_url = NULL) {
334
    if (empty($feed_url)) {
335
      $feed_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2';
336
    }
337
    $edit = array(
338
      'feeds[FeedsHTTPFetcher][source]' => $feed_url,
339
    );
340
    $nid = $this->drupalPost('import/' . $id, $edit, 'Import');
341

    
342
    // Check whether feed got recorded in feeds_source table.
343
    $this->assertEqual(1, db_query("SELECT COUNT(*) FROM {feeds_source} WHERE id = :id AND feed_nid = 0", array(':id' => $id))->fetchField());
344
    $source = db_query("SELECT * FROM {feeds_source} WHERE id = :id AND feed_nid = 0",  array(':id' => $id))->fetchObject();
345
    $config = unserialize($source->config);
346
    $this->assertEqual($config['FeedsHTTPFetcher']['source'], $feed_url, t('URL in DB correct.'));
347

    
348
    // Check whether feed got properly added to scheduler.
349
    $this->assertEqual(1, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = :id AND id = 0 AND name = 'feeds_source_import' AND last <> 0 AND scheduled = 0", array(':id' => $id))->fetchField());
350
    // Check expire scheduler.
351
    if (feeds_importer($id)->processor->expiryTime() == FEEDS_EXPIRE_NEVER) {
352
      $this->assertEqual(0, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = :id AND id = 0 AND name = 'feeds_source_expire'", array(':id' => $id))->fetchField());
353
    }
354
    else {
355
      $this->assertEqual(1, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = :id AND id = 0 AND name = 'feeds_source_expire'", array(':id' => $id))->fetchField());
356
    }
357
  }
358

    
359
  /**
360
   * Import a file through the import form. Assumes FeedsFileFetcher in place.
361
   */
362
  public function importFile($id, $file) {
363

    
364
    $this->assertTrue(file_exists($file), 'Source file exists');
365
    $edit = array(
366
      'files[feeds]' => $file,
367
    );
368
    $this->drupalPost('import/' . $id, $edit, 'Import');
369
  }
370

    
371
  /**
372
   * Assert a feeds configuration's plugins.
373
   *
374
   * @deprecated:
375
   *   Use setPlugin() instead.
376
   *
377
   * @todo Refactor users of assertPlugin() and make them use setPugin() instead.
378
   */
379
  public function assertPlugins($id, $fetcher, $parser, $processor) {
380
    // Assert actual configuration.
381
    $config = unserialize(db_query("SELECT config FROM {feeds_importer} WHERE id = :id", array(':id' => $id))->fetchField());
382

    
383
    $this->assertEqual($config['fetcher']['plugin_key'], $fetcher, 'Correct fetcher');
384
    $this->assertEqual($config['parser']['plugin_key'], $parser, 'Correct parser');
385
    $this->assertEqual($config['processor']['plugin_key'], $processor, 'Correct processor');
386
  }
387

    
388
  /**
389
   * Overrides DrupalWebTestCase::assertFieldByXPath().
390
   *
391
   * The core version has a bug, this is the D8 version.
392
   *
393
   * @todo Remove once https://drupal.org/node/2105617 lands.
394
   */
395
  protected function assertFieldByXPath($xpath, $value = NULL, $message = '', $group = 'Other') {
396
    $fields = $this->xpath($xpath);
397

    
398
    // If value specified then check array for match.
399
    $found = TRUE;
400
    if (isset($value)) {
401
      $found = FALSE;
402
      if ($fields) {
403
        foreach ($fields as $field) {
404
          if (isset($field['value']) && $field['value'] == $value) {
405
            // Input element with correct value.
406
            $found = TRUE;
407
          }
408
          elseif (isset($field->option) || isset($field->optgroup)) {
409
            // Select element found.
410
            $selected = $this->getSelectedItem($field);
411
            if ($selected === FALSE) {
412
              // No item selected so use first item.
413
              $items = $this->getAllOptions($field);
414
              if (!empty($items) && $items[0]['value'] == $value) {
415
                $found = TRUE;
416
              }
417
            }
418
            elseif ($selected == $value) {
419
              $found = TRUE;
420
            }
421
          }
422
          elseif ((string) $field == $value) {
423
            // Text area with correct text.
424
            $found = TRUE;
425
          }
426
        }
427
      }
428
    }
429
    return $this->assertTrue($fields && $found, $message, $group);
430
  }
431

    
432
   /**
433
    * Adds mappings to a given configuration.
434
    *
435
    * @param string $id
436
    *   ID of the importer.
437
    * @param array $mappings
438
    *   An array of mapping arrays. Each mapping array must have a source and
439
    *   an target key and can have a unique key.
440
    * @param bool $test_mappings
441
    *   (optional) TRUE to automatically test mapping configs. Defaults to TRUE.
442
    */
443
  public function addMappings($id, array $mappings, $test_mappings = TRUE) {
444

    
445
    $path = "admin/structure/feeds/$id/mapping";
446

    
447
    // Iterate through all mappings and add the mapping via the form.
448
    foreach ($mappings as $i => $mapping) {
449

    
450
      if ($test_mappings) {
451
        $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
452
        $this->assertEqual($current_mapping_key, -1, 'Mapping does not exist before addition.');
453
      }
454

    
455
      // Get unique flag and unset it. Otherwise, drupalPost will complain that
456
      // Split up config and mapping.
457
      $config = $mapping;
458
      unset($config['source'], $config['target']);
459
      $mapping = array('source' => $mapping['source'], 'target' => $mapping['target']);
460

    
461
      // Add mapping.
462
      $this->drupalPost($path, $mapping, t('Save'));
463

    
464
      // If there are other configuration options, set them.
465
      if ($config) {
466
        $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_' . $i);
467

    
468
        // Set some settings.
469
        $edit = array();
470
        foreach ($config as $key => $value) {
471
          $edit["config[$i][settings][$key]"] = $value;
472
        }
473
        $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_' . $i);
474
        $this->drupalPost(NULL, array(), t('Save'));
475
      }
476

    
477
      if ($test_mappings) {
478
        $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
479
        $this->assertTrue($current_mapping_key >= 0, 'Mapping exists after addition.');
480
      }
481
    }
482
  }
483

    
484
  /**
485
   * Remove mappings from a given configuration.
486
   *
487
   * @param string $id
488
   *   ID of the importer.
489
   * @param array $mappings
490
   *   An array of mapping arrays. Each mapping array must have a source and
491
   *   a target key and can have a unique key.
492
   * @param bool $test_mappings
493
   *   (optional) TRUE to automatically test mapping configs. Defaults to TRUE.
494
   */
495
  public function removeMappings($id, array $mappings, $test_mappings = TRUE) {
496
    $path = "admin/structure/feeds/$id/mapping";
497

    
498
    $edit = array();
499

    
500
    // Iterate through all mappings and remove via the form.
501
    foreach ($mappings as $i => $mapping) {
502

    
503
      if ($test_mappings) {
504
        $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
505
        $this->assertEqual($current_mapping_key, $i, 'Mapping exists before removal.');
506
      }
507

    
508
      $edit["remove_flags[$i]"] = 1;
509
    }
510

    
511
    $this->drupalPost($path, $edit, t('Save'));
512
    $this->assertText('Your changes have been saved.');
513
  }
514

    
515
  /**
516
   * Gets an array of current mappings from the feeds_importer config.
517
   *
518
   * @param string $id
519
   *   ID of the importer.
520
   *
521
   * @return bool|array
522
   *   FALSE if the importer has no mappings, or an an array of mappings.
523
   */
524
  public function getCurrentMappings($id) {
525
    $config = db_query("SELECT config FROM {feeds_importer} WHERE id = :id", array(':id' => $id))->fetchField();
526

    
527
    $config = unserialize($config);
528

    
529
    // We are very specific here. 'mappings' can either be an array or not
530
    // exist.
531
    if (array_key_exists('mappings', $config['processor']['config'])) {
532
      $this->assertTrue(is_array($config['processor']['config']['mappings']), 'Mappings is an array.');
533

    
534
      return $config['processor']['config']['mappings'];
535
    }
536

    
537
    return FALSE;
538
  }
539

    
540
  /**
541
   * Determines if a mapping exists for a given importer.
542
   *
543
   * @param string $id
544
   *   ID of the importer.
545
   * @param integer $i
546
   *   The key of the mapping.
547
   * @param string $source
548
   *   The source field.
549
   * @param string $target
550
   *   The target field.
551
   *
552
   * @return integer
553
   *   -1 if the mapping doesn't exist, the key of the mapping otherwise.
554
   */
555
  public function mappingExists($id, $i, $source, $target) {
556

    
557
    $current_mappings = $this->getCurrentMappings($id);
558

    
559
    if ($current_mappings) {
560
      foreach ($current_mappings as $key => $mapping) {
561
        if ($mapping['source'] == $source && $mapping['target'] == $target && $key == $i) {
562
          return $key;
563
        }
564
      }
565
    }
566

    
567
    return -1;
568
  }
569

    
570
  /**
571
   * Helper function, retrieves node id from a URL.
572
   */
573
  public function getNid($url) {
574
    $matches = array();
575
    preg_match('/node\/(\d+?)$/', $url, $matches);
576
    $nid = $matches[1];
577

    
578
    // Test for actual integerness.
579
    $this->assertTrue($nid === (string) (int) $nid, 'Node id is an integer.');
580

    
581
    return $nid;
582
  }
583

    
584
  /**
585
   * Copies a directory.
586
   */
587
  public function copyDir($source, $dest) {
588
    $result = file_prepare_directory($dest, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
589
    foreach (@scandir($source) as $file) {
590
      if (is_file("$source/$file")) {
591
        $file = file_unmanaged_copy("$source/$file", "$dest/$file");
592
      }
593
    }
594
  }
595

    
596
  /**
597
   * Download and extract SimplePIE.
598
   *
599
   * Sets the 'feeds_simplepie_library_dir' variable to the directory where
600
   * SimplePie is downloaded.
601
   */
602
  function downloadExtractSimplePie($version) {
603
    $url = "http://simplepie.org/downloads/simplepie_$version.mini.php";
604
    $filename = 'simplepie.mini.php';
605

    
606
    // Avoid downloading the file dozens of times
607
    $library_dir = DRUPAL_ROOT . '/' . $this->originalFileDirectory . '/simpletest/feeds';
608
    $simplepie_library_dir = $library_dir . '/simplepie';
609

    
610
    if (!file_exists($library_dir)) {
611
      drupal_mkdir($library_dir);
612
    }
613

    
614
    if (!file_exists($simplepie_library_dir)) {
615
      drupal_mkdir($simplepie_library_dir);
616
    }
617

    
618
    // Local file name.
619
    $local_file = $simplepie_library_dir . '/' . $filename;
620

    
621
    // Begin single threaded code.
622
    if (function_exists('sem_get')) {
623
      $semaphore = sem_get(ftok(__FILE__, 1));
624
      sem_acquire($semaphore);
625
    }
626

    
627
    // Download and extact the archive, but only in one thread.
628
    if (!file_exists($local_file)) {
629
      $local_file = system_retrieve_file($url, $local_file, FALSE, FILE_EXISTS_REPLACE);
630
    }
631

    
632
    if (function_exists('sem_get')) {
633
      sem_release($semaphore);
634
    }
635
    // End single threaded code.
636

    
637
    // Verify that files were successfully extracted.
638
    $this->assertTrue(file_exists($local_file), t('@file found.', array('@file' => $local_file)));
639

    
640
    // Set the simpletest library directory.
641
    variable_set('feeds_library_dir', $library_dir);
642
  }
643
}
644

    
645
/**
646
 * Provides a wrapper for DrupalUnitTestCase for Feeds unit testing.
647
 */
648
class FeedsUnitTestHelper extends DrupalUnitTestCase {
649
  public function setUp() {
650
    parent::setUp();
651

    
652
    // Manually include the feeds module.
653
    // @todo Allow an array of modules from the child class.
654
    drupal_load('module', 'feeds');
655
  }
656
}
657

    
658
class FeedsUnitTestCase extends FeedsUnitTestHelper {
659
  public static function getInfo() {
660
    return array(
661
      'name' => 'Unit tests',
662
      'description' => 'Test basic low-level Feeds module functionality.',
663
      'group' => 'Feeds',
664
    );
665
  }
666

    
667
  /**
668
   * Test valid absolute urls.
669
   *
670
   * @see ValidUrlTestCase
671
   *
672
   * @todo Remove when http://drupal.org/node/1191252 is fixed.
673
   */
674
  function testFeedsValidURL() {
675
    $url_schemes = array('http', 'https', 'ftp', 'feed', 'webcal');
676
    $valid_absolute_urls = array(
677
      'example.com',
678
      'www.example.com',
679
      'ex-ample.com',
680
      '3xampl3.com',
681
      'example.com/paren(the)sis',
682
      'example.com/index.html#pagetop',
683
      'example.com:8080',
684
      'subdomain.example.com',
685
      'example.com/index.php?q=node',
686
      'example.com/index.php?q=node&param=false',
687
      'user@www.example.com',
688
      'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop',
689
      '127.0.0.1',
690
      'example.org?',
691
      'john%20doe:secret:foo@example.org/',
692
      'example.org/~,$\'*;',
693
      'caf%C3%A9.example.org',
694
      '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
695
      'graph.asfdasdfasdf.com/blarg/feed?access_token=133283760145143|tGew8jbxi1ctfVlYh35CPYij1eE',
696
    );
697

    
698
    foreach ($url_schemes as $scheme) {
699
      foreach ($valid_absolute_urls as $url) {
700
        $test_url = $scheme . '://' . $url;
701
        $valid_url = feeds_valid_url($test_url, TRUE);
702
        $this->assertTrue($valid_url, t('@url is a valid url.', array('@url' => $test_url)));
703
      }
704
    }
705

    
706
    $invalid_ablosule_urls = array(
707
      '',
708
      'ex!ample.com',
709
      'ex%ample.com',
710
    );
711

    
712
    foreach ($url_schemes as $scheme) {
713
      foreach ($invalid_ablosule_urls as $url) {
714
        $test_url = $scheme . '://' . $url;
715
        $valid_url = feeds_valid_url($test_url, TRUE);
716
        $this->assertFalse($valid_url, t('@url is NOT a valid url.', array('@url' => $test_url)));
717
      }
718
    }
719
  }
720
}