dfp.test in Doubleclick for Publishers (DFP) 7.2
Test file for DFP module.
File
tests/dfp.testView source
<?php
/**
* @file
* Test file for DFP module.
*/
class dfpBaseTest extends DrupalWebTestCase {
/**
* Implementation of setUp().
*/
function setUp() {
// Enable a couple modules.
parent::setUp('ctools', 'dfp', 'taxonomy', 'entity_modified');
menu_rebuild();
// Create an admin user with all the permissions needed to run tests.
$this->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', '<p>Global slug</p>');
$edit['settings[slug]'] = '';
$tag = $this
->createTag($edit);
$this
->assertRaw('<div class="slug">' . check_plain(variable_get('dfp_default_slug', '')) . '</div>', 'The default slug is correctly used when no slug exists for an individual tag.');
// Change the slug to <none> and ensure that no slug is displayed.
$edit['settings[slug]'] = '<none>';
$this
->editTag($tag->machinename, $edit);
$this
->assertNoRaw('<div class="slug">', t('No slug is appearing when "@none" is used.', array(
'@none' => '<none>',
)));
// Specify a slug and check that it shows instead of the default slug.
$slug = '<p>Custom slug</p>';
$edit['settings[slug]'] = $slug;
$this
->editTag($tag->machinename, $edit);
$this
->assertRaw('<div class="slug">' . check_plain($slug) . '</div>', '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 = "<script>alert('not safe');</script>";
$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.');
}
}
Classes
Name | Description |
---|---|
dfpAdCategoriesTest | |
dfpAdTestTest | |
dfpBaseTest | @file Test file for DFP module. |
dfpDisplayTagTest | |
dfpGlobalsTest | |
dfpTokensTest | |
DFPUnitTest |