APMT
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
allUsers
without 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:
allowedUsers
define users who can perform actiondeniedUsers
define users who can not perform actionallUsers
used 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")