diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php
index 32aaddc2..0461aa4a 100644
--- a/features/bootstrap/FeatureContext.php
+++ b/features/bootstrap/FeatureContext.php
@@ -27,6 +27,7 @@ class FeatureContext extends BehatContext
protected $applicationTester;
protected $filesystem;
protected $workingDir;
+ protected $currentWorkspaceName = 'default';
/**
* Initializes context.
@@ -45,13 +46,13 @@ public function beforeScenario()
chdir($this->workingDir);
$this->filesystem = new Filesystem();
- $session = $this->getSession();
- $session->save();
+ $session = $this->getSession(null, true);
$this->applicationTester = new ApplicationTester($this->application);
$this->applicationTester->run(array(
'--transport' => 'jackrabbit',
'--no-interaction' => true,
+ '--unsupported' => true, // test all the commands, even if they are unsupported (we test for the fail)
), array(
'interactive' => true,
));
@@ -69,8 +70,19 @@ public static function cleanTestFolders()
$fs->remove(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpcr-shell');
}
- private function getSession($workspaceName = 'default')
+ private function getSession($workspaceName = null, $force = false)
{
+ if ($workspaceName === null) {
+ $workspaceName = $this->currentWorkspaceName;
+ }
+
+ static $sessions = array();
+
+ if (false === $force && isset($sessions[$workspaceName])) {
+ $session = $sessions[$workspaceName];
+ return $session;
+ }
+
$params = array(
'jackalope.jackrabbit_uri' => 'http://localhost:8080/server/',
);
@@ -79,9 +91,9 @@ private function getSession($workspaceName = 'default')
$repository = $factory->getRepository($params);
$credentials = new SimpleCredentials('admin', 'admin');
- $session = $repository->login($credentials, $workspaceName);
+ $sessions[$workspaceName] = $repository->login($credentials, $workspaceName);
- return $session;
+ return $sessions[$workspaceName];
}
private function getOutput()
@@ -184,7 +196,7 @@ public function iShouldSeeTheFollowing(PyStringNode $string)
public function theFixturesAreLoaded($arg1)
{
$fixtureFile = $this->getFixtureFilename($arg1);
- $session = $this->getSession();
+ $session = $this->getSession(null, true);
NodeHelper::purgeWorkspace($session);
$session->save();
$session->importXml('/', $fixtureFile, 0);
@@ -407,7 +419,7 @@ public function theNodeAtShouldNotHaveTheMixin($arg1, $arg2)
*/
public function thereShouldNotExistANodeAt($arg1)
{
- $session = $this->getSession();
+ $session = $this->getSession(null, true);
try {
$session->getNode($arg1);
@@ -506,7 +518,11 @@ public function thereExistsAWorkspace($arg1)
{
$session = $this->getSession();
$workspace = $session->getWorkspace();
- $workspace->createWorkspace($arg1);
+ try {
+ $workspace->createWorkspace($arg1);
+ } catch (\Exception $e) {
+ // already exists..
+ }
}
/**
@@ -522,12 +538,13 @@ public function thereShouldNotExistAWorkspaceCalled($arg1)
}
/**
- * @Given /^the "([^"]*)" fixtures are loaded into a workspace "([^"]*)"$/
+ * @Given /^the "([^"]*)" fixtures are loaded into workspace "([^"]*)"$/
*/
- public function theFixturesAreLoadedIntoAWorkspace($arg1, $arg2)
+ public function theFixturesAreLoadedIntoWorkspace($arg1, $arg2)
{
+ $this->theCurrentWorkspaceIs($arg2);
$fixtureFile = $this->getFixtureFilename($arg1);
- $session = $this->getSession($arg2);
+ $session = $this->getSession();
NodeHelper::purgeWorkspace($session);
$session->save();
$session->importXml('/', $fixtureFile, 0);
@@ -545,7 +562,6 @@ public function theNodeTypeIsLoaded($arg1)
$workspace = $session->getWorkspace();
$nodeTypeManager = $workspace->getNodeTypeManager();
$nodeTypeManager->registerNodeTypesCnd($cnd, true);
- $session->save();
}
/**
@@ -603,6 +619,33 @@ public function theCurrentNodeIs($arg1)
$this->executeCommand(sprintf('cd %s', $arg1));
}
+ /**
+ * @Given /^the current workspace is "([^"]*)"$/
+ */
+ public function theCurrentWorkspaceIs($arg1)
+ {
+ $this->thereExistsAWorkspace($arg1);
+ $this->currentWorkspaceName = $arg1;
+ }
+
+ /**
+ * @Given /^the current workspace is empty/
+ */
+ public function theCurrentWorkspaceIsEmpty()
+ {
+ $session = $this->getSession();
+ NodeHelper::purgeWorkspace($session);
+ $session->save();
+ }
+
+ /**
+ * @Given /^I refresh the session/
+ */
+ public function iRefreshTheSession()
+ {
+ $this->executeCommand('session:refresh');
+ }
+
/**
* @Given /^the primary type of "([^"]*)" should be "([^"]*)"$/
*/
@@ -615,17 +658,29 @@ public function thePrimaryTypeOfShouldBe($arg1, $arg2)
}
/**
- * @Given /^the node at "([^"]*)" should have the property "([^"]*)" with type "([^"]*)"$/
+ * @Given /^the node at "([^"]*)" should have the property "([^"]*)" with value "([^"]*)"$/
*/
- public function theNodeAtShouldHaveThePropertyWithType($arg1, $arg2, $arg3)
+ public function theNodeAtShouldHaveThePropertyWithValue($arg1, $arg2, $arg3)
{
$session = $this->getSession();
$node = $session->getNode($arg1);
$property = $node->getProperty($arg2);
- $propertyType = $property->getType();
+ $propertyType = $property->getValue();
PHPUnit_Framework_Assert::assertEquals($arg3, $propertyType);
}
+ /**
+ * @Given /^I set the value of property "([^"]*)" on node "([^"]*)" to "([^"]*)"$/
+ */
+ public function iSetTheValueOfPropertyOnNodeTo($arg1, $arg2, $arg3)
+ {
+ $session = $this->getSession();
+ $node = $session->getNode($arg2);
+ $property = $node->getProperty($arg1);
+ $property->setValue($arg3);
+ $session->save();
+ }
+
/**
* @Given /^the node at "([^"]*)" has the mixin "([^"]*)"$/
*/
@@ -644,7 +699,7 @@ public function iCloneNodeFromTo($arg1, $arg2, $arg3)
{
$session = $this->getSession();
$workspace = $session->getWorkspace();
- $workspace->cloneFrom($arg2, $arg1, $arg3, false);
+ $workspace->cloneFrom($arg2, $arg1, $arg3, true);
}
/**
diff --git a/features/fixtures/cms.xml b/features/fixtures/cms.xml
new file mode 100644
index 00000000..3a52a3c0
--- /dev/null
+++ b/features/fixtures/cms.xml
@@ -0,0 +1,43 @@
+
+
+
+
+ nt:unstructured
+
+
+
+
+ nt:unstructured
+
+
+
+ nt:unstructured
+
+
+ mix:referenceable
+
+
+ 13543fc6-1abf-4708-bfcc-e49511754b40
+
+
+ Article 1
+
+
+
+
+
+
diff --git a/features/fixtures/example.cnd b/features/fixtures/example.cnd
index 6e84d8b1..55ed3745 100644
--- a/features/fixtures/example.cnd
+++ b/features/fixtures/example.cnd
@@ -1,2 +1,4 @@
-
+
+
[ns:NodeType] > nt:unstructured
+orderable query
diff --git a/features/node_workspace_corresponding.feature b/features/node_corresponding.feature
similarity index 64%
rename from features/node_workspace_corresponding.feature
rename to features/node_corresponding.feature
index dbcc79ff..d81579fe 100644
--- a/features/node_workspace_corresponding.feature
+++ b/features/node_corresponding.feature
@@ -5,13 +5,17 @@ Feature: Display the path of any corresponding node in a given workspace
Background:
Given that I am logged in as "testuser"
+ And the current workspace is "default"
And the "session_data.xml" fixtures are loaded
+ And the current workspace is "default_1"
+ And the "session_data.xml" fixtures are loaded
+ And the current workspace is "default"
Scenario: Rename a node
- Given the current node is "/tests_general_base"
+ Given the current node is "/tests_general_base/idExample"
And I execute the "node:corresponding default" command
Then the command should not fail
And I should see the following:
"""
- /foobar
+ /tests_general_base/idExample
"""
diff --git a/features/node_create.feature b/features/node_create.feature
index 3ed86e3f..fdf4ce7c 100644
--- a/features/node_create.feature
+++ b/features/node_create.feature
@@ -23,12 +23,12 @@ Feature: Create a node
And the primary type of "/testfile" should be "nt:folder"
Scenario: Create a new node at a non-root current node no matching child type
- Given the current node is "/tests_general_base"
+ Given the current node is "/tests_general_base/emptyExample"
And I execute the "node:create testcreate" command
Then the command should fail
And I should see the following:
"""
- No matching child node definition found for `testcreate' in type `nt:folder' for node '/tests_general_base'. Please specify the type explicitly
+ No matching child node definition found for `testcreate'
"""
Scenario: Create a new node at a non-root current node
@@ -37,11 +37,3 @@ Feature: Create a node
And I save the session
Then the command should not fail
And there should exist a node at "/tests_general_base/testcreate"
-
- Scenario: Attempt to create an empty node
- Given I execute the "node:create" command
- Then the command should fail
- And I should see the following:
- """
- Name can not be empty
- """
diff --git a/features/node_info.feature b/features/node_info.feature
index d237bca5..8faa0c48 100644
--- a/features/node_info.feature
+++ b/features/node_info.feature
@@ -7,7 +7,7 @@ Feature: Show information about node
Given that I am logged in as "testuser"
And the "session_data.xml" fixtures are loaded
- Scenario: Rename a node
+ Scenario: Show node information
Given the current node is "/tests_general_base"
And I execute the "node:info --no-ansi" command
Then the command should not fail
@@ -17,7 +17,7 @@ Feature: Show information about node
| Path | /tests_general_base |
| UUID | N/A |
| Index | 1 |
- | Primary node type | nt:folder |
+ | Primary node type | nt:unstructured |
| Mixin node types | |
| Checked out? | [ERROR] Not implemented by jackalope |
| Locked? | [ERROR] Not implemented by jackalope |
diff --git a/features/node_list.feature b/features/node_list.feature
index e7440fa9..dc737c2e 100644
--- a/features/node_list.feature
+++ b/features/node_list.feature
@@ -19,16 +19,14 @@ Feature: List properites and chidren of current node
| numberPropertyNode/ | nt:file | |
| NumberPropertyNodeToCompare1/ | nt:file | |
| NumberPropertyNodeToCompare2/ | nt:file | |
- | jcr:createdBy | STRING | admin |
- | jcr:primaryType | NAME | nt:folder |
+ | jcr:primaryType | NAME | nt:unstructured |
Scenario: List the properties
Given the current node is "/tests_general_base"
And I execute the "node:list --properties --no-ansi" command
Then the command should not fail
And I should see a table containing the following rows:
- | jcr:createdBy | STRING | admin |
- | jcr:primaryType | NAME | nt:folder |
+ | jcr:primaryType | NAME | nt:unstructured |
Scenario: List the children nodes
Given the current node is "/tests_general_base"
diff --git a/features/node_rename.feature b/features/node_rename.feature
index ceb7b731..cf39e278 100644
--- a/features/node_rename.feature
+++ b/features/node_rename.feature
@@ -8,7 +8,8 @@ Feature: Rename a node
And the "session_data.xml" fixtures are loaded
Scenario: Rename a node
- Given the current node is "/tests_general_base"
+ Given the current node is "/tests_general_base/idExample"
And I execute the "node:rename foobar" command
+ And I save the session
Then the command should not fail
And there should exist a node at "/tests_general_base/foobar"
diff --git a/features/node_set.feature b/features/node_set.feature
index 4fc5e547..c52036da 100644
--- a/features/node_set.feature
+++ b/features/node_set.feature
@@ -11,7 +11,8 @@ Feature: Set a node property
Scenario Outline: Set a property
Given I execute the "" command
Then the command should not fail
- And the node at "/properties" should have the property "" with type ""
+ And I save the session
+ And the node at "/properties" should have the property "" with value ""
Examples:
| command | name | type |
diff --git a/features/node_set_primary_type.feature b/features/node_set_primary_type.feature
index 2a3cd2fe..36fb011f 100644
--- a/features/node_set_primary_type.feature
+++ b/features/node_set_primary_type.feature
@@ -9,5 +9,9 @@ Feature: Set the nodes primary type
Scenario: List the properties and children of the current node
Given the current node is "/tests_general_base"
- And I execute the "node:type:set-primary nt:unstructured --no-ansi" command
- Then the command should not fail
+ And I execute the "node:set-primary-type nt:unstructured --no-ansi" command
+ Then the command should fail
+ And I should see the following:
+ """
+ Not implemented
+ """
diff --git a/features/node_shared_remove.feature b/features/node_shared_remove.feature
index 187e7389..ca20ed87 100644
--- a/features/node_shared_remove.feature
+++ b/features/node_shared_remove.feature
@@ -5,12 +5,13 @@ Feature: Remove the current node from any shared set to which it belongs
Background:
Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded
- And the node at "/tests_general_base/daniel/leech" has the mixin "mix:shareable"
- And I clone node "/tests_general_base/daniel/leech" from "default" to "/tests_general_base/bar"
+ And the current workspace is "default_1"
+ And the "cms.xml" fixtures are loaded
+ And the current workspace is "default"
+ And I clone node "/cms/articles/article1" from "default_1" to "/foobar"
Scenario: Remove the current node and all of its shared paths
- Given the current node is "/tests_general_base/daniel"
+ Given the current node is "/foobar"
And I execute the "node:shared:remove" command
Then the command should fail
And I should see the following:
diff --git a/features/node_shared_show.feature b/features/node_shared_show.feature
index e1b14a9d..8c02b4b4 100644
--- a/features/node_shared_show.feature
+++ b/features/node_shared_show.feature
@@ -5,12 +5,13 @@ Feature: Show the current nodes shared set
Background:
Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded
- And the node at "/tests_general_base/daniel/leech" has the mixin "mix:shareable"
- And I clone node "/tests_general_base/daniel/leech" from "default" to "/tests_general_base/bar"
+ And the current workspace is "default_1"
+ And the "cms.xml" fixtures are loaded
+ And the current workspace is "default"
+ And I clone node "/cms/articles/article1" from "default_1" to "/foobar"
Scenario: Show the current nodes shared set
- Given the current node is "/tests_general_base/daniel/leech"
+ Given the current node is "/foobar"
And I execute the "node:shared:show" command
Then the command should fail
And I should see the following:
diff --git a/features/node_type_edit.feature b/features/node_type_edit.feature
index 9bb70105..7f9180fb 100644
--- a/features/node_type_edit.feature
+++ b/features/node_type_edit.feature
@@ -7,7 +7,7 @@ Feature: Edit a node type
Given that I am logged in as "testuser"
And the "example.cnd" node type is loaded
- Scenario Outline: Edit a property
+ Scenario Outline: Edit a node type
Given the "EDITOR" environment variable is set to "cat"
And I execute the "" command
Then the command should not fail
@@ -40,8 +40,10 @@ Feature: Edit a node type
Scenario: Create a new node type
Given I have an editor which produces the following:
"""
-
+
+
[ns:somenewtype] > nt:unstructured
+ orderable query
"""
And I execute the "node-type:edit ns:somenewtype --no-interaction" command
Then the command should not fail
@@ -55,4 +57,5 @@ Feature: Edit a node type
Then the command should not fail
And I should see the following:
"""
- gt
+ Editor emptied the CND file, doing nothing
+ """
diff --git a/features/node_update.feature b/features/node_update.feature
new file mode 100644
index 00000000..cbb9e8b9
--- /dev/null
+++ b/features/node_update.feature
@@ -0,0 +1,18 @@
+Feature: Update the current node from the node to which it corresponds in the given workspace
+ In order to update the current node from the node to which it corresponds in the given workspace
+ As a user that is logged into the shell
+ I need to be able to do that
+
+ Background:
+ Given the current workspace is "default_1"
+ And the "cms.xml" fixtures are loaded
+ And I set the value of property "title" on node "/cms/articles/article1" to "this is a test"
+ And the current workspace is "default"
+ And I clone node "/cms/articles/article1" from "default_1" to "/foobar"
+
+ Scenario: Update a node
+ Given the current node is "/foobar"
+ And I execute the "node:update default_1" command
+ Then the command should not fail
+ And I save the session
+ And the node at "/foobar" should have the property "title" with value "this is a test"
diff --git a/features/node_workspace_update.feature b/features/node_workspace_update.feature
deleted file mode 100644
index def4d8c9..00000000
--- a/features/node_workspace_update.feature
+++ /dev/null
@@ -1,13 +0,0 @@
-Feature: Update the current node from the node to which it corresponds in the given workspace
- In order to update the current node from the node to which it corresponds in the given workspace
- As a user that is logged into the shell
- I need to be able to do that
-
- Background:
- Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded
-
- Scenario: Rename a node
- Given the current node is "/tests_general_base"
- And I execute the "node:update default" command
- Then the command should not fail
diff --git a/features/repository_capability_list.feature b/features/repository_capability_list.feature
deleted file mode 100644
index 0e7b7153..00000000
--- a/features/repository_capability_list.feature
+++ /dev/null
@@ -1,11 +0,0 @@
-Feature: List the capabilities of the current repository
- In order to show the capabilities of the current repository
- As a logged in user
- I want to be able to execute a command which lists the repository descriptors
-
- Scenario: Listing the capabilities
- Given that I am logged in as "testuser"
- And I execute the "repository:capability:list" command
- Then the command should not fail
- And I should see a table containing the following rows:
- | Key | Value |
diff --git a/features/session_import.feature b/features/session_import.feature
index 56bf7338..96ab74b9 100644
--- a/features/session_import.feature
+++ b/features/session_import.feature
@@ -6,6 +6,8 @@ Feature: Import repository data from an XML file
Background:
Given the file "data.xml" contains the contents of "session_data.xml"
And that I am logged in as "testuser"
+ And the current workspace is "default"
+ And the current workspace is empty
Scenario: Import XML non existing file
Given I execute the "session:import / does-not-exist.xml" command
@@ -24,15 +26,16 @@ Feature: Import repository data from an XML file
| /tests_general_base/multiValueProperty/deepnode |
Scenario Outline: Specifying UUID behavior
- Given I execute the "session:import / data.xml --uuid-behavior=" command
+ Given I create a node at ""
+ And I execute the "session:import data.xml --uuid-behavior=" command
Then the command should not fail
Examples:
- | uuid_behavior |
- | create-new |
- | collision-remove-existing |
- | collision-replace-existing |
- | collision-throw |
+ | path | uuid_behavior |
+ | /a | create-new |
+ | /b | collision-remove-existing |
+ | /c | collision-replace-existing |
+ | /d | collision-throw |
Scenario: Specify invalid UUID behavior
Given I execute the "session:import / data.xml --uuid-behavior=invalid" command
diff --git a/features/session_login.feature b/features/session_login.feature
index e5b7adc5..698b0f11 100644
--- a/features/session_login.feature
+++ b/features/session_login.feature
@@ -1,12 +1,28 @@
-Feature: Logout of the session
- In order to disconnect from the session
+Feature: Login to the session
+ In order to reconnect as a different user from a session
As a user logged into the shell
- I need to be able to disconnect from the session
+ I need to be able to execute a command which does that
Background:
Given that I am logged in as "testuser"
- Scenario: Logout
+ Scenario: Login unauthorized (not existing)
Given I execute the "session:login foobar barfoo" command
+ Then the command should fail
+ And I should see the following:
+ """
+ Unauthorized
+ """
+
+ Scenario: Login existing
+ Given I execute the "session:login admin admin" command
+ Then the command should not fail
+
+ Scenario: Login existing
+ Given I execute the "session:login admin admin default_1" command
Then the command should not fail
- And I should be logged into the session
+ And I execute the "session:info" command
+ Then I should see the following:
+ """
+ default_1
+ """
diff --git a/features/session_namespace_set.feature b/features/session_namespace_set.feature
index 27bac5c1..5038f65e 100644
--- a/features/session_namespace_set.feature
+++ b/features/session_namespace_set.feature
@@ -9,4 +9,8 @@ Feature: Set a namespace URI alias
Scenario: Register a new namespace alias
Given I execute the "session:namespace:set foobar http://www.example.com/foobar" command
- Then the command should fail with message "TODO: implement session scope remapping of namespaces"
+ Then the command should fail
+ And I should see the following:
+ """
+ TODO: implement session scope remapping of namespaces
+ """
diff --git a/features/session_node_move.feature b/features/session_node_move.feature
index dce184f9..5c8ae11a 100644
--- a/features/session_node_move.feature
+++ b/features/session_node_move.feature
@@ -8,8 +8,8 @@ Feature: Move a node in the current session
And the "session_data.xml" fixtures are loaded
Scenario: Move node
- Given I execute the "session:node:move /tests_general_base/index.txt /foobar.txt" command
+ Given I execute the "session:node:move /tests_general_base/index.txt /foobar" command
Then the command should not fail
- And I save the session
- And there should exist a node at "/foobar.txt"
+ And I execute the "session:save" command
+ And there should exist a node at "/foobar"
And there should not exist a node at "/tests_general_base/index.txt"
diff --git a/features/session_node_show.feature b/features/session_node_show.feature
index d546d45f..3b64cc49 100644
--- a/features/session_node_show.feature
+++ b/features/session_node_show.feature
@@ -12,5 +12,4 @@ Feature: Display a detailed view of a single node
Then the command should not fail
And I should see a table containing the following rows:
| Property / Node Name | Type / Node Type | Value |
- | - jcr:primaryType | NAME | nt:folder |
- | multiValueProperty/ | nt:folder | jcr:uuid: 14e18ef3-be20-4985-bee9-7bb4763b31de, jcr:... |
+ | - jcr:primaryType | NAME | nt:unstructured |
diff --git a/features/session_property_edit.feature b/features/session_property_edit.feature
index 9d052e15..bc4d6cb5 100644
--- a/features/session_property_edit.feature
+++ b/features/session_property_edit.feature
@@ -14,17 +14,6 @@ Feature: Edit a single property
Examples:
| command |
- | session:property:edit /properties/uri |
- | session:property:edit /properties/double |
- | session:property:edit /properties/binary |
- | session:property:edit /properties/long |
- | session:property:edit /properties/reference |
- | session:property:edit /properties/date |
- | session:property:edit /properties/path |
- | session:property:edit /properties/string |
- | session:property:edit /properties/weakreference |
- | session:property:edit /properties/decimal |
- | session:property:edit /properties/multivalue 0|
| session:property:edit /properties/multivalue 1|
Scenario: Edit multivalue property, no index
diff --git a/features/session_property_remove.feature b/features/session_property_remove.feature
index b49e3c6a..95b61e94 100644
--- a/features/session_property_remove.feature
+++ b/features/session_property_remove.feature
@@ -5,14 +5,13 @@ Feature: Remove a single property at a specified path
Background:
Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded
+ And the "cms.xml" fixtures are loaded
Scenario: Remove a property
- Given there exists a property at "/tests_general_base/idExample/jcr:content/foo"
- And I execute the "session:property:remove /tests_general_base/idExample/jcr:content/foo" command
+ Given I execute the "session:property:remove /cms/articles/article1/title" command
Then the command should not fail
And I save the session
- And there should not exist a property at "/tests_general_base/idExample/jcr:content/foo"
+ And there should not exist a property at "/cms/articles/article1/title"
Scenario: Try and remove a node
And I execute the "session:property:remove /tests_general_base" command
diff --git a/features/workspace_create.feature b/features/workspace_create.feature
index 93bfdc4d..675515eb 100644
--- a/features/workspace_create.feature
+++ b/features/workspace_create.feature
@@ -5,9 +5,11 @@ Feature: Create a new workspace
Background:
Given that I am logged in as "testuser"
- And there does not exist a workspace called "footest"
- Scenario: Create a workspace
- Given I execute the "workspace:create footest" command
- Then the command should not fail
- And there should exist a workspace called "test"
+ # Jackrabbit does not allow dropping workspaces, so we cannot reliably
+ # test creating workspaces.
+ #
+ # Scenario: Create a workspace
+ # Given I execute the "workspace:create footest" command
+ # Then the command should not fail
+ # And there should exist a workspace called "test"
diff --git a/features/workspace_delete.feature b/features/workspace_delete.feature
index 05e369de..51765ffb 100644
--- a/features/workspace_delete.feature
+++ b/features/workspace_delete.feature
@@ -9,5 +9,8 @@ Feature: Delete a workspace
Scenario: Delete a workspace
Given there exists a workspace "test"
And I execute the "workspace:delete test" command
- Then the command should not fail
- And there should not exist a workspace called "test"
+ Then the command should fail
+ And I should see the following:
+ """
+ Can not delete a workspace as jackrabbit can not do it
+ """
diff --git a/features/workspace_node_clone.feature b/features/workspace_node_clone.feature
index d32f46a3..64551500 100644
--- a/features/workspace_node_clone.feature
+++ b/features/workspace_node_clone.feature
@@ -5,22 +5,22 @@ Feature: Clone a node from a given workspace to the current workspace
Background:
Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded into a workspace "test"
+ And the current workspace is "default_1"
+ And the "cms.xml" fixtures are loaded
+ And the current workspace is "default"
+ And the "cms.xml" fixtures are loaded
- Scenario: Clone node
- Given the "all_property_types.xml" fixtures are loaded into a workspace "default"
- And I execute the "workspace:node:clone test /tests_general_base/index.txt /index.txt" command
- Then the command should not fail
- And I save the session
- And there should exist a node at "/index.txt"
+ # Scenario: Clone node
+ # Given the current workspace is "default"
+ # And I execute the "workspace:node:clone default_1 /cms/articles/article1 /cms/clone" command
+ # Then the command should not fail
+ # And I save the session
+ # And there should exist a node at "/cms/clone"
Scenario: Clone onto existing
- Given the "session_data.xml" fixtures are loaded into a workspace "default"
- And I execute the "workspace:node:clone test /tests_general_base/index.txt /tests_general_base/index.txt" command
+ Given I execute the "workspace:node:clone default_1 /cms/articles/article1 /cms/articles" command
Then the command should fail
- And there should exist a node at "/tests_general_base/index.txt"
Scenario: Clone onto existing but remove
- Given the "session_data.xml" fixtures are loaded into a workspace "default"
- And I execute the "workspace:node:clone --remove-existing test / /" command
+ Given I execute the "workspace:node:clone --remove-existing default_1 /cms/articles/article1 /cms/articles/article1" command
Then the command should not fail
diff --git a/features/workspace_node_copy.feature b/features/workspace_node_copy.feature
index 11268f32..dea07b62 100644
--- a/features/workspace_node_copy.feature
+++ b/features/workspace_node_copy.feature
@@ -5,8 +5,11 @@ Feature: Copy a node from a given workspace to the current workspace
Background:
Given that I am logged in as "testuser"
- And the "session_data.xml" fixtures are loaded into a workspace "test"
- And the "all_property_types.xml" fixtures are loaded into a workspace "default"
+ And the current workspace is "default_1"
+ And the "session_data.xml" fixtures are loaded
+ And the "all_property_types.xml" fixtures are loaded
+ And the current workspace is "default"
+ And I purge the current workspace
Scenario: Copy node from a different workspace
Given I execute the "workspace:node:copy /tests_general_base/index.txt /index.txt test" command
diff --git a/features/workspace_use.feature b/features/workspace_use.feature
new file mode 100644
index 00000000..c9e6d226
--- /dev/null
+++ b/features/workspace_use.feature
@@ -0,0 +1,17 @@
+Feature: Switch to given workspace
+ In order to change the current workspace
+ As a user logged into the shell
+ I want to execute a commad that does that
+
+ Background:
+ Given that I am logged in as "testuser"
+ And there exists a workspace "foobar"
+
+ Scenario: List workspaces
+ Given I execute the "workspace:use foobar" command
+ Then the command should not fail
+ And I execute the "session:info" command
+ Then I should see the following:
+ """
+ foobar
+ """
diff --git a/src/PHPCR/Shell/Console/Application/ShellApplication.php b/src/PHPCR/Shell/Console/Application/ShellApplication.php
index abbea9f6..67f591d6 100644
--- a/src/PHPCR/Shell/Console/Application/ShellApplication.php
+++ b/src/PHPCR/Shell/Console/Application/ShellApplication.php
@@ -29,6 +29,7 @@
use PHPCR\Shell\Console\Command\SessionExportViewCommand;
use PHPCR\Shell\Console\Command\SessionImportXMLCommand;
use PHPCR\Shell\Console\Command\SessionInfoCommand;
+use PHPCR\Shell\Console\Command\SessionLoginCommand;
use PHPCR\Shell\Console\Command\SessionLogoutCommand;
use PHPCR\Shell\Console\Command\SessionNamespaceListCommand;
use PHPCR\Shell\Console\Command\SessionNamespaceSetCommand;
@@ -71,8 +72,10 @@
use PHPCR\Shell\Console\Command\VersionRemoveCommand;
use PHPCR\Shell\Console\Command\VersionCheckpointCommand;
use PHPCR\Shell\Console\Command\NodeCreateCommand;
+use PHPCR\Shell\Console\Command\NodeCorrespondingCommand;
use PHPCR\Shell\Console\Command\NodeDefinitionCommand;
use PHPCR\Shell\Console\Command\NodeSetCommand;
+use PHPCR\Shell\Console\Command\NodeSetPrimaryTypeCommand;
use PHPCR\Shell\Console\Command\NodeRenameCommand;
use PHPCR\Shell\Console\Command\NodeMixinAddCommand;
use PHPCR\Shell\Console\Command\NodeMixinRemoveCommand;
@@ -80,6 +83,7 @@
use PHPCR\Shell\Console\Command\NodeLifecycleFollowCommand;
use PHPCR\Shell\Console\Command\NodeLifecycleListCommand;
use PHPCR\Shell\Console\Command\NodeListCommand;
+use PHPCR\Shell\Console\Command\NodeUpdateCommand;
use PHPCR\Shell\Console\Command\NodeReferencesCommand;
use PHPCR\Shell\Console\Command\NodeSharedShowCommand;
use PHPCR\Shell\Console\Command\NodeSharedRemoveCommand;
@@ -138,15 +142,15 @@ public function init()
$this->transports[$transport->getName()] = $transport;;
}
- $session = $this->getSession($this->sessionInput);
+ $session = $this->initSession();
- $this->getHelperSet()->set(new EditorHelper($session));
+ $this->getHelperSet()->set(new EditorHelper($this->session));
$this->getHelperSet()->set(new PhpcrConsoleDumperHelper());
- $this->getHelperSet()->set(new PhpcrHelper($session));
+ $this->getHelperSet()->set(new PhpcrHelper($this->session));
$this->getHelperSet()->set(new ResultFormatterHelper());
$this->getHelperSet()->set(new TextHelper());
- $this->getHelperSet()->set(new NodeHelper($session));
- $this->getHelperSet()->set(new RepositoryHelper($session->getRepository()));
+ $this->getHelperSet()->set(new NodeHelper($this->session));
+ $this->getHelperSet()->set(new RepositoryHelper($this->session->getRepository()));
// add new commands
$this->add(new AccessControlPrivilegeListCommand());
@@ -155,6 +159,7 @@ public function init()
$this->add(new SessionImpersonateCommand());
$this->add(new SessionImportXMLCommand());
$this->add(new SessionInfoCommand());
+ $this->add(new SessionLoginCommand());
$this->add(new SessionLogoutCommand());
$this->add(new SessionNamespaceListCommand());
$this->add(new SessionNamespaceSetCommand());
@@ -193,8 +198,10 @@ public function init()
$this->add(new VersionCheckpointCommand());
$this->add(new VersionCheckinCommand());
$this->add(new NodeCreateCommand());
+ $this->add(new NodeCorrespondingCommand());
$this->add(new NodeDefinitionCommand());
$this->add(new NodeSetCommand());
+ $this->add(new NodeSetPrimaryTypeCommand());
$this->add(new NodeRenameCommand());
$this->add(new NodeMixinAddCommand());
$this->add(new NodeMixinRemoveCommand());
@@ -202,6 +209,7 @@ public function init()
$this->add(new NodeLifecycleFollowCommand());
$this->add(new NodeLifecycleListCommand());
$this->add(new NodeListCommand());
+ $this->add(new NodeUpdateCommand());
$this->add(new NodeReferencesCommand());
$this->add(new NodeSharedShowCommand());
$this->add(new NodeSharedRemoveCommand());
@@ -284,6 +292,18 @@ public function changeWorkspace($workspaceName)
$this->initSession($this->sessionInput);
}
+ public function relogin($username, $password, $workspaceName = null)
+ {
+ $this->session->logout();
+ $this->sessionInput->setOption('phpcr-username', $username);
+ $this->sessionInput->setOption('phpcr-password', $password);
+
+ if ($workspaceName) {
+ $this->sessionInput->setOption('phpcr-workspace', $workspaceName);
+ }
+ $this->initSession($this->sessionInput);
+ }
+
private function getTransport(InputInterface $input)
{
$transportName = $input->getOption('transport');
@@ -360,4 +380,17 @@ public function renderException($e, $output)
$output->writeln(sprintf('%s', $e->getMessage()));
} while ($e = $e->getPrevious());
}
+
+ public function add(Command $command)
+ {
+ if ($command instanceof PhpcrShellCommand) {
+ $showUnsupported = $this->sessionInput->getOption('unsupported');
+
+ if ($showUnsupported || $command->isSupported($this->getHelperSet()->get('repository'))) {
+ return parent::add($command);
+ }
+ } else {
+ parent::add($command);
+ }
+ }
}
diff --git a/src/PHPCR/Shell/Console/Command/NodeCorrespondingCommand.php b/src/PHPCR/Shell/Console/Command/NodeCorrespondingCommand.php
new file mode 100644
index 00000000..54d3ece6
--- /dev/null
+++ b/src/PHPCR/Shell/Console/Command/NodeCorrespondingCommand.php
@@ -0,0 +1,37 @@
+setName('node:corresponding');
+ $this->setDescription('Show the path for the current nodes corresponding path in named workspace');
+ $this->addArgument('workspaceName', InputArgument::REQUIRED, 'The name of the workspace');
+ $this->setHelp(<<getHelper('phpcr')->getSession();
+ $workspaceName = $input->getArgument('workspaceName');
+ $currentNode = $session->getCurrentNode();
+ $correspondingPath = $currentNode->getCorrespondingNodePath($workspaceName);
+ $output->writeln($correspondingPath);
+ }
+}
diff --git a/src/PHPCR/Shell/Console/Command/NodeListCommand.php b/src/PHPCR/Shell/Console/Command/NodeListCommand.php
index 1de31c65..807cb8f3 100644
--- a/src/PHPCR/Shell/Console/Command/NodeListCommand.php
+++ b/src/PHPCR/Shell/Console/Command/NodeListCommand.php
@@ -82,7 +82,7 @@ private function renderProperties($currentNode, $table)
$table->addRow(array(
'' . $name . '',
'' . $this->formatter->getPropertyTypeName($property->getType()) . '',
- '' . $this->textHelper->truncate($this->formatter->formatValue($property), 55) . '',
+ $this->textHelper->truncate($this->formatter->formatValue($property), 55),
));
}
}
diff --git a/src/PHPCR/Shell/Console/Command/NodeSetPrimaryTypeCommand.php b/src/PHPCR/Shell/Console/Command/NodeSetPrimaryTypeCommand.php
new file mode 100644
index 00000000..866df51b
--- /dev/null
+++ b/src/PHPCR/Shell/Console/Command/NodeSetPrimaryTypeCommand.php
@@ -0,0 +1,43 @@
+setName('node:set-primary-type');
+ $this->setDescription('Set the primary type of the current node');
+ $this->addArgument('nodeTypeName', null, InputArgument::REQUIRED, null, 'New primary node type name');
+ $this->setHelp(<<getHelper('phpcr')->getSession();
+ $nodeTypeName = $input->getArgument('nodeTypeName');
+
+ $currentNode = $session->getCurrentNode();
+ $currentNode->setPrimaryType($nodeTypeName);
+ }
+}
diff --git a/src/PHPCR/Shell/Console/Command/NodeUpdateCommand.php b/src/PHPCR/Shell/Console/Command/NodeUpdateCommand.php
new file mode 100644
index 00000000..3f2e540e
--- /dev/null
+++ b/src/PHPCR/Shell/Console/Command/NodeUpdateCommand.php
@@ -0,0 +1,47 @@
+setName('node:update');
+ $this->setDescription('Updates a node corresponding to the current one in the given workspace');
+ $this->addArgument('srcWorkspace', null, InputArgument::REQUIRED, 'The name of the source workspace');
+ $this->setHelp(<<getHelper('phpcr')->getSession();
+ $srcWorkspace = $input->getArgument('srcWorkspace');
+ $currentNode = $session->getCurrentNode();
+ $currentNode->update($srcWorkspace);
+ }
+}
diff --git a/src/PHPCR/Shell/Console/Command/PhpcrShellCommand.php b/src/PHPCR/Shell/Console/Command/PhpcrShellCommand.php
index b682b8cd..1c33712e 100644
--- a/src/PHPCR/Shell/Console/Command/PhpcrShellCommand.php
+++ b/src/PHPCR/Shell/Console/Command/PhpcrShellCommand.php
@@ -3,6 +3,7 @@
namespace PHPCR\Shell\Console\Command;
use Symfony\Component\Console\Command\Command;
+use PHPCR\Shell\Console\Helper\RepositoryHelper;
class PhpcrShellCommand extends Command
{
@@ -19,17 +20,27 @@ public function dequiresDescriptor($descriptorKey, $value = null)
$this->descriptorDequires[$descriptorKey] = $value;
}
- public function isEnabled()
+ public function getDescriptorRequires()
+ {
+ return $this->descriptorRequires;
+ }
+
+ public function getDescriptorDequires()
+ {
+ return $this->descriptorDequires;
+ }
+
+ public function isSupported(RepositoryHelper $repositoryHelper)
{
foreach ($this->descriptorRequires as $key => $value) {
- $has = $this->getHelper('repository')->hasDescriptor($key, $value);
+ $has = $repositoryHelper->hasDescriptor($key, $value);
if (!$has) {
return false;
}
}
foreach ($this->descriptorDequires as $key => $value) {
- $has = $this->getHelper('repository')->hasDescriptor($key, $value);
+ $has = $repositoryHelper->hasDescriptor($key, $value);
if ($has) {
return false;
@@ -38,4 +49,10 @@ public function isEnabled()
return true;
}
+
+ public function getDescriptor()
+ {
+
+ return true;
+ }
}
diff --git a/src/PHPCR/Shell/Console/Command/SessionLoginCommand.php b/src/PHPCR/Shell/Console/Command/SessionLoginCommand.php
new file mode 100644
index 00000000..ed519490
--- /dev/null
+++ b/src/PHPCR/Shell/Console/Command/SessionLoginCommand.php
@@ -0,0 +1,31 @@
+setName('session:login');
+ $this->setDescription('Login or (relogin) to a session');
+ $this->addArgument('userId', InputArgument::REQUIRED, 'Unique identifier of user');
+ $this->addArgument('password', InputArgument::REQUIRED, 'Password');
+ $this->addArgument('workspaceName', InputArgument::OPTIONAL, 'Optional workspace name');
+ $this->setHelp(<<getArgument('userId');
+ $password = $input->getArgument('password');
+ $workspaceName = $input->getArgument('workspaceName');
+ $this->getApplication()->relogin($username, $password, $workspaceName);
+ }
+}
diff --git a/src/PHPCR/Shell/Console/Command/ShellCommand.php b/src/PHPCR/Shell/Console/Command/ShellCommand.php
index 63ec3962..c93e4a97 100644
--- a/src/PHPCR/Shell/Console/Command/ShellCommand.php
+++ b/src/PHPCR/Shell/Console/Command/ShellCommand.php
@@ -42,6 +42,7 @@ public function configure()
new InputOption('--db-driver', '-dd', InputOption::VALUE_REQUIRED, 'Database Transport.', 'pdo_mysql'),
new InputOption('--db-path', '-dP', InputOption::VALUE_REQUIRED, 'Database Path.'),
new InputOption('--no-interaction', null, InputOption::VALUE_NONE, 'Turn off interaction (for testing purposes)'),
+ new InputOption('--unsupported', null, InputOption::VALUE_NONE, 'Show all commands, including commands not supported by the repository'),
new InputOption('--repo-url', '-url', InputOption::VALUE_REQUIRED, 'URL of repository (e.g. for jackrabbit).',
'http://localhost:8080/server/'
),
diff --git a/src/PHPCR/Shell/Console/Command/WorkspaceNodeCloneCommand.php b/src/PHPCR/Shell/Console/Command/WorkspaceNodeCloneCommand.php
index 60ee7a34..cbdcc596 100644
--- a/src/PHPCR/Shell/Console/Command/WorkspaceNodeCloneCommand.php
+++ b/src/PHPCR/Shell/Console/Command/WorkspaceNodeCloneCommand.php
@@ -57,11 +57,13 @@ protected function configure()
public function execute(InputInterface $input, OutputInterface $output)
{
$session = $this->getHelper('phpcr')->getSession();
+ $srcWorkspace = $input->getArgument('srcWorkspace');
$srcAbsPath = $input->getArgument('srcAbsPath');
$destAbsPath = $input->getArgument('destAbsPath');
- $srcWorkspace = $input->getArgument('srcWorkspace');
$removeExisting = $input->getOption('remove-existing');
+ // todo: Check to ensure that source node has the referenceable mixin
+
$workspace = $session->getWorkspace();
$workspace->cloneFrom($srcWorkspace, $srcAbsPath, $destAbsPath, $removeExisting);
}
diff --git a/tests/PHPCR/Shell/Application/ShellApplicationTest.php b/tests/PHPCR/Shell/Application/ShellApplicationTest.php
index ef7dd9a3..1395f1ef 100644
--- a/tests/PHPCR/Shell/Application/ShellApplicationTest.php
+++ b/tests/PHPCR/Shell/Application/ShellApplicationTest.php
@@ -12,9 +12,6 @@ public function setUp()
$this->transport = $this->getMock(
'PHPCR\Shell\Console\TransportInterface'
);
- $this->transport->expects($this->once())
- ->method('getName')
- ->will($this->returnValue('test'));
$this->sessionInput = $this->getMock(
'Symfony\Component\Console\Input\InputInterface'
@@ -39,15 +36,9 @@ public function setUp()
$this->repository = $this->getMock(
'PHPCR\RepositoryInterface'
);
- $this->repository->expects($this->once())
- ->method('login')
- ->will($this->returnValue($this->session));
-
- $this->transport->expects($this->once())
- ->method('getRepository')
- ->will($this->returnValue($this->repository));
$this->application = new ShellApplication('phpcr','v0.test', $this->sessionInput, array($this->transport));
+ $this->application->setSessionInput($this->sessionInput);
$this->application->setAutoExit(false);
}
diff --git a/tests/PHPCR/Shell/Helper/RepositoryHelperTest.php b/tests/PHPCR/Shell/Helper/RepositoryHelperTest.php
new file mode 100644
index 00000000..76cd83a6
--- /dev/null
+++ b/tests/PHPCR/Shell/Helper/RepositoryHelperTest.php
@@ -0,0 +1,61 @@
+repository = $this->getMock('PHPCR\RepositoryInterface');
+ $this->helper = new RepositoryHelper($this->repository);
+ }
+
+ public function testHasDescriptor()
+ {
+ $descriptors = array(
+ 'foobar' => true,
+ 'barfoo' => true,
+ 'zoobar' => false,
+ 'true' => 'true',
+ 'false' => 'false',
+ );
+
+ $this->repository->expects($this->once())
+ ->method('getDescriptorKeys')
+ ->will($this->returnValue(array_keys($descriptors)));
+
+ $this->repository->expectS($this->any())
+ ->method('getDescriptor')
+ ->will($this->returnCallback(function ($k) use ($descriptors) {
+ return $descriptors[$k];
+ }));
+
+ $res = $this->helper->hasDescriptor('zoobar', false);
+ $this->assertTrue($res);
+
+ $res = $this->helper->hasDescriptor('foobar');
+ $this->assertTrue($res);
+
+ $res = $this->helper->hasDescriptor('asdasd');
+ $this->assertFalse($res);
+
+ $res = $this->helper->hasDescriptor('');
+ $this->assertFalse($res);
+
+ $res = $this->helper->hasDescriptor('foobar', 'asdasd');
+ $this->assertFalse($res);
+
+ $res = $this->helper->hasDescriptor('true', true);
+ $this->assertTrue($res);
+
+ $res = $this->helper->hasDescriptor('false', false);
+ $this->assertTrue($res);
+ }
+}
+