qcubed/framework

View on GitHub
includes/tests/qcubed-unit/BasicOrmTest.php

Summary

Maintainability
C
1 day
Test Coverage
<?php

/**
 * 
 * @package Tests
 */
if(!class_exists('Person')){
    require_once __INCLUDES__ .'/model/Person.class.php';
    
}
if(!class_exists('Project')){
    require_once __INCLUDES__ .'/model/Project.class.php';
}
if(!class_exists('Login')){
    require_once __INCLUDES__ .'/model/Login.class.php';
}
if(!class_exists('Milestone')){
    require_once __INCLUDES__ .'/model/Milestone.class.php';
}
if(!class_exists('Address')){
    require_once __INCLUDES__ .'/model/Address.class.php';
}
if(!class_exists('TwoKey')){
    require_once __INCLUDES__ .'/model/TwoKey.class.php';
}

class BasicOrmTests extends QUnitTestCaseBase {    
    public function testSaveAndDelete() {
        $objPerson1 = new Person();
        $objPerson1->FirstName = "Test1";
        $objPerson1->LastName = "Last1";
        $objPerson1->Save();
        
        $items = Person::QueryArray(
            QQ::AndCondition(
                QQ::Equal(QQN::Person()->FirstName, "Test1"),
                QQ::Equal(QQN::Person()->LastName, "Last1")
            )
        );
                
        $this->assertEquals(1, sizeof($items), "Saved the Person object");
            
        $objPerson2 = $items[0];
        $this->assertEquals("Test1", $objPerson2->FirstName, "The first name is correct");
        $this->assertEquals("Last1", $objPerson2->LastName, "The last name is correct");
        
        $objPerson2->Delete();

        $items = Person::QueryArray(
            QQ::AndCondition(
                QQ::Equal(QQN::Person()->FirstName, "Test1"),
                QQ::Equal(QQN::Person()->LastName, "Last1")
            )                          
        );
        
        $this->assertEquals(0, sizeof($items), "Deleting the Person object");
    }

    public function testQueryArray() {
        $someDate = new QDateTime();
        $someDate->setDate(2006, 1, 1);
        
        $objItems = Milestone::QueryArray(
            QQ::GreaterThan(QQN::Milestone()->Project->StartDate, $someDate),
            QQ::OrderBy(QQN::Milestone()->Project->Name)
        );
        
        $this->assertEquals(3, sizeof($objItems));

        $this->assertEquals("Milestone F", $objItems[0]->Name);
        $this->assertEquals("Blueman Industrial Site Architecture", $objItems[0]->Project->Name);

        $this->assertEquals("Milestone D", $objItems[1]->Name);
        $this->assertEquals("State College HR System", $objItems[1]->Project->Name);

        $this->assertEquals("Milestone E", $objItems[2]->Name);
        $this->assertEquals("State College HR System", $objItems[2]->Project->Name);
    }
    
    public function testQueryCount() {
        $someDate = new QDateTime();
        $someDate->setDate(2006, 1, 1);
        
        $intItemCount = Milestone::QueryCount(
            QQ::GreaterThan(QQN::Milestone()->Project->StartDate, $someDate),
            // test for single QQClause object
            // the subject of the https://github.com/qcubed/qcubed/issues/100 issue #100
            QQ::Distinct()
        );
        
        $this->assertEquals(3, $intItemCount);

        $intItemCount2 = Milestone::QueryCount(
            QQ::GreaterThan(QQN::Milestone()->Project->StartDate, $someDate),
            // test for an array of QQClause objects
            QQ::Clause(
                // The QQ::Distinct is used because of the https://github.com/qcubed/qcubed/issues/231 issue #231
                QQ::Distinct()
                , QQ::Distinct()
            )
        );
        
        $this->assertEquals(3, $intItemCount2);
    }
    
    public function testOrderByCondition() {
        $objItems = Person::QueryArray(
            QQ::All(),
            QQ::Clause(
                QQ::OrderBy(
                    QQ::NotEqual(QQN::Person()->LastName, 'Smith'), 
                    QQN::Person()->FirstName)
                )
            );

        $this->assertEquals("Alex Smith", $objItems[0]->FirstName . " " . $objItems[0]->LastName);
        $this->assertEquals("Jennifer Smith", $objItems[1]->FirstName . " " . $objItems[1]->LastName);
        $this->assertEquals("Wendy Smith", $objItems[2]->FirstName . " " . $objItems[2]->LastName);
        $this->assertEquals("Ben Robinson", $objItems[3]->FirstName . " " . $objItems[3]->LastName);
    }
    
    public function testGroupBy() {
        $objItems = Project::QueryArray(
            QQ::All(),
            QQ::Clause(
                QQ::GroupBy(QQN::Project()->Id),
                QQ::Count(QQN::Project()->PersonAsTeamMember->PersonId, 'team_member_count'),
                QQ::OrderBy(QQN::Project()->Id)
            )
        );
        
        $this->assertEquals(4, sizeof($objItems), "4 projects found");
        
        $this->assertEquals(5, $objItems[0]->GetVirtualAttribute('team_member_count'), "5 team members found for the first project");
        $this->assertEquals(6, $objItems[1]->GetVirtualAttribute('team_member_count'), "6 team members found for the second project");
        $this->assertEquals(5, $objItems[2]->GetVirtualAttribute('team_member_count'), "5 team members found for the third project");
        $this->assertEquals(7, $objItems[3]->GetVirtualAttribute('team_member_count'), "7 team members found for the forth project");
    }
    
    public function testAssociationTables() {
        // All People Who Are on a Project Managed by Karen Wolfe (Person ID #7)        
        $objPersonArray = Person::QueryArray(
            QQ::Equal(QQN::Person()->ProjectAsTeamMember->Project->ManagerPersonId, 7),
            QQ::Clause(
                QQ::Distinct(),
                QQ::OrderBy(QQN::Person()->LastName, QQN::Person()->FirstName)
            )
        );
        
        $arrNamesOnly = array();
        foreach ($objPersonArray as $item) {
            $arrNamesOnly[] = $item->FirstName . " " . $item->LastName;
         }
        
        $this->assertEquals(array(
            "Brett Carlisle",
            "John Doe",
            "Samantha Jones",
            "Jacob Pratt",
            "Kendall Public",
            "Ben Robinson",
            "Alex Smith",
            "Wendy Smith",
            "Karen Wolfe"),
            $arrNamesOnly,
            "List managed persons is correct");
        
        $objPersonArray = Person::QueryArray(
            QQ::Equal(QQN::Person()->PersonType->PersonTypeId, PersonType::Inactive),
            QQ::Clause(
                QQ::OrderBy(QQN::Person()->LastName, QQN::Person()->FirstName)
            )
        );
        
        $arrNamesOnly = array();
        foreach ($objPersonArray as $item) {
            $arrNamesOnly[] = $item->FirstName . " " . $item->LastName;
        }
        
        $this->assertEquals(array(
            "Linda Brady",
            "John Doe",
            "Ben Robinson")
            , $arrNamesOnly
            , "Person-PersonType assn is correct");
        
    }
    
    public function testQuerySingleEmpty() {
        $targetPerson = Person::QuerySingle(
            QQ::Equal(QQN::Person()->Id, 1241243));
        
        $this->assertEquals(null, $targetPerson, "QuerySingle should return null for a not-found record");
    }

    public function testQuerySelectSubset() {
        $objPersonArray = Person::LoadAll(QQ::Select(QQN::Person()->FirstName));
        foreach ($objPersonArray as $objPerson) {
            $this->setExpectedExceptionRegExp('QCallerException', '/LastName .* is not valid./');
            $objPerson->LastName;
            $this->setExpectedException(null);

            // If we now set the last name, we should be able to get it
            $objPerson->LastName = "Test";
            $this->assertEquals("Test", $objPerson->LastName); // use the getter
            $this->assertNotNull($objPerson->Id, "Id should not be null since it's always added to the select list");
        }
    }
    
    public function testLoadAll() {
        $objPersonArray = Person::LoadAll ();
        $this->assertEquals(12, count($objPersonArray), "12 people found.");
        
        $objTwoKeyArray = TwoKey::LoadAll();
        $this->assertEquals(6, count($objTwoKeyArray), "6 TwoKey items found.");
    }
    
    public function testQuerySelectSubsetSkipPK() {
        $objSelect = QQ::Select(QQN::Person()->FirstName);
        $objSelect->SetSkipPrimaryKey(true);
        $objPersonArray = Person::LoadAll($objSelect);
        foreach ($objPersonArray as $objPerson) {
            $this->setExpectedExceptionRegExp('QCallerException', '/LastName .* is not valid./');
            $objPerson->LastName;
            $this->setExpectedException(null);
            $this->assertNull($objPerson->Id, "Id should be null since SkipPrimaryKey is set on the Select object");
        }
    }

    public function testExpand() {
        // Test intermediate nodes on expansion
         $clauses = QQ::Clause(
            QQ::Expand(QQN::Milestone()->Project->ManagerPerson)
        );
        
        $objMilestone = 
            Milestone::QuerySingle(
                QQ::Equal (QQN::Milestone()->Id, 1),
                $clauses
            );
        
        $this->assertTrue(!is_null($objMilestone->Name), "Milestone 1 has a name");
        $this->assertEquals("Milestone A", $objMilestone->Name, "Milestone 1 has name of Milestone A");
        $this->assertTrue(!is_null($objMilestone->Project->Name), "Project 1 has a name");
        $this->assertEquals("ACME Website Redesign", $objMilestone->Project->Name, "Project 1 has name of ACME Website Redesign");
        $this->assertTrue(!is_null($objMilestone->Project->ManagerPerson->FirstName), "Person 7 has a name");
        $this->assertEquals("Karen", $objMilestone->Project->ManagerPerson->FirstName, "Person 7 has first name of Karen");
        
         $clauses = QQ::Clause(
            QQ::ExpandAsArray (QQN::Project()->PersonAsTeamMember),
            QQ::OrderBy (QQN::Project()->PersonAsTeamMember->Person->LastName, QQN::Project()->PersonAsTeamMember->Person->FirstName)
        );
        
        // short reach
        $objProject = 
            Project::QuerySingle(
                QQ::Equal (QQN::Project()->Id, 1),
                $clauses
            );
            
        $objPersonArray = $objProject->_PersonAsTeamMemberArray;
        $arrNamesOnly = array();
        foreach ($objPersonArray as $item) {
            $arrNamesOnly[] = $item->FirstName . " " . $item->LastName;
        }
        
        $this->assertEquals(array(
            "Samantha Jones",
            "Kendall Public",
            "Alex Smith",
            "Wendy Smith",
            "Karen Wolfe")
            , $arrNamesOnly
            , "Project Team Member expansion is correct");
        
        // long reach
        $clauses = QQ::Clause(
            QQ::ExpandAsArray (QQN::Milestone()->Project->PersonAsTeamMember),
            QQ::OrderBy (QQN::Milestone()->Project->PersonAsTeamMember->Person->LastName, QQN::Milestone()->Project->PersonAsTeamMember->Person->FirstName)
        );
        
        
        $objMilestone = 
            Milestone::QuerySingle(
                QQ::Equal (QQN::Milestone()->Id, 1),
                $clauses
            );
            
        $objPersonArray = $objMilestone->Project->_PersonAsTeamMemberArray;
        $arrNamesOnly = array();
        foreach ($objPersonArray as $item) {
            $arrNamesOnly[] = $item->FirstName . " " . $item->LastName;
        }
        
        $this->assertEquals(array(
            "Samantha Jones",
            "Kendall Public",
            "Alex Smith",
            "Wendy Smith",
            "Karen Wolfe"
            )
            , $arrNamesOnly
            , "Long reach Milestone to Project Team Member expansion is correct");
    }

    /**
     * Make sure that expansions looking backwards are pointing to the same object looking forwards
     */
    public function testExpandReverseReferences() {

        // Test virtual binding of reverse relationships
        $clauses = [QQ::Expand(QQN::Person()->ProjectAsManager)];
        $objPerson = Person::QuerySingle(QQ::All(), $clauses);
        $objPerson->FirstName = 'test';
        $objProject = $objPerson->ProjectAsManager;
        $objPerson2 = $objProject->ManagerPerson;

        $this->assertEquals('test', $objPerson2->FirstName);

        
        // Test forward reference looking back
        $clauses = [QQ::Expand(QQN::Project()->ManagerPerson)];
        $objProject = Project::QuerySingle(QQ::All(), $clauses);
        $objProject->Name = 'test';
        $objPerson = $objProject->ManagerPerson;
        $objProject2 = $objPerson->ProjectAsManager;

        $this->assertEquals('test', $objProject2->Name);

        // test unique reverse reference
        $clauses = [QQ::Expand(QQN::Person()->Login)];
        $objPerson = Person::QuerySingle(QQ::All(), $clauses);
        $objPerson->FirstName = 'test';
        $objLogin = $objPerson->Login;
        $objPerson2 = $objLogin->Person;

        $this->assertEquals('test', $objPerson2->FirstName);

        // test many-to-many expansion
        $clauses = [QQ::ExpandAsArray(QQN::Project()->PersonAsTeamMember)];
        $objProject = Project::QuerySingle(QQ::All(), $clauses);
        $objProject->Name = 'test';
        $objPersonArray = $objProject->_PersonAsTeamMemberArray;
        $objProject2 = $objPersonArray[0]->_ProjectAsTeamMember;

        $this->assertEquals('test', $objProject2->Name);

    }
    
    public function testHaving() {
        $objItems = Project::QueryArray(
            QQ::All(),
            QQ::Clause(
                QQ::Select(QQN::Project()->Id, QQN::Project()->Name),    // Some databases require selecting specific fields when aggregating
                QQ::GroupBy(QQN::Project()->Id),
                QQ::Count(QQN::Project()->PersonAsTeamMember->PersonId, 'team_member_count'),
                QQ::Having(QQ::SubSql('COUNT({1}) > 5', QQN::Project()->PersonAsTeamMember->PersonId)),
                QQ::OrderBy(QQN::Project()->Id)
            )
        );
        
        $this->assertEquals(2, sizeof($objItems), "2 projects found");
        
        $this->assertEquals("State College HR System", $objItems[0]->Name, "Project " . $objItems[0]->Name . " found");
        $this->assertEquals(6, $objItems[0]->GetVirtualAttribute('team_member_count'), "6 team members found for project " . $objItems[0]->Name);
    }
    
    public function testEmptyColumns() {
        $objItem = Login::QuerySingle(
            QQ::Equal(QQN::Login()->Id, 1)
        );
        
        $var = $objItem->IsEnabled;

        $this->assertNotNull($var, "Zero column does not return null. ");
        $this->assertTrue($var == 0, "Zero boolean column is false or zero. ");

        $objItem = Project::QuerySingle(
            QQ::Equal(QQN::Project()->Id, 2)
        );
        $this->assertTrue($objItem->EndDate === null, "Null date column returns a null.");

        // Testing unique reverse reference on null
        $objPerson = new Person();
        $objLogin = $objPerson->Login;

        $this->assertNull($objLogin, "New record should not be associated with null PK.");
    }

    public function testOrderByReverseReference() {
        // orders by the private key of the reverse reference node.
        $objPerson = Person::QuerySingle(
            QQ::IsNotNull(QQN::Person()->ProjectAsManager->Id),
            [QQ::OrderBy(QQN::Person()->ProjectAsManager)]
        );
        $this->assertEquals(7, $objPerson->Id, "Manager of first project found.");

    }

    public function testOrderByExpansion() {
        $objPersonArray = Person::QueryArray(
            QQ::All(),
            QQ::OrderBy(
                QQ::IsNotNull(QQN::Person()->ProjectAsManager->Description), false, QQN::Person()->ProjectAsManager->Id
            )
        );

        $this->assertEquals(7, $objPersonArray[0]->Id, "Found first project with manager");
    }

    public function testVirtualAttributeAliases() {
        $clauses = [
            QQ::GroupBy(QQN::Project()->ProjectStatusTypeId),
            QQ::Sum(QQN::Project()->Budget, 'Budget Amount'),
            QQ::Expand(QQ::Virtual('Balance', QQ::Func('SUM', QQ::Sub(QQN::Project()->Budget, QQN::Project()->Spent))))
        ];
        $cond = QQ::Equal(QQN::Project()->ProjectStatusTypeId, ProjectStatusType::Open);

        $objProject = Project::QuerySingle($cond, $clauses);

        $amount1 = $objProject->GetVirtualAttribute('Budget Amount');
        $this->assertEquals(83000, $amount1);
        $amount2 = $objProject->GetVirtualAttribute('Balance');
        $this->assertEquals(5599.50, $amount2);
    }

    public function testSubSql() {
        $objProject = Project::QuerySingle(
            QQ::All(),
            QQ::Clause(
                QQ::Count(QQ::SubSql('DISTINCT {1}', QQN::Project()->ManagerPersonId), "manager_count")
            )
        );

        $this->assertEquals(3, $objProject->GetVirtualAttribute("manager_count"), "Project manager count is 3");
    }

    public function testGettersSetters() {
        $objProject = Project::QuerySingle(QQ::Equal(QQN::Project()->Id, 1));

        $this->assertEquals(1, $objProject->getId());
        $this->assertEquals(7, $objProject->getManagerPersonId());

        $objProject2 = new Project();

        try {
            $objProject2->setId(2);    // can't set a pk that is an identity
            $blnPassed = true;
        }
        catch(QCallerException $e) {
            $blnPassed = false;
        }
        $this->assertEquals(false, $blnPassed, 'Exception sould be called when trying to set a pk on an identity column');


        $objProject2->setName('Test');
        $strName = $objProject2->getName();    
        $this->assertEquals('Test', $strName);


    }

    public function testReload() {
        $objProject = Project::QuerySingle(QQ::Equal(QQN::Project()->Id, 1));
        $objProject->Reload();

        $this->assertEquals(1, $objProject->getId());
        $this->assertEquals(7, $objProject->getManagerPersonId());
        $this->assertEquals("ACME Website Redesign", $objProject->Name);

        // Test non-identity set and reload
        $objMilestone = Milestone::Load(1);
        $objMilestone->Id = 5;    // Should be legal for non-identity PKs
        $objMilestone->Reload();
        $this->assertEquals(1, $objMilestone->Id, "Identity should reset to original value after a reload");
    }

    public function testSetReference() {
        $milestone1 = Milestone::Load(1);
        $intProjectId = $milestone1->ProjectId;

        $project4 = Project::Load(4);

        $milestone1->Project = $project4;
        $milestone1->Save();

        $milestone1 = Milestone::Load(1);
        $this->assertEquals(4, $milestone1->Project->Id);

        // Restore state of database
        $milestone1->ProjectId = $intProjectId;
        $milestone1->Save();
        $this->assertEquals($intProjectId, $milestone1->Project->Id);
    }

    public function testTypes() {
        $objProject =
            Project::QuerySingle(
                QQ::Equal (QQN::Project()->Id, 1)
            );

        $this->assertEquals(3, $objProject->getProjectStatusTypeId());
        $this->assertEquals("Completed", $objProject->getProjectStatusType());
    }
}