Arsnael commented on code in PR #1277:
URL: https://github.com/apache/james-project/pull/1277#discussion_r1009142836


##########
server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaQueryMethodContract.scala:
##########
@@ -0,0 +1,852 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.rfc8621.contract
+
+import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
+import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.http.ContentType.JSON
+import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import org.apache.http.HttpStatus.SC_OK
+import org.apache.james.GuiceJamesServer
+import org.apache.james.core.quota.{QuotaCountLimit, QuotaSizeLimit}
+import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
+import org.apache.james.jmap.http.UserCredential
+import 
org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, 
ANDRE, ANDRE_PASSWORD, BOB, BOB_PASSWORD, DOMAIN, authScheme, 
baseRequestSpecBuilder}
+import org.apache.james.mailbox.model.MailboxPath
+import org.apache.james.modules.QuotaProbesImpl
+import org.apache.james.utils.DataProbeImpl
+import org.awaitility.Awaitility
+import org.junit.jupiter.api.{BeforeEach, Test}
+
+import java.time.Duration
+import java.util.concurrent.TimeUnit
+
+trait QuotaQueryMethodContract {
+
+  private lazy val awaitAtMostTenSeconds = Awaitility.`with`
+    .await
+    .pollInterval(Duration.ofMillis(100))
+    .atMost(10, TimeUnit.SECONDS)
+
+  @BeforeEach
+  def setUp(server: GuiceJamesServer): Unit = {
+    server.getProbe(classOf[DataProbeImpl])
+      .fluent
+      .addDomain(DOMAIN.asString)
+      .addUser(BOB.asString, BOB_PASSWORD)
+      .addUser(ANDRE.asString, ANDRE_PASSWORD)
+
+    requestSpecification = baseRequestSpecBuilder(server)
+      .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD)))
+      .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .build
+  }
+
+  @Test
+  def queryShouldSuccessByDefault(): Unit = {
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {}
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "00000000",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def queryShouldReturnAllWhenFilterIsEmpty(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {}
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "a06886ff",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"08417be420b6dd6fa77d48fb2438e0d19108cd29424844bb109b52d356fab528",
+         |                    
"eab6ce8ac5d9730a959e614854410cf39df98ff3760a623b8e540f36f5184947"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterResourceTypesShouldWork(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "resourceTypes": ["count"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "d8d3e770",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"08417be420b6dd6fa77d48fb2438e0d19108cd29424844bb109b52d356fab528"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterResourceTypesShoulFailWhenInvalidResourceTypes(server: 
GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "resourceTypes": ["invalid"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "error",
+         |            {
+         |                "type": "invalidArguments",
+         |                "description": 
"{\\"errors\\":[{\\"path\\":\\"obj.filter.resourceTypes[0]\\",\\"messages\\":[\\"Expecting
 a JsString to represent a resourceType property\\"]}]}"
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterDataTypesShouldWork(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "dataTypes": ["Mail"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "a06886ff",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"08417be420b6dd6fa77d48fb2438e0d19108cd29424844bb109b52d356fab528",
+         |                    
"eab6ce8ac5d9730a959e614854410cf39df98ff3760a623b8e540f36f5184947"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterDataTypesShouldFailWhenInvalidDataTypes(server: GuiceJamesServer): 
Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "dataTypes": ["invalid"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "error",
+         |            {
+         |                "type": "invalidArguments",
+         |                "description": 
"{\\"errors\\":[{\\"path\\":\\"obj.filter.dataTypes[0]\\",\\"messages\\":[\\"Expecting
 a JsString to represent a dataType property\\"]}]}"
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterScopeShouldWork(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "scope": ["account"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "a06886ff",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"08417be420b6dd6fa77d48fb2438e0d19108cd29424844bb109b52d356fab528",
+         |                    
"eab6ce8ac5d9730a959e614854410cf39df98ff3760a623b8e540f36f5184947"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterScopeShouldFailWhenInvalidScope(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "scope": ["invalidScope"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "error",
+         |            {
+         |                "type": "invalidArguments",
+         |                "description": 
"{\\"errors\\":[{\\"path\\":\\"obj.filter.scope[0]\\",\\"messages\\":[\\"Expecting
 a JsString to represent a scope property\\"]}]}"
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterQuotaNameShouldWork(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "name": 
"#private&[email protected]@domain.tld:account:octets:Mail"
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "6cacd8a2",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"eab6ce8ac5d9730a959e614854410cf39df98ff3760a623b8e540f36f5184947"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterQuotaNameShouldReturnEmptyResultWhenNameIsNotFound(server: 
GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "name": "notFound"
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "00000000",
+         |                "canCalculateChanges": false,
+         |                "ids": [],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterMultiPropertyShouldWork(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "name": 
"#private&[email protected]@domain.tld:account:octets:Mail",
+           |        "dataTypes": ["Mail"],
+           |        "scope": ["account"],
+           |        "resourceTypes": ["octets"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "6cacd8a2",
+         |                "canCalculateChanges": false,
+         |                "ids": [
+         |                    
"eab6ce8ac5d9730a959e614854410cf39df98ff3760a623b8e540f36f5184947"
+         |                ],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterShouldBeANDLogic(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "name": 
"#private&[email protected]@domain.tld:account:octets:Mail",
+           |        "resourceTypes": ["count"]
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "Quota/query",
+         |            {
+         |                "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "queryState": "00000000",
+         |                "canCalculateChanges": false,
+         |                "ids": [],
+         |                "position": 0,
+         |                "limit": 256
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def filterShouldFailWhenInvalidFilter(server: GuiceJamesServer): Unit = {
+    val quotaProbe = server.getProbe(classOf[QuotaProbesImpl])
+    val bobQuotaRoot = quotaProbe.getQuotaRoot(MailboxPath.inbox(BOB))
+    quotaProbe.setMaxMessageCount(bobQuotaRoot, QuotaCountLimit.count(100L))
+    quotaProbe.setMaxStorage(bobQuotaRoot, QuotaSizeLimit.size(99L))
+
+    val response = `given`
+      .body(
+        s"""{
+           |  "using": [
+           |    "urn:ietf:params:jmap:core",
+           |    "urn:ietf:params:jmap:quota"],
+           |  "methodCalls": [[
+           |    "Quota/query",
+           |    {
+           |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |      "filter" : {
+           |        "filterName1": "filterValue2"
+           |      }
+           |    },
+           |    "c1"]]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "${SESSION_STATE.value}",
+         |    "methodResponses": [
+         |        [
+         |            "error",
+         |            {
+         |                "type": "invalidArguments",
+         |                "description": 
"{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"These 
'[filterName1]' was unsupported filter options\\"]}]}"
+         |            },
+         |            "c1"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+
+  @Test
+  def quotaQueryShouldFailWhenWrongAccountId(): Unit = {
+    val request =
+      s"""{
+         |  "using": [
+         |    "urn:ietf:params:jmap:core",
+         |    "urn:ietf:params:jmap:quota"],
+         |  "methodCalls": [[
+         |    "Quota/query",
+         |    {
+         |      "accountId": "unknownAccountId",
+         |      "filter": {}
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response = `given`
+      .body(request)
+    .when
+      .post
+    .`then`
+      .log().ifValidationFails()
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |  "sessionState": "${SESSION_STATE.value}",
+         |  "methodResponses": [
+         |    ["error", {
+         |      "type": "accountNotFound"
+         |    }, "c1"]
+         |  ]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def quotaQueryShouldFailWhenOmittingOneCapability(): Unit = {
+    val request =
+      s"""{
+         |  "using": [
+         |    "urn:ietf:params:jmap:core"],
+         |  "methodCalls": [[
+         |    "Quota/query",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "filter": {}
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response = `given`
+      .body(request)
+    .when
+      .post
+    .`then`
+      .log().ifValidationFails()
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |  "sessionState": "${SESSION_STATE.value}",
+         |  "methodResponses": [[
+         |    "error",
+         |    {
+         |      "type": "unknownMethod",
+         |      "description":"Missing capability(ies): 
urn:ietf:params:jmap:quota"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin)
+  }
+
+  @Test
+  def quotaQueryShouldFailWhenOmittingAllCapability(): Unit = {
+    val request =
+      s"""{
+         |  "using": [],
+         |  "methodCalls": [[
+         |    "Quota/query",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "filter": {}
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response = `given`
+      .body(request)
+    .when
+      .post
+    .`then`
+      .log().ifValidationFails()
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |  "sessionState": "${SESSION_STATE.value}",
+         |  "methodResponses": [[
+         |    "error",
+         |    {
+         |      "type": "unknownMethod",
+         |      "description":"Missing capability(ies): 
urn:ietf:params:jmap:quota, urn:ietf:params:jmap:core"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin)
+  }
+}

Review Comment:
   Test with shared mailboxes?
   Test making sure the query does not return somebody else quota?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to