/** * Pushes a class and template manifest instance that include tests onto the * top of the loader stacks. */ public static function use_test_manifest() { $classManifest = new SS_ClassManifest(BASE_PATH, true, isset($_GET['flush'])); SS_ClassLoader::instance()->pushManifest($classManifest, false); SapphireTest::set_test_class_manifest($classManifest); SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(BASE_PATH, project(), true, isset($_GET['flush']))); Config::inst()->pushConfigStaticManifest(new SS_ConfigStaticManifest(BASE_PATH, true, isset($_GET['flush']))); // Invalidate classname spec since the test manifest will now pull out new subclasses for each internal class // (e.g. Member will now have various subclasses of DataObjects that implement TestOnly) DataObject::reset(); }
/** * @param $class * @param $extension * @param $args * @return array|mixed */ public static function get_extra_config($class, $extension, $args) { if (self::$disable_continental_fields) { return array(); } foreach (ClassInfo::subclassesFor($class) as $subClass) { $config = self::make_continental_fields($subClass); foreach ($config as $name => $value) { Config::inst()->update($subClass, $name, $value); } } DataObject::reset(); return self::make_continental_fields($class); }
public function testUpdateFieldLabels() { // Add custom translation for testing i18n::get_translator('core')->getAdapter()->addTranslation(array('SiteTree.METATITLE' => 'TRANS-EN Meta Title'), 'en'); $siteTree = new SiteTree(); $labels = $siteTree->fieldLabels(); $this->assertArrayHasKey('MetaTitle', $labels); $this->assertEquals('TRANS-EN Meta Title', $labels['MetaTitle']); // Set different locale, clear field label cache i18n::set_locale('de_DE'); DataObject::reset(); // Add custom translation for testing i18n::get_translator('core')->getAdapter()->addTranslation(array('SiteTree.METATITLE' => 'TRANS-DE Meta Title'), 'de_DE'); $labels = $siteTree->fieldLabels(); $this->assertEquals('TRANS-DE Meta Title', $labels['MetaTitle']); }
function setUp() { // Mark test as being run $this->originalIsRunningTest = self::$is_running_test; self::$is_running_test = true; // i18n needs to be set to the defaults or tests fail i18n::set_locale(i18n::default_locale()); i18n::set_date_format(null); i18n::set_time_format(null); // Remove password validation $this->originalMemberPasswordValidator = Member::password_validator(); $this->originalRequirements = Requirements::backend(); Member::set_password_validator(null); Cookie::set_report_errors(false); RootURLController::reset(); Translatable::reset(); Versioned::reset(); DataObject::reset(); SiteTree::reset(); Hierarchy::reset(); if (Controller::has_curr()) { Controller::curr()->setSession(new Session(array())); } $this->originalTheme = SSViewer::current_theme(); // Save nested_urls state, so we can restore it later $this->originalNestedURLsState = SiteTree::nested_urls(); $className = get_class($this); $fixtureFile = eval("return {$className}::\$fixture_file;"); $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; // Set up fixture if ($fixtureFile || $this->usesDatabase || !self::using_temp_db()) { if (substr(DB::getConn()->currentDatabase(), 0, strlen($prefix) + 5) != strtolower(sprintf('%stmpdb', $prefix))) { //echo "Re-creating temp database... "; self::create_temp_db(); //echo "done.\n"; } singleton('DataObject')->flushCache(); self::empty_temp_db(); foreach ($this->requireDefaultRecordsFrom as $className) { $instance = singleton($className); if (method_exists($instance, 'requireDefaultRecords')) { $instance->requireDefaultRecords(); } if (method_exists($instance, 'augmentDefaultRecords')) { $instance->augmentDefaultRecords(); } } if ($fixtureFile) { $fixtureFiles = is_array($fixtureFile) ? $fixtureFile : array($fixtureFile); $i = 0; foreach ($fixtureFiles as $fixtureFilePath) { $fixture = new YamlFixture($fixtureFilePath); $fixture->saveIntoDatabase(); $this->fixtures[] = $fixture; // backwards compatibility: Load first fixture into $this->fixture if ($i == 0) { $this->fixture = $fixture; } $i++; } } $this->logInWithPermission("ADMIN"); } // Set up email $this->originalMailer = Email::mailer(); $this->mailer = new TestMailer(); Email::set_mailer($this->mailer); Email::send_all_emails_to(null); // Preserve memory settings $this->originalMemoryLimit = ini_get('memory_limit'); }
public static function get_extra_config($class, $extension, $args) { if (self::$disable_fluent_fields) { return array(); } // Merge all config values for subclasses foreach (ClassInfo::subclassesFor($class) as $subClass) { $config = self::generate_extra_config($subClass); foreach ($config as $name => $value) { Config::inst()->update($subClass, $name, $value); } } // Force all subclass DB caches to invalidate themselves since their db attribute is now expired DataObject::reset(); return self::generate_extra_config($class); }
/** * Reset the testing database's schema. * @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included */ public function resetDBSchema($includeExtraDataObjects = false) { if (self::using_temp_db()) { DataObject::reset(); // clear singletons, they're caching old extension info which is used in DatabaseAdmin->doBuild() Injector::inst()->unregisterAllObjects(); $dataClasses = ClassInfo::subclassesFor('DataObject'); array_shift($dataClasses); DB::quiet(); $schema = DB::get_schema(); $extraDataObjects = $includeExtraDataObjects ? $this->extraDataObjects : null; $schema->schemaUpdate(function () use($dataClasses, $extraDataObjects) { foreach ($dataClasses as $dataClass) { // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness if (class_exists($dataClass)) { $SNG = singleton($dataClass); if (!$SNG instanceof TestOnly) { $SNG->requireTable(); } } } // If we have additional dataobjects which need schema, do so here: if ($extraDataObjects) { foreach ($extraDataObjects as $dataClass) { $SNG = singleton($dataClass); if (singleton($dataClass) instanceof DataObject) { $SNG->requireTable(); } } } }); ClassInfo::reset_db_cache(); singleton('DataObject')->flushCache(); } }
function testPromoOnVariation() { /** @var Product $p4 */ $p4 = $this->objFromFixture('Product', 'p4'); /** @var ProductVaration $p4v1 */ $p4v1 = $this->objFromFixture('ProductVariation', 'p4v1'); /** @var ProductVaration $p4v3 */ $p4v3 = $this->objFromFixture('ProductVariation', 'p4v3'); // this one doesn't have it's own price // When there is no promo price, should return the base price $this->assertEquals(20, $p4v1->sellingPrice(), 'When there is no promo, should return the base price'); $this->assertEquals(25, $p4v3->sellingPrice(), 'When there is no promo, should return the base price even if no price on variation'); // When we add a promo price to the PRODUCT, it should apply to the variations as well $p4->PromoActive = true; $p4->PromoType = 'Amount'; $p4->PromoAmount = 10; $p4->write(); DataObject::flush_and_destroy_cache(); $this->assertEquals(15, $p4->sellingPrice(), 'When we add a promo to the product, should return it'); $this->assertEquals(10, $p4v1->sellingPrice(), 'When we add a promo to the product, should return it for variations'); $this->assertEquals(15, $p4v3->sellingPrice(), 'When we add a promo to the product, should return it for variations without a price'); // When we add a promo to the variation, and compound_discounts is disabled, it should OVERRIDE any promos on the product $p4v1->PromoActive = true; $p4v1->PromoType = 'Amount'; $p4v1->PromoAmount = 1; $p4v3->PromoActive = true; $p4v3->PromoType = 'Amount'; $p4v3->PromoAmount = 1; Config::inst()->update('HasPromotionalPricing', 'compound_discounts', false); $this->assertEquals(19, $p4v1->sellingPrice(), 'When we add a promo to the variation, and compound_discounts is disabled, it should OVERRIDE any promos on the product'); $this->assertEquals(24, $p4v3->sellingPrice(), 'When we add a promo to the variation, and compound_discounts is disabled, it should OVERRIDE any promos on the product even if the variation has no price'); // When we add a promo to the variation, and compound_discounts is enabled, it should APPLY BOTH promos Config::inst()->update('HasPromotionalPricing', 'compound_discounts', true); $this->assertEquals(9, $p4v1->sellingPrice(), 'When we add a promo to the variation, and compound_discounts is disabled, it should APPLY BOTH promos'); $this->assertEquals(14, $p4v3->sellingPrice(), 'When we add a promo to the variation, and compound_discounts is disabled, it should APPLY BOTH promos even if the variation has no price'); // When a promo is only on the variation it should apply properly $p4->PromoActive = false; $p4->write(); DataObject::reset(); $p4v1->flushCache(); $p4v3->flushCache(); $this->assertEquals(19, $p4v1->sellingPrice(), 'When we add a promo to the variation only, it should apply'); $this->assertEquals(24, $p4v3->sellingPrice(), 'When we add a promo to the variation only, it should apply even if the variation has no price'); }
public function setUp() { // We cannot run the tests on this abstract class. if (get_class($this) == "SapphireTest") { $this->skipTest = true; } if ($this->skipTest) { $this->markTestSkipped(sprintf('Skipping %s ', get_class($this))); return; } // Mark test as being run $this->originalIsRunningTest = self::$is_running_test; self::$is_running_test = true; // i18n needs to be set to the defaults or tests fail i18n::set_locale(i18n::default_locale()); i18n::set_date_format(null); i18n::set_time_format(null); // Set default timezone consistently to avoid NZ-specific dependencies date_default_timezone_set('UTC'); // Remove password validation $this->originalMemberPasswordValidator = Member::password_validator(); $this->originalRequirements = Requirements::backend(); Member::set_password_validator(null); Cookie::set_report_errors(false); if (class_exists('RootURLController')) { RootURLController::reset(); } if (class_exists('Translatable')) { Translatable::reset(); } Versioned::reset(); DataObject::reset(); if (class_exists('SiteTree')) { SiteTree::reset(); } Hierarchy::reset(); if (Controller::has_curr()) { Controller::curr()->setSession(new Session(array())); } Security::$database_is_ready = null; $this->originalTheme = SSViewer::current_theme(); if (class_exists('SiteTree')) { // Save nested_urls state, so we can restore it later $this->originalNestedURLsState = SiteTree::nested_urls(); } $className = get_class($this); $fixtureFile = eval("return {$className}::\$fixture_file;"); $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; // Todo: this could be a special test model $this->model = DataModel::inst(); // Set up fixture if ($fixtureFile || $this->usesDatabase || !self::using_temp_db()) { if (substr(DB::getConn()->currentDatabase(), 0, strlen($prefix) + 5) != strtolower(sprintf('%stmpdb', $prefix))) { //echo "Re-creating temp database... "; self::create_temp_db(); //echo "done.\n"; } singleton('DataObject')->flushCache(); self::empty_temp_db(); foreach ($this->requireDefaultRecordsFrom as $className) { $instance = singleton($className); if (method_exists($instance, 'requireDefaultRecords')) { $instance->requireDefaultRecords(); } if (method_exists($instance, 'augmentDefaultRecords')) { $instance->augmentDefaultRecords(); } } if ($fixtureFile) { $pathForClass = $this->getCurrentAbsolutePath(); $fixtureFiles = is_array($fixtureFile) ? $fixtureFile : array($fixtureFile); $i = 0; foreach ($fixtureFiles as $fixtureFilePath) { // Support fixture paths relative to the test class, rather than relative to webroot // String checking is faster than file_exists() calls. $isRelativeToFile = strpos('/', $fixtureFilePath) === false || preg_match('/^\\.\\./', $fixtureFilePath); if ($isRelativeToFile) { $resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath); if ($resolvedPath) { $fixtureFilePath = $resolvedPath; } } $fixture = new YamlFixture($fixtureFilePath); $fixture->saveIntoDatabase($this->model); $this->fixtures[] = $fixture; // backwards compatibility: Load first fixture into $this->fixture if ($i == 0) { $this->fixture = $fixture; } $i++; } } $this->logInWithPermission("ADMIN"); } // Set up email $this->originalMailer = Email::mailer(); $this->mailer = new TestMailer(); Email::set_mailer($this->mailer); Email::send_all_emails_to(null); // Preserve memory settings $this->originalMemoryLimit = ini_get('memory_limit'); // turn off template debugging SSViewer::set_source_file_comments(false); // Clear requirements Requirements::clear(); }
public function testOrderAddress() { $order = $this->objFromFixture('Order', 'paid'); // assert that order doesn't contain user information $this->assertNull($order->FirstName); $this->assertNull($order->Surname); $this->assertNull($order->Email); // The shipping address should use the members default shipping address $this->assertEquals('Joe Bloggs, 12 Foo Street, Bar, Farmville, New Sandwich, US', $order->getShippingAddress()->toString()); $address = $this->objFromFixture('Address', 'pukekohe'); $order->ShippingAddressID = $address->ID; $order->write(); // Address doesn't have firstname and surname $this->assertNull(Address::get()->byID($order->ShippingAddressID)->FirstName); $this->assertNull(Address::get()->byID($order->ShippingAddressID)->Surname); // Shipping address should contain the name from the member object and new address information $this->assertEquals('Joe Bloggs, 1 Queen Street, Pukekohe, Auckland, 2120', $order->getShippingAddress()->toString()); // changing fields on the Order will have precendence! $order->FirstName = 'Tester'; $order->Surname = 'Mc. Testerson'; $order->write(); // Reset caches, otherwise the previously set name will persist (eg. Joe Bloggs) DataObject::reset(); $this->assertEquals('Tester Mc. Testerson, 1 Queen Street, Pukekohe, Auckland, 2120', $order->getShippingAddress()->toString()); }