BranchControllerTest.php #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • application/
  • site/
  • tests/
  • BranchControllerTest.php
  • View
  • Commits
  • Open Download .zip Download (23 KB)
<?php
/**
 * Test the site branch controller.
 *
 * @copyright   2012 Perforce Software. All rights reserved.
 * @license     Please see LICENSE.txt in top-level folder of this distribution.
 * @version     <release>/<patch>
 */
class Site_Test_BranchControllerTest extends ModuleControllerTest
{
    /**
     * Test the manage action with no additional sites.
     */
    public function testManageEmpty()
    {
        $this->utility->impersonate('administrator');

        $this->dispatch('/site/branch/manage');
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('manage',     'Expected action, line ' . __LINE__);

        // verify that table and dojo data elements exist
        $this->assertXpath('//div[@dojotype="dojox.data.QueryReadStore"]', 'Expected dojo.data div');
        $this->assertXpath(
            '//table[@dojotype="p4cms.ui.grid.DataGrid" and @jsid="p4cms.site.branch.grid.instance"]',
            'Expected dojox.grid table'
        );

        // check JSON output
        $this->resetRequest()
             ->resetResponse();
        $this->dispatch('/site/branch/manage/format/json');

        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('manage',     'Expected action, line ' . __LINE__);

        $body = $this->response->getBody();
        $data = Zend_Json::decode($body);

        //verify number of sites
        $this->assertSame(
            $data['numRows'],
            2,
            'Expected number of items'
        );
    }

    /**
     * Test manage active page - should redirect to manage
     */
    public function testManageActive()
    {
        $this->utility->impersonate('administrator');

        $this->dispatch('/site/branch/manage-active/format/json');
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('manage',     'Expected action, line ' . __LINE__);
    }

    /**
     * Test management pages with sites created.
     */
    public function testManageSites()
    {
        $this->utility->impersonate('administrator');

        $branchNames = array('fee', 'fi', 'fo', 'fum');
        $this->_createBranches($branchNames);

        $this->dispatch('/site/branch/manage/format/json');
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('manage',     'Expected action, line ' . __LINE__);

        $body = $this->response->getBody();
        $data = Zend_Json::decode($body);

        array_unshift($branchNames, P4Cms_Site::fetchActive()->getBranchBasename());
        array_unshift($branchNames, 'testsite');

        // verify number of sites
        $this->assertSame(
            count($branchNames),
            $data['numRows'],
            'Expected number of items'
        );

        foreach ($data['items'] as $key => $branch) {
            $this->assertSame(
                $branchNames[$key],
                $branch['name'],
                'Expected branch named ' . $branchNames[$key] . ' in position ' . $key . ', line ' . __LINE__
            );
        }
    }

    /**
     * Test the switch action
     */
    public function testSwitch()
    {
        $this->utility->impersonate('administrator');

        $this->_createBranches(array('test'));

        $this->dispatch('/site/branch/switch/sessionId/' . session_id());
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('switch',     'Expected action, line ' . __LINE__);

        $body        = $this->response->getBody();
        $decodedBody = Zend_Json_Decoder::decode($body);

        $this->assertSame($decodedBody['site'], 'chronicle-test', 'Expected site, line ' . __LINE__);
        $this->assertSame($decodedBody['branch'], 'live', 'Expected branch, line ' . __LINE__);
    }

    /**
     * Ensure that the proper form is returned when an add request is sent
     */
    public function testAddForm()
    {
        $this->utility->impersonate('administrator');

        $this->dispatch('/site/branch/add');
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('add',     'Expected action, line ' . __LINE__);

        // ensure that required form inputs are presented correctly.
        $this->assertQuery("#layout-main form",     "Expected add form.");
        $this->assertQuery("input[name='name']",    "Expected name input.");
        $this->assertQuery("select[name='site']",   "Expected site select input.");
        $this->assertQuery("select[name='parent']", "Expected parent select input.");
        $this->assertQuery(
            "select[name='parent'] option[value='//chronicle-test/live']",
            "Expected live parent option."
        );
        $this->assertQuery("input[type='submit']",  "Expected submit button.");
    }

    /**
     * Test a valid add form submission.
     */
    public function testAddGoodPost()
    {
        $this->utility->impersonate('administrator');
        // save acl so it can be loaded from the site as needed
        P4Cms_Site::fetchActive()->getAcl()->save();

        $branchName = 'test';

        // form request with required fields.
        $this->request->setMethod('POST');
        $this->request->setPost('name',   $branchName);
        $this->request->setPost('parent', '//chronicle-test/live');
        $this->request->setPost('site',   'chronicle-test');

        $this->dispatch('/site/branch/add');
        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('add',        'Expected action, line ' . __LINE__);

        $id = '//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $branchName;

        $sites = P4Cms_Site::fetchAll();
        $this->assertSame(count($sites), 2, "Expected site count to include new branch.  " . __LINE__);

        try {
            $site = P4Cms_Site::fetch($id);
        }
        catch (P4Cms_Model_NotFoundException $e) {
            $this->fail('Expected newly added branch with id ' . $id . ' to be present.');
        }
        $stream = $site->getStream();
        $this->assertSame($stream->getName(), $branchName, 'Expected matching branch name, line ' . __LINE__);
        $this->assertSame(
            $stream->getParent(),
            P4Cms_Site::fetchActive()->getId(),
            'Expected matching branch parent, line ' . __LINE__
        );
        $this->assertSame($stream->getId(), $id, 'Expected matching branch id, line ' . __LINE__);
    }

    /**
     * Test delete action
     */
    public function testDelete()
    {
        $this->utility->impersonate('administrator');

        // create test branch
        $name   = 'test';
        $siteId = '//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name;
        $this->_createBranches(array($name));

        $this->request->setMethod('POST');
        $this->request->setPost('id', $siteId);

        $this->dispatch('/site/branch/delete');

        $this->assertModule('site',       'Expected module, line ' . __LINE__);
        $this->assertController('branch', 'Expected controller, line ' . __LINE__);
        $this->assertAction('delete',     'Expected action, line ' . __LINE__);

        // verify deleted
        try {
            $site = P4Cms_Site::fetch($siteId);
        }
        catch (P4Cms_Model_NotFoundException $e) {
            return;
        }

        $this->fail('Expected branch with id ' . $siteId . ' to be deleted.');
    }

    /**
     * Test edit with bad branch id.
     */
    public function testEditId()
    {
        $this->utility->impersonate('administrator');

        $this->_createBranches(array('test', 'stage'));

        // try to edit with non-existing site id
        $this->request->setParam('id', '//' . P4Cms_Site::fetchActive()->getSiteId() . '/test-1');
        $this->dispatch('/site/branch/edit');
        $this->assertModule('error',     'Expected module.');
        $this->assertController('index', 'Expected controller.');
        $this->assertAction('error',     'Expected action.');

        // verify it works with existing id
        $this->resetRequest()->resetResponse();
        $this->request->setParam('id', '//' . P4Cms_Site::fetchActive()->getSiteId() . '/test');
        $this->dispatch('/site/branch/edit');

        $this->assertModule('site',       'Expected module #2.');
        $this->assertController('branch', 'Expected controller #2.');
        $this->assertAction('edit',       'Expected action #2.');
    }

    /**
     * Tets branch edit action.
     */
    public function testEditAction()
    {
        $this->utility->impersonate('administrator');

        $active = P4Cms_Site::fetchActive();

        $this->_createBranches(array('stage'));
        $stage  = P4Cms_Site::fetch('//' . $active->getSiteId() . '/stage');

        $this->_createBranches(array('test'), $stage);
        $test   = P4Cms_Site::fetch('//' . $active->getSiteId() . '/test');

        $this->assertSame(
            'test',
            $test->getStream()->getName(),
            "Expected name of the 'test' branch."
        );

        // edit 'test' branch
        $this->request->setMethod('POST');
        $this->request->setPost(
            array(
                'id'            => $test->getId(),
                'name'          => 'review',
                'description'   => 'review stage',
                'parent'        => '//' . $active->getSiteId() . '/live'
            )
        );
        $this->dispatch('/site/branch/edit');

        $this->assertModule('site',       'Expected module.');
        $this->assertController('branch', 'Expected controller.');
        $this->assertAction('edit',       'Expected action.');


        // verify that 'test' branch has been updated
        $branch = P4Cms_Site::fetch($test->getId());
        $stream = $branch->getStream();

        $this->assertSame(
            'review',
            $stream->getName(),
            "Expected branch name."
        );

        $this->assertSame(
            'review stage',
            trim($stream->getDescription()),
            "Expected branch description."
        );

        // ensure that parent has been changed as requested
        $this->assertSame(
            '//' . $active->getSiteId() . '/live',
            $stream->getParent(),
            "Expected changed branch parent."
        );
    }

    /**
     * Test for the pull details action with no params; expects an InvalidArgumentException.
     */
    public function testPullDetailsNoParams()
    {
        $this->utility->impersonate('administrator');

        $this->dispatch('/site/branch/pull-details');

        $this->assertModule('error',     'Expected error module.');
        $this->assertController('index', 'Expected controller.');
        $this->assertAction('error',     'Expected error action.');

        $this->assertQueryContentContains(
            'dl dd',
            'InvalidArgumentException',
            'Expected exception is not present, line '. __LINE__
        );
    }

    /**
     * Test for the pull details action with valid params
     */
    public function testPullDetailsMerge()
    {
        $this->utility->impersonate('administrator');

        // create test branch
        $name = 'test';
        $this->_createBranches(array($name));

        // switch to test branch, add some content, switch back
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name)->load();
        $this->_createContentChanges();
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . 'live')->load();

        $query = http_build_query(
            array(
                'groupId'   => 'content',
                'source'    => '//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name,
                'paths'     => array('content', 'content/unpublished-entries', 'content/types')
            )
        );

        $this->dispatch('/site/branch/pull-details/?' . $query);

        $body = $this->response->getBody();

        $this->assertModule('site',         'Expected site module.  ' . $body);
        $this->assertController('branch',   'Expected branch controller.  ' . $body);
        $this->assertAction('pull-details', 'Expected pull-details action.  ' . $body);

        $this->assertQueryContentContains(
            'tbody tr td',
            'Test Type',
            'Expected content type is not present.  ' . $body
        );

        $this->assertQueryContentContains(
            'tbody tr td',
            'Title!',
            'Expected content entry title is not present.  ' . $body
        );
    }

    /**
     * Tests pull action with no changes to pull.
     */
    public function testPullFormEmpty()
    {
        $this->utility->impersonate('administrator');

        $this->_createBranches(array('test'));

        $this->dispatch(
            '/site/branch/pull/format/partial/source/'
            . urlencode('//' . P4Cms_Site::fetchActive()->getSiteId() . '/test')
        );

        $this->assertModule('site',       'Expected module.');
        $this->assertController('branch', 'Expected controller.');
        $this->assertAction('pull',       'Expected action.');

        // ensure that required form inputs are presented correctly.
        $this->assertQuery("form.pull-form",           "Expected pull form.");
        $this->assertQuery("input[name='headChange']", "Expected headChange input.");
        $this->assertQuery("select[name='source']",   "Expected sourceselect input.");
        $this->assertQuery("input[name='target'][readOnly='1']", "Expected readonly target input.");
        $this->assertQuery("input[type='radio'][name='mode']",  "Expected mode radio selector.");

        // Expect 2 paths (Configuration parent and Permissions child) due to acl.
        $this->assertQueryCount("input[type='checkbox'][name='paths[]']", 2, "Expected 2 paths available to pull.");
        $this->assertQueryContentContains(
            "ul.nested-checkbox li",
            "Configuration",
            "Expected Configuration pull path label.  " . $this->response->getBody()
        );
        $this->assertQueryContentContains(
            "ul.nested-checkbox li",
            "Permissions",
            "Expected Permissions pull path label.  " . $this->response->getBody()
        );
    }

    /**
     * Tests pull action with a merge request
     */
    public function testPullFormChanges()
    {
        $this->utility->impersonate('administrator');

        // create test branch
        $name = 'test';
        $this->_createBranches(array($name));

        // switch to test branch, add some content, switch back
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name)->load();
        $this->_createContentChanges();
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . 'live')->load();

        // pull content from test branch to live
        $this->dispatch(
            '/site/branch/pull/format/partial/source/'
            . urlencode('//chronicle-test/test')
        );

        $this->assertModule('site',       'Expected module.');
        $this->assertController('branch', 'Expected controller.');
        $this->assertAction('pull',       'Expected action.');

        $body = $this->response->getBody();

        // ensure that required form inputs are presented correctly.
        $this->assertQuery("form.pull-form",                      "Expected pull form." . $body);
        $this->assertQuery("input[name='headChange'][value='5']", "Expected headChange input with value 5." . $body);
        $this->assertQuery("select[name='source']",               "Expected source select." . $body);
        $this->assertQuery("input[name='target'][readOnly='1']",  "Expected readonly target input." . $body);
        $this->assertQuery("input[type='radio'][name='mode']",    "Expected mode radio selector." . $body);

        // expect 5 paths: Content parent, Published Entries and Type children; Configuration parent, Permissions child
        $this->assertQueryCount(
            "input[type='checkbox'][name='paths[]']",
            5,
            "Expected 5 paths available to pull." . $body
        );
    }

    /**
     * Tests pull action with a copy request
     */
    public function testPullCopy()
    {
        $this->utility->impersonate('administrator');

        // create test branch
        $name = 'test';
        $this->_createBranches(array($name));

        // switch to test branch, add some content, switch back
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name)->load();
        $this->_createContentChanges();
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . 'live')->load();
        $this->_createContentChanges();

        // modify content to ensure difference between branches
        P4Cms_Content::fetch("test")->setValue('title', 'Test?')->setValue('body', str_repeat(':', 25))->save();

        $change = P4_Change::fetchAll(
            array(
                P4_Change::FETCH_BY_STATUS => P4_Change::SUBMITTED_CHANGE,
                P4_Change::FETCH_MAXIMUM   => 1
            ),
            P4Cms_User::fetchActive()->getPersonalAdapter()->getConnection()
        )->last()->getId();

        $this->request->setMethod('POST');
        $this->request->setPost(
            array(
                'headChange' => $change,
                'source'     => '//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name,
                'target'     => 'live',
                'mode'       => Site_Form_Pull::MODE_COPY,
                'paths'      => array('content', 'content/published-entries', 'content/types')
            )
        );

        $this->dispatch('/site/branch/pull/format/json');

        $this->assertModule('site',       'Expected module.');
        $this->assertController('branch', 'Expected controller.');
        $this->assertAction('pull',       'Expected action.');

        $body = $this->response->getBody();
        $data = Zend_Json::decode($body);

        $this->assertSame(
            $data['severity'],
            'success',
            'Expected successful pull.  ' . print_r($data['errors'], true)
        );
        $this->assertSame(
            $data['message'],
            "Pulled 2 items from 'test'.",
            'Expected message indicating successful pull of 2 records: ' . $data['message']
        );
    }

    /**
     * Tests pull action with a merge request
     *
     * @todo - add content to live and ensure it's not there.
     */
    public function testPullMerge()
    {
        $this->utility->impersonate('administrator');

        // create test branch
        $name = 'test';
        $this->_createBranches(array($name));

        // switch to test branch, add some content, switch back
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name)->load();
        $this->_createContentChanges();
        P4Cms_Site::fetch('//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . 'live')->load();

        $change = P4_Change::fetchAll(
            array(
                P4_Change::FETCH_BY_STATUS => P4_Change::SUBMITTED_CHANGE,
                P4_Change::FETCH_MAXIMUM   => 1
            ),
            P4Cms_User::fetchActive()->getPersonalAdapter()->getConnection()
        )->last()->getId();

        $this->request->setMethod('POST');
        $this->request->setPost(
            array(
                'headChange' => $change,
                'source'     => '//' . P4Cms_Site::fetchActive()->getSiteId() . '/' . $name,
                'target'     => 'live',
                'mode'       => Site_Form_Pull::MODE_MERGE,
                'paths'      => array('content', 'content/published-entries', 'content/types')
            )
        );

        $this->dispatch('/site/branch/pull/format/json');

        $this->assertModule('site',       'Expected module.');
        $this->assertController('branch', 'Expected controller.');
        $this->assertAction('pull',       'Expected action.');

        $body = $this->response->getBody();
        $data = Zend_Json::decode($body);

        $this->assertSame($data['severity'], 'success', 'Expected successful pull.  ' . print_r($data, true));
        $this->assertSame(
            $data['message'],
            "Pulled 2 items from 'test'.",
            'Expected message indicating successful pull of 2 records: ' . $data['message']
        );
    }

    /**
     * Adds a content type and a content entry to the current active site.
     */
    protected function _createContentChanges()
    {
        $type = new P4Cms_Content_Type;
        $type->setId('test-type')
             ->setLabel('Test Type')
             ->setElements(
                array(
                    "title" => array(
                        "type"      => "text",
                        "options"   => array("label" => "Title", "required" => true)
                    ),
                    "body"  => array(
                        "type"      => "textarea",
                        "options"   => array("label" => "Body")
                    )
                )
             )
             ->setValue('icon', file_get_contents(TEST_ASSETS_PATH . "/images/content-type-icon.png"))
             ->setFieldMetadata('icon', array("mimeType" => "image/png"))
             ->setValue('group', 'test')
             ->save();

        $entry = new P4Cms_Content;
        $entry->setId("test")
            ->setValue('contentType', 'test-type')
            ->setValue('title',       "Title!")
            ->setValue('body',        str_repeat('.', 25))
            ->save();
    }

    /**
     * Creates several branches of the given site for testing (does not copy
     * any data from parent).
     *
     * @param   array       $branches   list of branches names to create for the given site.
     * @param   P4Cms_Site  $site       optional - site to create branches for (active site
     *                                  if not provided).
     */
    protected function _createBranches(array $branches, P4Cms_Site $site = null)
    {
        $site = $site ?: P4Cms_Site::fetchActive();

        foreach ($branches as $name) {
            $stream = new P4_Stream();
            $stream->setId('//' . $site->getSiteId() . '/' . $name)
                   ->setName($name)
                   ->setDescription('Description for ' . $name)
                   ->setParent($site->getId())
                   ->setType('development')
                   ->setOwner(P4Cms_User::fetchActive()->getId())
                   ->setPaths('share ...')
                   ->save();

            $newSite = P4Cms_Site::fetch($stream->getId());
            $acl     = $newSite->getAcl();
            $acl->installDefaults()->save();
        }
    }
}
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/application/site/tests/BranchControllerTest.php
#1 8972 Matt Attaway Initial add of the Chronicle source code