diff --git a/dfp.info b/dfp.info index 1334cea..9f92d5b 100755 --- a/dfp.info +++ b/dfp.info @@ -16,6 +16,12 @@ dependencies[] = taxonomy files[] = plugins/export_ui/dfp_tag_ui.class.inc files[] = plugins/export_ui/dfp_ctools_export_ui.inc -files[] = tests/dfp.test +files[] = tests/dfp_ad_categories.test +files[] = tests/dfp_ads.test +files[] = tests/dfp_base.test +files[] = tests/dfp_display_tag.test +files[] = tests/dfp_globals.test +files[] = tests/dfp_tokens.test +files[] = tests/dfp_unit.test testing_api = 2.x diff --git a/tests/dfp.test b/tests/dfp.test deleted file mode 100644 index c8d344c..0000000 --- a/tests/dfp.test +++ /dev/null @@ -1,565 +0,0 @@ -admin_user = $this->drupalCreateUser(array('administer DFP', 'administer taxonomy', 'access administration pages', 'administer blocks', 'bypass node access', 'administer nodes', 'edit terms in 1')); - $this->drupalLogin($this->admin_user); - - // Add the some global settings needed for dfp ads to work. - variable_set('dfp_network_id', '12345'); - variable_set('dfp_default_slug', $this->randomName(8)); - } - - /** - * Create a simple $edit array to be used on the DFP tag form to create a new - * DFP tag object. - */ - function dfpBasicTagEditValues() { - $machinename = drupal_strtolower($this->randomName(8)); - $basic_tag = array( - 'machinename' => $machinename, - 'slot' => $machinename, - 'size' => implode(',', $this->dfpGenerateSize(2)), - 'adunit' => $this->randomName(8), - 'block' => 1, - 'settings[slug]' => $this->randomName(32), - 'settings[adsense_ad_types]' => '', - 'settings[adsense_channel_ids]' => '', - 'settings[adsense_colors][background]' => '', - 'settings[adsense_colors][border]' => '', - 'settings[adsense_colors][link]' => '', - 'settings[adsense_colors][text]' => '', - 'settings[adsense_colors][url]' => '', - 'targeting[0][target]' => $this->randomName(8), - 'targeting[0][value]' => $this->randomName(8), - 'breakpoints[0][browser_size]' => $this->dfpGenerateSize(), - 'breakpoints[0][ad_sizes]' => implode(',', $this->dfpGenerateSize(2)), - ); - - return $basic_tag; - } - - /** - * Generate a random size (or array or sizes) to use when testing tags - * formatted as ###x###. - */ - function dfpGenerateSize($count = 1) { - $sizes = array('300x250', '300x600', '728x90', '728x10', '160x600', '120x80', '300x100', '50x50', '160x300'); - shuffle($sizes); - - return $count == 1 ? array_pop($sizes) : array_slice($sizes, 0, min($count, count($sizes))); - } - - /** - * Creates a basic dfp ad tag. - */ - function createTag($edit = array()) { - // Create a new tag. - $edit += $this->dfpBasicTagEditValues(); - $this->drupalPost('admin/structure/dfp_ads/add', $edit, t('Save')); - - // Load the tag object. - $tag = dfp_tag_load($edit['machinename']); - $this->assertTrue(is_object($tag) && $tag->machinename = $edit['machinename'], 'The new tag was saved correctly.'); - - // Display the new tag. - $edit = array(); - $delta = 'dfp_' . (drupal_strlen($tag->machinename) >= 32 ? md5($tag->machinename) : $tag->machinename); - $edit['blocks[' . $delta . '][region]'] = 'sidebar_first'; - $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); - - return $tag; - } - - /** - * Edit a given tag specified by $machinename with the given values. - */ - function editTag($machinename, &$edit) { - // Make sure there is no machinename set when we are editing. - if (isset($edit['machinename'])) { - unset($edit['machinename']); - } - $this->drupalPost('admin/structure/dfp_ads/list/' . $machinename . '/edit', $edit, t('Save')); - $tag = dfp_tag_load($machinename); - return $tag; - } - - /** - * Create a taxonomy term. - */ - function createTerm($vocabulary) { - $term = new stdClass(); - $term->name = $this->randomName(); - $term->description = $this->randomName(); - // Use the first available text format. - $term->format = db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(); - $term->vid = $vocabulary->vid; - taxonomy_term_save($term); - return $term; - } - - /** - * Assert that a property is properly being set. - */ - function assertPropertySet($property, $key, $val) { - $pattern = '|' . '.set' . $property . '\("' . $key . '",{1}\s(.)*' . addslashes($val) . '|'; - $this->assertPattern($pattern, 'A ' . $property . ' property was set for ' . $key . ' = ' . $val); - } - - /** - * Assert that a property is not being set. - */ - function assertPropertyNotSet($property, $key, $val) { - $pattern = '|' . '.set' . $property . '\("' . $key . '",{1}\s(.)*' . addslashes($val) . '|'; - $this->assertNoPattern($pattern, 'A ' . $property . ' property was not set for ' . $key . ' = ' . $val); - } - -} - -class dfpDisplayTagTest extends dfpBaseTest { - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('Displaying DFP Tags'), - 'description' => t('Tests for displaying DFP tags.'), - 'group' => t('DFP'), - ); - } - - function testDisplayTag() { - // Create a simple tag as a block. - $tag = $this->createTag(); - $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $tag->adunit . '", ' . dfp_format_size($tag->size) . ', "' . $tag->placeholder_id . '")', 'The ad slot has been correctly defined in javascript.'); - - // Create a tag with a machine name longer than 32 characters. - $edit = array('machinename' => drupal_strtolower($this->randomName(64))); - $tag = $this->createTag($edit); - $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $tag->adunit . '", ' . dfp_format_size($tag->size) . ', "' . $tag->placeholder_id . '")', 'The ad slot with a very long machine name has been correctly defined in javascript.'); - - // Ensure the DPF click url is safe. - variable_set('dfp_click_url', 'javascript://example.com?foo&bar'); - $this->drupalGet('/'); - $this->assertNoRaw('javascript://example.com'); - $pattern = '|.setClickUrl\("http(.*):\/\/(.*)javascript%3A\/\/example.com%3Ffoo%26bar"\)|'; - $this->assertPattern($pattern, 'Click URL is filtered for bad protocols and absolute.'); - - variable_set('dfp_click_url', 'http://example.com?foo&bar'); - $this->drupalGet('/'); - $this->assertRaw('.setClickUrl("http://example.com?foo&bar")', 'Valid external Click URL is not mangled.'); - } - - function testDisplayTagWithMapping() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a simple tag with a mapping. Verify javascript on page. - $tag = $this->createTag($edit); - $mapping_sizes = explode(',', $edit['breakpoints[0][ad_sizes]']); - $size_count = count($mapping_sizes); - // Calculate addSize mappings. - $mapping_tag = '.addSize('; - $mapping_tag .= '[' . str_replace('x', ', ', $edit['breakpoints[0][browser_size]']) . '], '; - $mapping_tag .= ($size_count > 1) ? '[' : ''; - for ($i = 0; $i < $size_count; $i++) { - $mapping_sizes[$i] = '[' . str_replace('x', ', ', $mapping_sizes[$i]) . ']'; - $mapping_tag .= ($i + 1 !== $size_count) ? $mapping_sizes[$i] . ', ' : $mapping_sizes[$i]; - } - $mapping_tag .= ($size_count > 1) ? '])' : ')'; - $this->assertRaw('googletag.sizeMapping()', 'The ad slot correctly attaches size mapping.'); - $this->assertRaw('.defineSizeMapping(mapping)', 'The ad slot correctly defines size mapping.'); - $this->assertRaw($mapping_tag, 'The ad slot correctly defines specific size mappings.'); - - // Create a tag with invalid browser size mappings. - $edit['breakpoints[0][browser_size]'] = $this->randomName(8); - $this->editTag($tag->machinename, $edit); - $this->assertText(t('The browser size can only contain numbers and the character x.'), 'An error was correctly thrown when invalid characters.'); - - // Create a tag with invalid ad size mappings. - $edit['breakpoints[0][browser_size]'] = $this->dfpGenerateSize(); - $edit['breakpoints[0][ad_sizes]'] = $this->randomName(8); - $this->editTag($tag->machinename, $edit); - $this->assertText(t('The ad size(s) can only contain numbers, the character x and commas.'), 'An error was correctly thrown when invalid characters.'); - } - - function testSlug() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag without a slug, display it and ensure the default slug is - // displayed. - variable_set('dfp_default_slug', '

Global slug

'); - $edit['settings[slug]'] = ''; - $tag = $this->createTag($edit); - $this->assertRaw('
' . check_plain(variable_get('dfp_default_slug', '')) . '
', 'The default slug is correctly used when no slug exists for an individual tag.'); - - // Change the slug to and ensure that no slug is displayed. - $edit['settings[slug]'] = ''; - $this->editTag($tag->machinename, $edit); - $this->assertNoRaw('
', t('No slug is appearing when "@none" is used.', array('@none' => ''))); - - // Specify a slug and check that it shows instead of the default slug. - $slug = '

Custom slug

'; - $edit['settings[slug]'] = $slug; - $this->editTag($tag->machinename, $edit); - $this->assertRaw('
' . check_plain($slug) . '
', 'The provided slug is correctly displayed with its tag.'); - } - - function testTargeting() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag with a target with only one value. - $tag = $this->createTag($edit); - $this->assertPropertySet('Targeting', $edit['targeting[0][target]'], $edit['targeting[0][value]']); - - // Create a tag with a target with multiple values. - $values = array($this->randomName(8), $this->randomName(8), $this->randomName(8)); - $edit['targeting[0][target]'] = $this->randomName(8); - $edit['targeting[0][value]'] = implode(', ', $values); - $this->editTag($tag->machinename, $edit); - $this->assertPropertySet('Targeting', $edit['targeting[0][target]'], implode('","', $values)); - - // Create a tag with a target but no value. - $edit['targeting[0][target]'] = $this->randomName(8); - $edit['targeting[0][value]'] = ''; - $this->editTag($tag->machinename, $edit); - $this->assertText(t('The value cannot be empty if a target exists.'), 'An error was correctly thrown when a target has no value.'); - - // Create a tag with an empty target, but a value. - $edit['targeting[0][target]'] = ''; - $edit['targeting[0][value]'] = $this->randomName(8); - $this->editTag($tag->machinename, $edit); - $this->assertText(t('The target cannot be empty if a value exists.'), 'An error was correctly thrown when a target is blank, but a value has been entered.'); - - // Create a tag with multiple targets. - $count = 3; - for ($i = 0; $i < $count; $i++) { - $edit['targeting[' . $i . '][target]'] = $this->randomName(8); - $edit['targeting[' . $i . '][value]'] = $this->randomName(8); - $this->drupalPost('admin/structure/dfp_ads/list/' . $tag->machinename . '/edit', $edit, t('Add another target')); - $this->editTag($tag->machinename, $edit); - } - - for ($i = 0; $i < $count; $i++) { - $this->assertPropertySet('Targeting', $edit['targeting[' . $i . '][target]'], $edit['targeting[' . $i . '][value]']); - } - // Make sure that empty values are ignored. - $this->drupalPost('admin/structure/dfp_ads/list/' . $tag->machinename . '/edit', $edit, t('Add another target')); - $this->editTag($tag->machinename, $edit); - $this->assertPropertyNotSet('Targeting', '', ''); - - // Test that target can be removed. - $edit['targeting[0][target]'] = ''; - $edit['targeting[0][value]'] = ''; - $this->editTag($tag->machinename, $edit); - $this->assertPropertyNotSet('Targeting', '', ''); - } - - function testBackfill() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag with backfill settings. - $colors = array('background', 'border', 'link', 'text', 'url'); - $types = array('text', 'image', 'text_image'); - shuffle($types); - - $edit['settings[adsense_ad_types]'] = array_pop($types); - $edit['settings[adsense_channel_ids]'] = $this->randomName(8); - foreach ($colors as $color) { - $edit['settings[adsense_colors][' . $color . ']'] = drupal_strtoupper($this->randomName(8)); - } - $tag = $this->createTag($edit); - $this->assertPropertySet('', 'adsense_ad_types', $edit['settings[adsense_ad_types]']); - $this->assertPropertySet('', 'adsense_channel_ids', $edit['settings[adsense_channel_ids]']); - foreach ($colors as $color) { - $this->assertPropertySet('', 'adsense_' . $color . '_color', $edit['settings[adsense_colors][' . $color . ']']); - } - } - -} - -class dfpAdCategoriesTest extends dfpBaseTest { - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('DFP Ad Categories'), - 'description' => t('Tests the functionaility of DFP ad categories.'), - 'group' => t('DFP'), - ); - } - - function testEnableDisableAdCategories() { - // Check that enabling DFP Ad Categories for the "tags" vocabulary works. - $edit = array( - 'dfp_enable_ad_categories' => 1, - 'dfp_enable_ad_categories_bundles[tags]' => 'tags', - ); - $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); - $this->drupalGet('admin/structure/taxonomy/tags/add'); - $this->assertFieldByName('field_dfp_ad_categories[und]'); - - // Check that disabling DFP Ad Categories vocabulary works even when a - // bundle is selected. - $edit = array( - 'dfp_enable_ad_categories' => 0, - ); - $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); - $this->drupalGet('admin/structure/taxonomy/tags/add'); - $this->assertNoFieldByName('field_dfp_ad_categories[und]'); - - // Check that disabling DFP Ad Categories on a specific vocabulary works. - // For this test to be valid, we first need to reenable DFP Ad Categories. - $edit = array( - 'dfp_enable_ad_categories' => 1, - 'dfp_enable_ad_categories_bundles[tags]' => 'tags', - ); - $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); - $this->drupalGet('admin/structure/taxonomy/tags/add'); - $edit = array( - 'dfp_enable_ad_categories_bundles[tags]' => 0, - ); - $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); - $this->drupalGet('admin/structure/taxonomy/tags/add'); - $this->assertNoFieldByName('field_dfp_ad_categories[und]'); - } - - // Test that DFP Catetories are displayed properly. - function testDisplayAdCategories() { - $dfp_add_categories_vocabulary = taxonomy_vocabulary_machine_name_load('dfp_ad_categories'); - $tags_vocabulary = taxonomy_vocabulary_machine_name_load('tags'); - - // Turn on DFP ad categories for the "tags" vocabulary. - $edit = array( - 'dfp_enable_ad_categories' => 1, - 'dfp_enable_ad_categories_bundles[tags]' => 'tags', - ); - $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); - - // Create a new DFP Ad Category term. - $dfp_category = $this->createTerm($dfp_add_categories_vocabulary); - $control_tag = $this->createTerm($tags_vocabulary); - $test_tag = $this->createTerm($tags_vocabulary); - - // Create a new "Article" node with these two tags. - $edit = array( - 'title' => $this->randomName(8), - 'field_tags[und]' => $control_tag->name . ', ' . $test_tag->name, - ); - $this->drupalPost('node/add/article', $edit, t('Save')); - - // Edit one the new tags and tag it with a DFP Ad Category. - $edit = array( - 'field_dfp_ad_categories[und]' => $dfp_category->tid, - ); - $this->drupalPost('taxonomy/term/' . $test_tag->tid . '/edit', $edit, t('Save')); - - // Create a DFP ad slot that targets the [dfp_tag:ad_categories] token. - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag that uses the slot token in a target. - $edit['slot'] = $this->randomName(8); - $edit['targeting[0][target]'] = 'categories'; - $edit['targeting[0][value]'] = '[dfp_tag:ad_categories]'; - $tag = $this->createTag($edit); - - // Check that when we are on the node page, that the DFP Ad Category is used - // and that the control tag is also displayed. - $this->drupalGet('node/1'); - $this->assertPropertySet('Targeting', 'categories', $control_tag->name); - $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); - - // Check that when we are on the term page for one of DFP Ad Categories that - // it is correctly included. - $this->drupalGet('taxonomy/term/' . $dfp_category->tid); - $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); - - // Check that when we are on a term page for a term with a coresponding - // DFP Ad Categories the DFP Ad Category is included. - $this->drupalGet('taxonomy/term/' . $test_tag->tid); - $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); - } -} - -class dfpTokensTest extends dfpBaseTest { - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('DFP Tokens'), - 'description' => t('Tests for custom tokens created by the DFP module.'), - 'group' => t('DFP'), - ); - } - - function testSlotToken() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag that uses the slot token in a target. - $test_slot = $this->randomName(8); - $edit['slot'] = $test_slot; - $edit['targeting[0][target]'] = 'slot'; - $edit['targeting[0][value]'] = '[dfp_tag:slot]'; - $tag = $this->createTag($edit); - $this->assertPropertySet('Targeting', 'slot', $test_slot); - } - - function testNetworkIDToken() { - $edit = $this->dfpBasicTagEditValues(); - - // Create a tag that uses the networkid token in a target. - $test_network_id = $this->randomName(8); - variable_set('dfp_network_id', $test_network_id); - $edit['targeting[0][target]'] = 'network id'; - $edit['targeting[0][value]'] = '[dfp_tag:network_id]'; - $tag = $this->createTag($edit); - $this->assertPropertySet('Targeting', 'network id', $test_network_id); - } - - function testUrlPartsToken() { - // Create a tag that uses the url parts token in a target. - $tag = $this->createTag(); - $url = 'admin/structure/dfp_ads'; - $url_parts = explode('/', $url); - - $max_parts_to_test = 3; - for ($i = 1; $i <= $max_parts_to_test; $i++) { - $edit['targeting[0][target]'] = 'url parts'; - $edit['targeting[0][value]'] = '[dfp_tag:url_parts:' . $i . ']'; - $this->editTag($tag->machinename, $edit); - - $this->drupalGet($url); - $replacement = implode('/', array_slice($url_parts, 0, $i)); - $this->assertPropertySet('Targeting', 'url parts', $replacement); - } - } - -} - -class dfpGlobalsTest extends dfpBaseTest { - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('Gloabl DFP Tag Settings'), - 'description' => t('Tests for the settings defined in admin/structure/dfp_ads/settings.'), - 'group' => t('DFP'), - ); - } - - function testGlobalSettingsOn() { - $injected_js = $this->randomName(32); - $target = array( - 'target' => $this->randomName(8), - 'value' => $this->randomName(8), - ); - - variable_set('dfp_async_rendering', '1'); - variable_set('dfp_single_request', '1'); - variable_set('dfp_collapse_empty_divs', '1'); - variable_set('dfp_injected_js', $injected_js); - variable_set('dfp_targeting', array($target)); - $this->drupalGet('/'); - $this->assertRaw('googletag.pubads().enableAsyncRendering();', 'Asyncronous rendering is turned on.'); - $this->assertRaw('googletag.pubads().enableSingleRequest();', 'Single request is turned on.'); - $this->assertRaw('googletag.pubads().collapseEmptyDivs();', 'Collapse empty divs is turned on.'); - $this->assertRaw($injected_js, 'Injected javascript correctly appears on the page.'); - $this->assertRaw('googletag.pubads().setTargeting("' . $target['target'] . '", "' . $target['value'] . '");', 'Global targetting values appear correclty in javascript.'); - } - - function testGlobalSettingsOff() { - variable_set('dfp_async_rendering', '0'); - variable_set('dfp_single_request', '0'); - variable_set('dfp_collapse_empty_divs', '0'); - $this->drupalGet('/'); - $this->assertNoRaw('googletag.pubads().enableAsyncRendering();', 'Asyncronous rendering is turned off.'); - $this->assertNoRaw('googletag.pubads().enableSingleRequest();', 'Single request is turned off.'); - $this->assertNoRaw('googletag.pubads().collapseEmptyDivs();', 'Collapse empty divs is turned off.'); - } - -} - -class dfpAdTestTest extends dfpBaseTest { - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('Displaying AdTest DFP Tags'), - 'description' => t('Tests for displaying overridden DFP tags for ad test purposes.'), - 'group' => t('DFP'), - ); - } - - function testTestPage() { - $tag = $this->createTag(); - - $override = $this->randomName(8); - $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adunit_override' => $override))); - $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $override . '"', 'The Ad Unit Name was properly overridden on the Ad Test Page.'); - } - - function testQueryString() { - $tag = $this->createTag(); - - $override = $this->randomName(8); - variable_set('dfp_adtest_adunit', $override); - $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adtest' => 'true'))); - $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $override . '"', 'The Ad Unit Name was properly overridden using the adtest query string.'); - - // Check that nefarious overrride values are caught because security. - $nefarious_override = ""; - $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adunit_override' => $nefarious_override))); - $this->assertNoRaw($nefarious_override, 'Only strings without executable code can be used for the adunit_override query string.'); - } - -} - -class DFPUnitTest extends DrupalUnitTestCase { - protected $profile = 'testing'; - - /** - * Implementation of setUp(). - */ - function setUp() { - // Enable a couple modules. - drupal_load('module', 'dfp'); - parent::setUp(); - } - - /** - * Implements getInfo(). - */ - public static function getInfo() { - return array( - 'name' => t('DFP Unit Tests'), - 'description' => t('Checks the integrity of certain DFP functions.'), - 'group' => t('DFP'), - ); - } - - function testDFPformatSize() { - $sizes = '300x250'; - $expected_result = '[300, 250]'; - - $this->assertTrue(dfp_format_size($sizes) == $expected_result, 'The dfp_format_sizes function correctly handles an single size.'); - $sizes = '300x250,728x90'; - $expected_result = '[[300, 250], [728, 90]]'; - $this->assertTrue(dfp_format_size($sizes) == $expected_result, 'The dfp_format_sizes function correctly handles multiple sizes.'); - } -} diff --git a/tests/dfp_ad_categories.test b/tests/dfp_ad_categories.test new file mode 100644 index 0000000..13f3ce5 --- /dev/null +++ b/tests/dfp_ad_categories.test @@ -0,0 +1,110 @@ + t('DFP Ad Categories'), + 'description' => t('Tests the functionality of DFP ad categories.'), + 'group' => t('DFP'), + ); + } + + function testEnableDisableAdCategories() { + // Check that enabling DFP Ad Categories for the "tags" vocabulary works. + $edit = array( + 'dfp_enable_ad_categories' => 1, + 'dfp_enable_ad_categories_bundles[tags]' => 'tags', + ); + $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); + $this->drupalGet('admin/structure/taxonomy/tags/add'); + $this->assertFieldByName('field_dfp_ad_categories[und]'); + + // Check that disabling DFP Ad Categories vocabulary works even when a + // bundle is selected. + $edit = array( + 'dfp_enable_ad_categories' => 0, + ); + $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); + $this->drupalGet('admin/structure/taxonomy/tags/add'); + $this->assertNoFieldByName('field_dfp_ad_categories[und]'); + + // Check that disabling DFP Ad Categories on a specific vocabulary works. + // For this test to be valid, we first need to re-enable DFP Ad Categories. + $edit = array( + 'dfp_enable_ad_categories' => 1, + 'dfp_enable_ad_categories_bundles[tags]' => 'tags', + ); + $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); + $this->drupalGet('admin/structure/taxonomy/tags/add'); + $edit = array( + 'dfp_enable_ad_categories_bundles[tags]' => 0, + ); + $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); + $this->drupalGet('admin/structure/taxonomy/tags/add'); + $this->assertNoFieldByName('field_dfp_ad_categories[und]'); + } + + // Test that DFP Categories are displayed properly. + function testDisplayAdCategories() { + $dfp_add_categories_vocabulary = taxonomy_vocabulary_machine_name_load('dfp_ad_categories'); + $tags_vocabulary = taxonomy_vocabulary_machine_name_load('tags'); + + // Turn on DFP ad categories for the "tags" vocabulary. + $edit = array( + 'dfp_enable_ad_categories' => 1, + 'dfp_enable_ad_categories_bundles[tags]' => 'tags', + ); + $this->drupalPost('admin/structure/dfp_ads/settings', $edit, t('Save configuration')); + + // Create a new DFP Ad Category term. + $dfp_category = $this->createTerm($dfp_add_categories_vocabulary); + $control_tag = $this->createTerm($tags_vocabulary); + $test_tag = $this->createTerm($tags_vocabulary); + + // Create a new "Article" node with these two tags. + $edit = array( + 'title' => $this->randomName(8), + 'field_tags[und]' => $control_tag->name . ', ' . $test_tag->name, + ); + $this->drupalPost('node/add/article', $edit, t('Save')); + + // Edit one the new tags and tag it with a DFP Ad Category. + $edit = array( + 'field_dfp_ad_categories[und]' => $dfp_category->tid, + ); + $this->drupalPost('taxonomy/term/' . $test_tag->tid . '/edit', $edit, t('Save')); + + // Create a DFP ad slot that targets the [dfp_tag:ad_categories] token. + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag that uses the slot token in a target. + $edit['slot'] = $this->randomName(8); + $edit['targeting[0][target]'] = 'categories'; + $edit['targeting[0][value]'] = '[dfp_tag:ad_categories]'; + $tag = $this->createTag($edit); + + // Check that when we are on the node page, that the DFP Ad Category is used + // and that the control tag is also displayed. + $this->drupalGet('node/1'); + $this->assertPropertySet('Targeting', 'categories', $control_tag->name); + $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); + + // Check that when we are on the term page for one of DFP Ad Categories that + // it is correctly included. + $this->drupalGet('taxonomy/term/' . $dfp_category->tid); + $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); + + // Check that when we are on a term page for a term with a corresponding + // DFP Ad Categories the DFP Ad Category is included. + $this->drupalGet('taxonomy/term/' . $test_tag->tid); + $this->assertPropertySet('Targeting', 'categories', $dfp_category->name); + } +} diff --git a/tests/dfp_ads.test b/tests/dfp_ads.test new file mode 100644 index 0000000..897b976 --- /dev/null +++ b/tests/dfp_ads.test @@ -0,0 +1,42 @@ + t('Displaying AdTest DFP Tags'), + 'description' => t('Tests for displaying overridden DFP tags for ad test purposes.'), + 'group' => t('DFP'), + ); + } + + function testTestPage() { + $tag = $this->createTag(); + + $override = $this->randomName(8); + $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adunit_override' => $override))); + $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $override . '"', 'The Ad Unit Name was properly overridden on the Ad Test Page.'); + } + + function testQueryString() { + $tag = $this->createTag(); + + $override = $this->randomName(8); + variable_set('dfp_adtest_adunit', $override); + $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adtest' => 'true'))); + $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $override . '"', 'The Ad Unit Name was properly overridden using the adtest query string.'); + + // Check that nefarious override values are caught because security. + $nefarious_override = ""; + $this->drupalGet('admin/structure/dfp_ads/test_page', array('query' => array('adunit_override' => $nefarious_override))); + $this->assertNoRaw($nefarious_override, 'Only strings without executable code can be used for the adunit_override query string.'); + } + +} diff --git a/tests/dfp_base.test b/tests/dfp_base.test new file mode 100644 index 0000000..94ba6e3 --- /dev/null +++ b/tests/dfp_base.test @@ -0,0 +1,130 @@ +admin_user = $this->drupalCreateUser(array('administer DFP', 'administer taxonomy', 'access administration pages', 'administer blocks', 'bypass node access', 'administer nodes', 'edit terms in 1')); + $this->drupalLogin($this->admin_user); + + // Add the some global settings needed for dfp ads to work. + variable_set('dfp_network_id', '12345'); + variable_set('dfp_default_slug', $this->randomName(8)); + } + + /** + * Create a simple $edit array to be used on the DFP tag form to create a new + * DFP tag object. + */ + function dfpBasicTagEditValues() { + $machinename = drupal_strtolower($this->randomName(8)); + $basic_tag = array( + 'machinename' => $machinename, + 'slot' => $machinename, + 'size' => implode(',', $this->dfpGenerateSize(2)), + 'adunit' => $this->randomName(8), + 'block' => 1, + 'settings[slug]' => $this->randomName(32), + 'settings[adsense_ad_types]' => '', + 'settings[adsense_channel_ids]' => '', + 'settings[adsense_colors][background]' => '', + 'settings[adsense_colors][border]' => '', + 'settings[adsense_colors][link]' => '', + 'settings[adsense_colors][text]' => '', + 'settings[adsense_colors][url]' => '', + 'targeting[0][target]' => $this->randomName(8), + 'targeting[0][value]' => $this->randomName(8), + 'breakpoints[0][browser_size]' => $this->dfpGenerateSize(), + 'breakpoints[0][ad_sizes]' => implode(',', $this->dfpGenerateSize(2)), + ); + + return $basic_tag; + } + + /** + * Generate a random size (or array or sizes) to use when testing tags + * formatted as ###x###. + */ + function dfpGenerateSize($count = 1) { + $sizes = array('300x250', '300x600', '728x90', '728x10', '160x600', '120x80', '300x100', '50x50', '160x300'); + shuffle($sizes); + + return $count == 1 ? array_pop($sizes) : array_slice($sizes, 0, min($count, count($sizes))); + } + + /** + * Creates a basic dfp ad tag. + */ + function createTag($edit = array()) { + // Create a new tag. + $edit += $this->dfpBasicTagEditValues(); + $this->drupalPost('admin/structure/dfp_ads/add', $edit, t('Save')); + + // Load the tag object. + $tag = dfp_tag_load($edit['machinename']); + $this->assertTrue(is_object($tag) && $tag->machinename = $edit['machinename'], 'The new tag was saved correctly.'); + + // Display the new tag. + $edit = array(); + $delta = 'dfp_' . (drupal_strlen($tag->machinename) >= 32 ? md5($tag->machinename) : $tag->machinename); + $edit['blocks[' . $delta . '][region]'] = 'sidebar_first'; + $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); + + return $tag; + } + + /** + * Edit a given tag specified by $machinename with the given values. + */ + function editTag($machinename, &$edit) { + // Make sure there is no machinename set when we are editing. + if (isset($edit['machinename'])) { + unset($edit['machinename']); + } + $this->drupalPost('admin/structure/dfp_ads/list/' . $machinename . '/edit', $edit, t('Save')); + $tag = dfp_tag_load($machinename); + return $tag; + } + + /** + * Create a taxonomy term. + */ + function createTerm($vocabulary) { + $term = new stdClass(); + $term->name = $this->randomName(); + $term->description = $this->randomName(); + // Use the first available text format. + $term->format = db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(); + $term->vid = $vocabulary->vid; + taxonomy_term_save($term); + return $term; + } + + /** + * Assert that a property is properly being set. + */ + function assertPropertySet($property, $key, $val) { + $pattern = '|' . '.set' . $property . '\("' . $key . '",{1}\s(.)*' . addslashes($val) . '|'; + $this->assertPattern($pattern, 'A ' . $property . ' property was set for ' . $key . ' = ' . $val); + } + + /** + * Assert that a property is not being set. + */ + function assertPropertyNotSet($property, $key, $val) { + $pattern = '|' . '.set' . $property . '\("' . $key . '",{1}\s(.)*' . addslashes($val) . '|'; + $this->assertNoPattern($pattern, 'A ' . $property . ' property was not set for ' . $key . ' = ' . $val); + } + +} diff --git a/tests/dfp_display_tag.test b/tests/dfp_display_tag.test new file mode 100644 index 0000000..bf5397c --- /dev/null +++ b/tests/dfp_display_tag.test @@ -0,0 +1,167 @@ + t('Displaying DFP Tags'), + 'description' => t('Tests for displaying DFP tags.'), + 'group' => t('DFP'), + ); + } + + function testDisplayTag() { + // Create a simple tag as a block. + $tag = $this->createTag(); + $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $tag->adunit . '", ' . dfp_format_size($tag->size) . ', "' . $tag->placeholder_id . '")', 'The ad slot has been correctly defined in javascript.'); + + // Create a tag with a machine name longer than 32 characters. + $edit = array('machinename' => drupal_strtolower($this->randomName(64))); + $tag = $this->createTag($edit); + $this->assertRaw('googletag.defineSlot("' . variable_get('dfp_network_id', '') . '/' . $tag->adunit . '", ' . dfp_format_size($tag->size) . ', "' . $tag->placeholder_id . '")', 'The ad slot with a very long machine name has been correctly defined in javascript.'); + + // Ensure the DPF click url is safe. + variable_set('dfp_click_url', 'javascript://example.com?foo&bar'); + $this->drupalGet('/'); + $this->assertNoRaw('javascript://example.com'); + $pattern = '|.setClickUrl\("http(.*):\/\/(.*)javascript%3A\/\/example.com%3Ffoo%26bar"\)|'; + $this->assertPattern($pattern, 'Click URL is filtered for bad protocols and absolute.'); + + variable_set('dfp_click_url', 'http://example.com?foo&bar'); + $this->drupalGet('/'); + $this->assertRaw('.setClickUrl("http://example.com?foo&bar")', 'Valid external Click URL is not mangled.'); + } + + function testDisplayTagWithMapping() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a simple tag with a mapping. Verify javascript on page. + $tag = $this->createTag($edit); + $mapping_sizes = explode(',', $edit['breakpoints[0][ad_sizes]']); + $size_count = count($mapping_sizes); + // Calculate addSize mappings. + $mapping_tag = '.addSize('; + $mapping_tag .= '[' . str_replace('x', ', ', $edit['breakpoints[0][browser_size]']) . '], '; + $mapping_tag .= ($size_count > 1) ? '[' : ''; + for ($i = 0; $i < $size_count; $i++) { + $mapping_sizes[$i] = '[' . str_replace('x', ', ', $mapping_sizes[$i]) . ']'; + $mapping_tag .= ($i + 1 !== $size_count) ? $mapping_sizes[$i] . ', ' : $mapping_sizes[$i]; + } + $mapping_tag .= ($size_count > 1) ? '])' : ')'; + $this->assertRaw('googletag.sizeMapping()', 'The ad slot correctly attaches size mapping.'); + $this->assertRaw('.defineSizeMapping(mapping)', 'The ad slot correctly defines size mapping.'); + $this->assertRaw($mapping_tag, 'The ad slot correctly defines specific size mappings.'); + + // Create a tag with invalid browser size mappings. + $edit['breakpoints[0][browser_size]'] = $this->randomName(8); + $this->editTag($tag->machinename, $edit); + $this->assertText(t('The browser size can only contain numbers and the character x.'), 'An error was correctly thrown when invalid characters.'); + + // Create a tag with invalid ad size mappings. + $edit['breakpoints[0][browser_size]'] = $this->dfpGenerateSize(); + $edit['breakpoints[0][ad_sizes]'] = $this->randomName(8); + $this->editTag($tag->machinename, $edit); + $this->assertText(t('The ad size(s) can only contain numbers, the character x and commas.'), 'An error was correctly thrown when invalid characters.'); + } + + function testSlug() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag without a slug, display it and ensure the default slug is + // displayed. + variable_set('dfp_default_slug', '

Global slug

'); + $edit['settings[slug]'] = ''; + $tag = $this->createTag($edit); + $this->assertRaw('
' . check_plain(variable_get('dfp_default_slug', '')) . '
', 'The default slug is correctly used when no slug exists for an individual tag.'); + + // Change the slug to and ensure that no slug is displayed. + $edit['settings[slug]'] = ''; + $this->editTag($tag->machinename, $edit); + $this->assertNoRaw('
', t('No slug is appearing when "@none" is used.', array('@none' => ''))); + + // Specify a slug and check that it shows instead of the default slug. + $slug = '

Custom slug

'; + $edit['settings[slug]'] = $slug; + $this->editTag($tag->machinename, $edit); + $this->assertRaw('
' . check_plain($slug) . '
', 'The provided slug is correctly displayed with its tag.'); + } + + function testTargeting() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag with a target with only one value. + $tag = $this->createTag($edit); + $this->assertPropertySet('Targeting', $edit['targeting[0][target]'], $edit['targeting[0][value]']); + + // Create a tag with a target with multiple values. + $values = array($this->randomName(8), $this->randomName(8), $this->randomName(8)); + $edit['targeting[0][target]'] = $this->randomName(8); + $edit['targeting[0][value]'] = implode(', ', $values); + $this->editTag($tag->machinename, $edit); + $this->assertPropertySet('Targeting', $edit['targeting[0][target]'], implode('","', $values)); + + // Create a tag with a target but no value. + $edit['targeting[0][target]'] = $this->randomName(8); + $edit['targeting[0][value]'] = ''; + $this->editTag($tag->machinename, $edit); + $this->assertText(t('The value cannot be empty if a target exists.'), 'An error was correctly thrown when a target has no value.'); + + // Create a tag with an empty target, but a value. + $edit['targeting[0][target]'] = ''; + $edit['targeting[0][value]'] = $this->randomName(8); + $this->editTag($tag->machinename, $edit); + $this->assertText(t('The target cannot be empty if a value exists.'), 'An error was correctly thrown when a target is blank, but a value has been entered.'); + + // Create a tag with multiple targets. + $count = 3; + for ($i = 0; $i < $count; $i++) { + $edit['targeting[' . $i . '][target]'] = $this->randomName(8); + $edit['targeting[' . $i . '][value]'] = $this->randomName(8); + $this->drupalPost('admin/structure/dfp_ads/list/' . $tag->machinename . '/edit', $edit, t('Add another target')); + $this->editTag($tag->machinename, $edit); + } + + for ($i = 0; $i < $count; $i++) { + $this->assertPropertySet('Targeting', $edit['targeting[' . $i . '][target]'], $edit['targeting[' . $i . '][value]']); + } + // Make sure that empty values are ignored. + $this->drupalPost('admin/structure/dfp_ads/list/' . $tag->machinename . '/edit', $edit, t('Add another target')); + $this->editTag($tag->machinename, $edit); + $this->assertPropertyNotSet('Targeting', '', ''); + + // Test that target can be removed. + $edit['targeting[0][target]'] = ''; + $edit['targeting[0][value]'] = ''; + $this->editTag($tag->machinename, $edit); + $this->assertPropertyNotSet('Targeting', '', ''); + } + + function testBackfill() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag with backfill settings. + $colors = array('background', 'border', 'link', 'text', 'url'); + $types = array('text', 'image', 'text_image'); + shuffle($types); + + $edit['settings[adsense_ad_types]'] = array_pop($types); + $edit['settings[adsense_channel_ids]'] = $this->randomName(8); + foreach ($colors as $color) { + $edit['settings[adsense_colors][' . $color . ']'] = drupal_strtoupper($this->randomName(8)); + } + $tag = $this->createTag($edit); + $this->assertPropertySet('', 'adsense_ad_types', $edit['settings[adsense_ad_types]']); + $this->assertPropertySet('', 'adsense_channel_ids', $edit['settings[adsense_channel_ids]']); + foreach ($colors as $color) { + $this->assertPropertySet('', 'adsense_' . $color . '_color', $edit['settings[adsense_colors][' . $color . ']']); + } + } + +} diff --git a/tests/dfp_globals.test b/tests/dfp_globals.test new file mode 100644 index 0000000..d020888 --- /dev/null +++ b/tests/dfp_globals.test @@ -0,0 +1,50 @@ + t('Global DFP Tag Settings'), + 'description' => t('Tests for the settings defined in admin/structure/dfp_ads/settings.'), + 'group' => t('DFP'), + ); + } + + function testGlobalSettingsOn() { + $injected_js = $this->randomName(32); + $target = array( + 'target' => $this->randomName(8), + 'value' => $this->randomName(8), + ); + + variable_set('dfp_async_rendering', '1'); + variable_set('dfp_single_request', '1'); + variable_set('dfp_collapse_empty_divs', '1'); + variable_set('dfp_injected_js', $injected_js); + variable_set('dfp_targeting', array($target)); + $this->drupalGet('/'); + $this->assertRaw('googletag.pubads().enableAsyncRendering();', 'Asyncronous rendering is turned on.'); + $this->assertRaw('googletag.pubads().enableSingleRequest();', 'Single request is turned on.'); + $this->assertRaw('googletag.pubads().collapseEmptyDivs();', 'Collapse empty divs is turned on.'); + $this->assertRaw($injected_js, 'Injected javascript correctly appears on the page.'); + $this->assertRaw('googletag.pubads().setTargeting("' . $target['target'] . '", "' . $target['value'] . '");', 'Global targeting values appear correctly in javascript.'); + } + + function testGlobalSettingsOff() { + variable_set('dfp_async_rendering', '0'); + variable_set('dfp_single_request', '0'); + variable_set('dfp_collapse_empty_divs', '0'); + $this->drupalGet('/'); + $this->assertNoRaw('googletag.pubads().enableAsyncRendering();', 'Asyncronous rendering is turned off.'); + $this->assertNoRaw('googletag.pubads().enableSingleRequest();', 'Single request is turned off.'); + $this->assertNoRaw('googletag.pubads().collapseEmptyDivs();', 'Collapse empty divs is turned off.'); + } + +} diff --git a/tests/dfp_tokens.test b/tests/dfp_tokens.test new file mode 100644 index 0000000..9afb486 --- /dev/null +++ b/tests/dfp_tokens.test @@ -0,0 +1,62 @@ + t('DFP Tokens'), + 'description' => t('Tests for custom tokens created by the DFP module.'), + 'group' => t('DFP'), + ); + } + + function testSlotToken() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag that uses the slot token in a target. + $test_slot = $this->randomName(8); + $edit['slot'] = $test_slot; + $edit['targeting[0][target]'] = 'slot'; + $edit['targeting[0][value]'] = '[dfp_tag:slot]'; + $tag = $this->createTag($edit); + $this->assertPropertySet('Targeting', 'slot', $test_slot); + } + + function testNetworkIDToken() { + $edit = $this->dfpBasicTagEditValues(); + + // Create a tag that uses the networkid token in a target. + $test_network_id = $this->randomName(8); + variable_set('dfp_network_id', $test_network_id); + $edit['targeting[0][target]'] = 'network id'; + $edit['targeting[0][value]'] = '[dfp_tag:network_id]'; + $tag = $this->createTag($edit); + $this->assertPropertySet('Targeting', 'network id', $test_network_id); + } + + function testUrlPartsToken() { + // Create a tag that uses the url parts token in a target. + $tag = $this->createTag(); + $url = 'admin/structure/dfp_ads'; + $url_parts = explode('/', $url); + + $max_parts_to_test = 3; + for ($i = 1; $i <= $max_parts_to_test; $i++) { + $edit['targeting[0][target]'] = 'url parts'; + $edit['targeting[0][value]'] = '[dfp_tag:url_parts:' . $i . ']'; + $this->editTag($tag->machinename, $edit); + + $this->drupalGet($url); + $replacement = implode('/', array_slice($url_parts, 0, $i)); + $this->assertPropertySet('Targeting', 'url parts', $replacement); + } + } + +} diff --git a/tests/dfp_unit.test b/tests/dfp_unit.test new file mode 100644 index 0000000..688e8b7 --- /dev/null +++ b/tests/dfp_unit.test @@ -0,0 +1,40 @@ + t('DFP Unit Tests'), + 'description' => t('Checks the integrity of certain DFP functions.'), + 'group' => t('DFP'), + ); + } + + function testDFPformatSize() { + $sizes = '300x250'; + $expected_result = '[300, 250]'; + + $this->assertTrue(dfp_format_size($sizes) == $expected_result, 'The dfp_format_sizes function correctly handles an single size.'); + $sizes = '300x250,728x90'; + $expected_result = '[[300, 250], [728, 90]]'; + $this->assertTrue(dfp_format_size($sizes) == $expected_result, 'The dfp_format_sizes function correctly handles multiple sizes.'); + } +}