/**
  * 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');
 }
Example #8
0
 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());
 }