This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 01991fdca16d9ef8c8597478f1dd7ddb3ddbe199 Author: duc91 <vdngu...@linagora.com> AuthorDate: Wed Jul 22 10:43:08 2020 +0700 JAMES-3312: Integration test for SessionRoutes --- .../james/jmap/rfc8621/RFC8621MethodsModule.java | 5 +- .../distributed/DistributedSessionRouteTest.java | 52 ++++++++ .../jmap/rfc8621/contract/EchoMethodContract.scala | 4 +- .../rfc8621/contract/SessionRoutesContract.scala} | 132 ++++++++------------- .../rfc8621/memory/MemorySessionRouteTest.java | 38 ++++++ .../org/apache/james/jmap/http/SessionRoutes.scala | 5 +- .../apache/james/jmap/http/SessionRoutesTest.scala | 62 +--------- .../scala/org/apache/james/jmap/json/Fixture.scala | 63 +++++++++- 8 files changed, 209 insertions(+), 152 deletions(-) diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java index 5cd2117..4c856da 100644 --- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java +++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java @@ -24,6 +24,7 @@ import org.apache.james.jmap.JMAPRoutesHandler; import org.apache.james.jmap.Version; import org.apache.james.jmap.http.Authenticator; import org.apache.james.jmap.http.BasicAuthenticationStrategy; +import org.apache.james.jmap.http.SessionRoutes; import org.apache.james.jmap.http.rfc8621.InjectionKeys; import org.apache.james.jmap.json.Serializer; import org.apache.james.jmap.jwt.JWTAuthenticationStrategy; @@ -53,8 +54,8 @@ public class RFC8621MethodsModule extends AbstractModule { } @ProvidesIntoSet - JMAPRoutesHandler routesHandler(JMAPApiRoutes jmapApiRoutes) { - return new JMAPRoutesHandler(Version.RFC8621, jmapApiRoutes); + JMAPRoutesHandler routesHandler(SessionRoutes sessionRoutes, JMAPApiRoutes jmapApiRoutes) { + return new JMAPRoutesHandler(Version.RFC8621, jmapApiRoutes, sessionRoutes); } @Provides diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedSessionRouteTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedSessionRouteTest.java new file mode 100644 index 0000000..ef34f84 --- /dev/null +++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedSessionRouteTest.java @@ -0,0 +1,52 @@ +/**************************************************************** + * 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.distributed; + +import org.apache.james.CassandraExtension; +import org.apache.james.CassandraRabbitMQJamesConfiguration; +import org.apache.james.CassandraRabbitMQJamesServerMain; +import org.apache.james.DockerElasticSearchExtension; +import org.apache.james.JamesServerBuilder; +import org.apache.james.JamesServerExtension; +import org.apache.james.SearchConfiguration; +import org.apache.james.jmap.rfc8621.contract.SessionRoutesContract; +import org.apache.james.modules.AwsS3BlobStoreExtension; +import org.apache.james.modules.RabbitMQExtension; +import org.apache.james.modules.TestJMAPServerModule; +import org.apache.james.modules.blobstore.BlobStoreConfiguration; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class DistributedSessionRouteTest implements SessionRoutesContract { + @RegisterExtension + static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir -> + CassandraRabbitMQJamesConfiguration.builder() + .workingDirectory(tmpDir) + .configurationFromClasspath() + .blobStore(BlobStoreConfiguration.objectStorage().disableCache()) + .searchConfiguration(SearchConfiguration.elasticSearch()) + .build()) + .extension(new DockerElasticSearchExtension()) + .extension(new CassandraExtension()) + .extension(new RabbitMQExtension()) + .extension(new AwsS3BlobStoreExtension()) + .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration) + .overrideWith(new TestJMAPServerModule())) + .build(); +} diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EchoMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EchoMethodContract.scala index 509106d..2306bc7 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EchoMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EchoMethodContract.scala @@ -102,7 +102,7 @@ trait EchoMethodContract { .body(ECHO_REQUEST_OBJECT) .when() .post() - .then + .`then` .statusCode(SC_OK) .contentType(JSON) .extract() @@ -119,7 +119,7 @@ trait EchoMethodContract { .body(REQUEST_OBJECT_WITH_UNSUPPORTED_METHOD) .when() .post() - .then + .`then` .statusCode(SC_OK) .contentType(JSON) .extract() diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala similarity index 64% copy from server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala copy to server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala index dad6b10..2155401 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala @@ -16,91 +16,24 @@ * specific language governing permissions and limitations * * under the License. * * ***************************************************************/ - -package org.apache.james.jmap.http - -import java.nio.charset.StandardCharsets +package org.apache.james.jmap.rfc8621.contract import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT -import io.restassured.RestAssured -import io.restassured.builder.RequestSpecBuilder -import io.restassured.config.EncoderConfig.encoderConfig -import io.restassured.config.RestAssuredConfig.newConfig -import io.restassured.http.ContentType -import org.apache.http.HttpStatus -import org.apache.james.core.Username -import org.apache.james.jmap._ -import org.apache.james.jmap.http.SessionRoutesTest.{BOB, TEST_CONFIGURATION} -import org.apache.james.jmap.json.Serializer -import org.apache.james.mailbox.MailboxSession -import org.apache.james.mailbox.model.TestId -import org.mockito.ArgumentMatchers.any -import org.mockito.Mockito._ -import org.scalatest.BeforeAndAfter -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import play.api.libs.json.Json -import reactor.core.publisher.Mono - -import scala.jdk.CollectionConverters._ - -object SessionRoutesTest { - private val JMAP_SESSION = "/jmap/session" - private val TEST_CONFIGURATION = JMAPConfiguration.builder.enable.randomPort.build - private val BOB = Username.of("b...@james.org") -} - -class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers { - - var jmapServer: JMAPServer = _ +import io.restassured.RestAssured._ +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.jmap.http.UserCredential +import org.apache.james.jmap.rfc8621.contract.Fixture._ +import org.apache.james.jmap.rfc8621.contract.SessionRoutesContract.session_object_json_expected +import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags +import org.apache.james.utils.DataProbeImpl +import org.junit.jupiter.api.{BeforeEach, Tag, Test} +import play.api.libs.json.{JsValue, Json} - before { - val mockedSession = mock(classOf[MailboxSession]) - when(mockedSession.getUser) - .thenReturn(BOB) - - val mockedAuthFilter = mock(classOf[Authenticator]) - when(mockedAuthFilter.authenticate(any())) - .thenReturn(Mono.just(mockedSession)) - - val sessionRoutes = new SessionRoutes( - serializer = new Serializer(new TestId.Factory), - sessionSupplier = new SessionSupplier(), - authenticator = mockedAuthFilter) - jmapServer = new JMAPServer( - TEST_CONFIGURATION, - Set(new JMAPRoutesHandler(Version.RFC8621, sessionRoutes)).asJava, - new VersionParser(Set(Version.RFC8621).asJava)) - jmapServer.start() - - RestAssured.requestSpecification = new RequestSpecBuilder() - .setContentType(ContentType.JSON) - .addHeader(ACCEPT.toString, s"application/json; jmapVersion=${Version.RFC8621.asString}") - .setConfig(newConfig.encoderConfig(encoderConfig.defaultContentCharset(StandardCharsets.UTF_8))) - .setPort(jmapServer.getPort.getValue) - .setBasePath(SessionRoutesTest.JMAP_SESSION) - .build() - } - - after { - jmapServer.stop() - } - - "get" should "return OK status" in { - RestAssured.when() - .get - .then - .statusCode(HttpStatus.SC_OK) - .contentType(ContentType.JSON) - } - - "get" should "return correct session" in { - val sessionJson = RestAssured.`with`() - .get - .thenReturn - .getBody - .asString() - val expectedJson = """{ +object SessionRoutesContract { + private val expected_session_object = """{ | "capabilities" : { | "urn:ietf:params:jmap:core" : { | "maxSizeUpload" : 10000000, @@ -159,7 +92,38 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers { | "eventSourceUrl" : "http://this-url-is-hardcoded.org/eventSource", | "state" : "000001" |}""".stripMargin + private val session_object_json_expected: JsValue = Json.parse(expected_session_object) +} + +trait SessionRoutesContract { - Json.parse(sessionJson) should equal(Json.parse(expectedJson)) + @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))) + .build } -} + + @Test + @Tag(CategoryTags.BASIC_FEATURE) + def getShouldReturnCorrectSession() { + val sessionJson: String = `given`() + .when() + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .get("/session") + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract() + .body() + .asString() + + assertThatJson(Json.parse(sessionJson)).isEqualTo(session_object_json_expected) + } +} \ No newline at end of file diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemorySessionRouteTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemorySessionRouteTest.java new file mode 100644 index 0000000..b4de0c7 --- /dev/null +++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemorySessionRouteTest.java @@ -0,0 +1,38 @@ +/**************************************************************** + * 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.memory; + +import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE; + +import org.apache.james.GuiceJamesServer; +import org.apache.james.JamesServerBuilder; +import org.apache.james.JamesServerExtension; +import org.apache.james.jmap.rfc8621.contract.SessionRoutesContract; +import org.apache.james.modules.TestJMAPServerModule; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class MemorySessionRouteTest implements SessionRoutesContract { + @RegisterExtension + static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider()) + .server(configuration -> GuiceJamesServer.forConfiguration(configuration) + .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE) + .overrideWith(new TestJMAPServerModule())) + .build(); +} diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala index a7efeab..047e8da 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala @@ -42,12 +42,11 @@ import reactor.core.scheduler.Schedulers import reactor.netty.http.server.HttpServerResponse object SessionRoutes { - private val JMAP_SESSION = "/jmap/session" + private val JMAP_SESSION: String = "/jmap/session" private val LOGGER = LoggerFactory.getLogger(classOf[SessionRoutes]) } -@Inject -class SessionRoutes(@Named(InjectionKeys.RFC_8621) val authenticator: Authenticator, +class SessionRoutes @Inject() (@Named(InjectionKeys.RFC_8621) val authenticator: Authenticator, val serializer: Serializer, val sessionSupplier: SessionSupplier = new SessionSupplier()) extends JMAPRoutes { diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala index dad6b10..0501f8b 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala @@ -31,6 +31,7 @@ import org.apache.http.HttpStatus import org.apache.james.core.Username import org.apache.james.jmap._ import org.apache.james.jmap.http.SessionRoutesTest.{BOB, TEST_CONFIGURATION} +import org.apache.james.jmap.json.Fixture.expected_session_object_json import org.apache.james.jmap.json.Serializer import org.apache.james.mailbox.MailboxSession import org.apache.james.mailbox.model.TestId @@ -100,66 +101,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers { .thenReturn .getBody .asString() - val expectedJson = """{ - | "capabilities" : { - | "urn:ietf:params:jmap:core" : { - | "maxSizeUpload" : 10000000, - | "maxConcurrentUpload" : 4, - | "maxSizeRequest" : 10000000, - | "maxConcurrentRequests" : 4, - | "maxCallsInRequest" : 16, - | "maxObjectsInGet" : 500, - | "maxObjectsInSet" : 500, - | "collationAlgorithms" : [ "i;unicode-casemap" ] - | }, - | "urn:ietf:params:jmap:mail" : { - | "maxMailboxesPerEmail" : 10000000, - | "maxMailboxDepth" : null, - | "maxSizeMailboxName" : 200, - | "maxSizeAttachmentsPerEmail" : 20000000, - | "emailQuerySortOptions" : [ "receivedAt", "cc", "from", "to", "subject", "size", "sentAt", "hasKeyword", "uid", "Id" ], - | "mayCreateTopLevelMailbox" : true - | } - | }, - | "accounts" : { - | "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401" : { - | "name" : "b...@james.org", - | "isPersonal" : true, - | "isReadOnly" : false, - | "accountCapabilities" : { - | "urn:ietf:params:jmap:core" : { - | "maxSizeUpload" : 10000000, - | "maxConcurrentUpload" : 4, - | "maxSizeRequest" : 10000000, - | "maxConcurrentRequests" : 4, - | "maxCallsInRequest" : 16, - | "maxObjectsInGet" : 500, - | "maxObjectsInSet" : 500, - | "collationAlgorithms" : [ "i;unicode-casemap" ] - | }, - | "urn:ietf:params:jmap:mail" : { - | "maxMailboxesPerEmail" : 10000000, - | "maxMailboxDepth" : null, - | "maxSizeMailboxName" : 200, - | "maxSizeAttachmentsPerEmail" : 20000000, - | "emailQuerySortOptions" : [ "receivedAt", "cc", "from", "to", "subject", "size", "sentAt", "hasKeyword", "uid", "Id" ], - | "mayCreateTopLevelMailbox" : true - | } - | } - | } - | }, - | "primaryAccounts" : { - | "urn:ietf:params:jmap:core" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401", - | "urn:ietf:params:jmap:mail" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401" - | }, - | "username" : "b...@james.org", - | "apiUrl" : "http://this-url-is-hardcoded.org/jmap", - | "downloadUrl" : "http://this-url-is-hardcoded.org/download", - | "uploadUrl" : "http://this-url-is-hardcoded.org/upload", - | "eventSourceUrl" : "http://this-url-is-hardcoded.org/eventSource", - | "state" : "000001" - |}""".stripMargin - Json.parse(sessionJson) should equal(Json.parse(expectedJson)) + Json.parse(sessionJson) should equal(expected_session_object_json) } } diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala index e249535..278d247 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala @@ -24,7 +24,7 @@ import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier import org.apache.james.jmap.model.Id.Id import org.apache.james.jmap.model.Invocation.{Arguments, MethodCallId, MethodName} import org.apache.james.jmap.model.{ClientId, CreatedIds, Invocation, ResponseObject, ServerId} -import play.api.libs.json.Json +import play.api.libs.json.{JsValue, Json} object Fixture { val id: Id = "aHR0cHM6Ly93d3cuYmFzZTY0ZW5jb2RlLm9yZy8" @@ -47,4 +47,65 @@ object Fixture { val responseObject1: ResponseObject = ResponseObject(ResponseObject.SESSION_STATE, Seq(invocation1)) val responseObject2: ResponseObject = ResponseObject(ResponseObject.SESSION_STATE, Seq(invocation2)) val responseObjectWithUnsupportedMethod: ResponseObject = ResponseObject(ResponseObject.SESSION_STATE, Seq(invocation1, unsupportedInvocation)) + + val expected_session_object: String = """{ + | "capabilities" : { + | "urn:ietf:params:jmap:core" : { + | "maxSizeUpload" : 10000000, + | "maxConcurrentUpload" : 4, + | "maxSizeRequest" : 10000000, + | "maxConcurrentRequests" : 4, + | "maxCallsInRequest" : 16, + | "maxObjectsInGet" : 500, + | "maxObjectsInSet" : 500, + | "collationAlgorithms" : [ "i;unicode-casemap" ] + | }, + | "urn:ietf:params:jmap:mail" : { + | "maxMailboxesPerEmail" : 10000000, + | "maxMailboxDepth" : null, + | "maxSizeMailboxName" : 200, + | "maxSizeAttachmentsPerEmail" : 20000000, + | "emailQuerySortOptions" : [ "receivedAt", "cc", "from", "to", "subject", "size", "sentAt", "hasKeyword", "uid", "Id" ], + | "mayCreateTopLevelMailbox" : true + | } + | }, + | "accounts" : { + | "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401" : { + | "name" : "b...@james.org", + | "isPersonal" : true, + | "isReadOnly" : false, + | "accountCapabilities" : { + | "urn:ietf:params:jmap:core" : { + | "maxSizeUpload" : 10000000, + | "maxConcurrentUpload" : 4, + | "maxSizeRequest" : 10000000, + | "maxConcurrentRequests" : 4, + | "maxCallsInRequest" : 16, + | "maxObjectsInGet" : 500, + | "maxObjectsInSet" : 500, + | "collationAlgorithms" : [ "i;unicode-casemap" ] + | }, + | "urn:ietf:params:jmap:mail" : { + | "maxMailboxesPerEmail" : 10000000, + | "maxMailboxDepth" : null, + | "maxSizeMailboxName" : 200, + | "maxSizeAttachmentsPerEmail" : 20000000, + | "emailQuerySortOptions" : [ "receivedAt", "cc", "from", "to", "subject", "size", "sentAt", "hasKeyword", "uid", "Id" ], + | "mayCreateTopLevelMailbox" : true + | } + | } + | } + | }, + | "primaryAccounts" : { + | "urn:ietf:params:jmap:core" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401", + | "urn:ietf:params:jmap:mail" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401" + | }, + | "username" : "b...@james.org", + | "apiUrl" : "http://this-url-is-hardcoded.org/jmap", + | "downloadUrl" : "http://this-url-is-hardcoded.org/download", + | "uploadUrl" : "http://this-url-is-hardcoded.org/upload", + | "eventSourceUrl" : "http://this-url-is-hardcoded.org/eventSource", + | "state" : "000001" + |}""".stripMargin + val expected_session_object_json: JsValue = Json.parse(expected_session_object) } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org