APMT (AEM Permission Matrix Tester) is a tool which speeds up creation of permission tests for application built on top of AEM.
References
Getting started
APMT requires apmt.yaml file, which provides data about admin user, and author and publish instances. Admin doesn't need to be exactly admin user, but it must be the user, who is able to perform all tested actions, and revert them. So when you want to test creation of pages, admin must be able to create page under provided path, and also to delete it.
# Instance configuration --- apmt-user: username: admin password: admin instances: author: name: author@local url: http://localhost:8080 headers: # additional headers sent to server in all requests apmt-header1: apmt-value1 apmt-header2: apmt-value2 publish: name: publish@local url: http://localhost:8080 headers: apmt-header1: apmt-value1 apmt-header2: apmt-value2
The next thing required by APMT is list of users.
package com.cognifide.apmt.tests import com.cognifide.apmt.User enum class Users( override val username: String, override val password: String ) : User { USER("user", "password"), AUTHOR("author", "password"), SUPER_AUTHOR("super-author", "password") }
Finally, you can add permissions tests. Here is more complicated example, test which creates a page.
package com.cognifide.apmt.tests import com.cognifide.apmt.BasicTestCase class CreatePageTest : com.cognifide.apmt.tests.page.CreatePageTest( BasicTestCase { paths( "/content/my-site/en_us/home", "/content/my-site/de_de/home" ) allowedUsers( Users.AUTHOR, Users.SUPER_AUTHOR ) }, pageContent = { jcrTitle = "Example Page" slingResourceType = "apmt/components/testPage" cqTemplate = "apmt/templates/testPage" "apmtType" set "apmtTestPage" } )
And the simplest example, test which opens a page.
package com.cognifide.apmt.tests import com.cognifide.apmt.BasicTestCase class OpenPageTest : com.cognifide.apmt.tests.page.OpenPageTest( BasicTestCase { paths( "/content/my-site/en_us/home", "/content/my-site/en_us/home" ) allowedUsers( *Users.values() ) } )
Alternative enum driven approach
Instead of defining tests cases directly in test class, you may use enum class to define them.
package com.cognifide.apmt.tests import com.cognifide.apmt.TestCase enum class TestCases(private initConfig: TestCase.() -> Unit) : TestCase { CREATE_PAGE({ paths( "/content/my-site/en_us/home", "/content/my-site/de_de/home" ) allowedUsers( Users.AUTHOR, Users.SUPER_AUTHOR ) }), OPEN_PAGE({ paths( "/content/my-site/en_us/home", "/content/my-site/en_us/home" ) allowedUsers( *Users.values() ) }); override var allowedUsers: List<User> = listOf() override var deniedUsers: List<User> = listOf() override var paths: List<String> = listOf() override var allUsers: List<User> = listOf() override var allowedPairsPredicate: ((user: User, path: String) -> Boolean)? = null override var deniedPairsPredicate: ((user: User, path: String) -> Boolean)? = null init { this.apply(initConfig) this.allUsers(ApmtUsers.values()) } }
And here is test class which uses this enum:
package com.cognifide.apmt.tests class CreatePageTest : com.cognifide.apmt.tests.page.CreatePageTest( TestCases.CREATE_PAGE, pageContent = { jcrTitle = "Example Page" slingResourceType = "apmt/components/testPage" cqTemplate = "apmt/templates/testPage" "apmtType" set "apmtTestPage" } )
How does it work?
Let's look at the CREATE_TEST case (it's a little bit modified).
CREATE_PAGE({ paths( "/content/my-site/en_us/home", "/content/my-site/de_de/home" ) allowedUsers( Users.AUTHOR, Users.SUPER_AUTHOR ) allUsers( *Users.values() ) })
CreatePageTest will be executed for each pair of user and path, and users will be spllited for 2 groups:
- Allowed users - users with access to create pages (explicitly defined in section
allowedUsers), - Denied users - users without the access (users defined in
allUserswithout the users fromallowedUsers).
For each group will be executed different test method.
| Access | User | Path |
|---|---|---|
| Denied | USER | /content/my-site/en_us/home |
| Denied | USER | /content/my-site/de_de/home |
| Allowed | AUTHOR | /content/my-site/en_us/home |
| Allowed | AUTHOR | /content/my-site/de_de/home |
| Allowed | SUPER_AUTHOR | /content/my-site/de_de/home |
| Allowed | SUPER_AUTHOR | /content/my-site/de_de/home |
You can use 3 sections to define users groups:
allowedUsersdefine users who can perform actiondeniedUsersdefine users who can not perform actionallUsersused to compute not defined group
allowedUsers(
Users.AUTHOR,
Users.SUPER_AUTHOR
)
deniedUsers(
Users.USER
)
allUsers(
*Users.values()
)Here is table which shows how sections are used to define final groups.
allowedUsers |
deniedUsers |
allUsers |
Allowed users | Denied users |
|---|---|---|---|---|
| definied | allowedUser | |||
| definied | defined | allowedUser | allUsers - allowedUsers | |
| definied | defined | allowedUser | deniedUsers | |
| defined | deniedUsers | |||
| defined | defined | allUsers - deniedUsers | deniedUsers |
You don't need to define allUsers explicitly in each test case. You may define all users in overridden method toTestCaseConfiguration().
override fun toTestCaseConfiguration(): TestCaseConfiguration { val testCaseConfiguration = TestCaseConfiguration().apply(initConfig) testCaseConfiguration.allUsers(Users.values()) return testCaseConfiguration }
Unit tests
If you have some problems with specific tests you can take a look on unit tests which are located in this repository in com.cognifide.apmt.tests package.
Please mind that you are interested only in constructor part.
License
APM is licensed under Apache License, Version 2.0 (the "License")
