Add support for manually managing the RestDocumentationContext
In 1.0, the reliance on JUnit was more widespread than it should have been. It should have been isolated to the JUnit TestRule implementation, RestDocumentation. Unfortunately, RestDocumentation was also an argument to MockMvcRestDocumentation.documentationConfiguration which made it impossible to use Spring REST Docs without having JUnit on the classpath. This commit introduces JUnitRestDocumentation and ManualRestDocumentation. The format is a direct replacement for RestDocumentation which has been reworked to delegate to JUnitRestDocumentation. The latter allows manual management of the RestDocumentationContext, primarily for use with TestNG. A new interface, RestDocumentationContextProvider, has been introduced. It is implemented by RestDocumentation, JUnitRestDocumentation and ManualRestDocumentation. MockMvcRestDocumentation.documentationConfiguration has been overridden to also accept a RestDocumentationContextProvider. The method that accepts a RestDocumentation has been deprecated, as has RestDocumentation itself. The documentation has been updated to encourage the use of JUnitRestDocumentation and a sample illustrating the use of Spring REST Docs with TestNG has been added. Closes gh-171
This commit is contained in:
@@ -203,7 +203,7 @@ from where it will be included in the jar file.
|
||||
|
||||
[[getting-started-documentation-snippets]]
|
||||
=== Generating documentation snippets
|
||||
Spring REST Docs uses JUnit and
|
||||
Spring REST Docs uses
|
||||
{spring-framework-docs}/#spring-mvc-test-framework[Spring's MVC Test framework] or
|
||||
http://www.rest-assured.io[REST Assured] to make requests to the service that you are
|
||||
documenting. It then produces documentation snippets for the request and the resulting
|
||||
@@ -214,11 +214,18 @@ response.
|
||||
[[getting-started-documentation-snippets-setup]]
|
||||
==== Setting up your tests
|
||||
|
||||
The first step in generating documentation snippets is to declare a `public`
|
||||
`RestDocumentation` field that's annotated as a JUnit `@Rule`. The `RestDocumentation`
|
||||
rule is configured with the output directory into which generated snippets should be
|
||||
written. This output directory should match the snippets directory that you have
|
||||
configured in your `build.gradle` or `pom.xml` file.
|
||||
Exactly how you setup your tests depends on the test framework that you're using.
|
||||
Spring REST Docs provides first-class support for JUnit. Other frameworks, such as TestNG,
|
||||
are also supported although slightly more setup is required.
|
||||
|
||||
[[getting-started-documentation-snippets-setup-junit]]
|
||||
===== Setting up your JUnit tests
|
||||
|
||||
When using JUnit, the first step in generating documentation snippets is to declare a
|
||||
`public` `JUnitRestDocumentation` field that's annotated as a JUnit `@Rule`. The
|
||||
`JUnitRestDocumentation` rule is configured with the output directory into which generated
|
||||
snippets should be written. This output directory should match the snippets directory that
|
||||
you have configured in your `build.gradle` or `pom.xml` file.
|
||||
|
||||
For Maven (`pom.xml` that will typically be `target/generated-snippets` and for
|
||||
Gradle (`build.gradle`) it will typically be `build/generated-snippets`:
|
||||
@@ -227,14 +234,16 @@ Gradle (`build.gradle`) it will typically be `build/generated-snippets`:
|
||||
.Maven
|
||||
----
|
||||
@Rule
|
||||
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
|
||||
public JUnitRestDocumentation restDocumentation =
|
||||
new JUnitRestDocumentation("target/generated-snippets");
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
@Rule
|
||||
public RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
|
||||
public JUnitRestDocumentation restDocumentation =
|
||||
new JUnitRestDocumentation("build/generated-snippets");
|
||||
----
|
||||
|
||||
Next, provide an `@Before` method to configure MockMvc or REST Assured:
|
||||
@@ -263,6 +272,54 @@ configuration. Refer to the <<configuration, configuration section>> for more in
|
||||
|
||||
|
||||
|
||||
===== Setting up your tests without JUnit
|
||||
[[getting-started-documentation-snippets-setup-manual]]
|
||||
|
||||
The configuration when JUnit is not being used is largely similar to when it is being
|
||||
used. This section describes the key differences. The {samples}/testng[TestNG sample] also
|
||||
illustrates the approach.
|
||||
|
||||
The first difference is that `ManualRestDocumentation` should be used in place of
|
||||
`JUnitRestDocumentation` and there's no need for the `@Rule` annotation:
|
||||
|
||||
[source,java,indent=0,role="primary"]
|
||||
.Maven
|
||||
----
|
||||
private ManualRestDocumentation restDocumentation =
|
||||
new ManualRestDocumentation("target/generated-snippets");
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
private ManualRestDocumentation restDocumentation =
|
||||
new ManualRestDocumentation("build/generated-snippets");
|
||||
----
|
||||
|
||||
Secondly, `ManualRestDocumentation.beforeTest(Class, String)`
|
||||
must be called before each test. This can be done as part of the method that is
|
||||
configuring MockMVC or REST Assured:
|
||||
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/mockmvc/ExampleApplicationTestNgTests.java[tags=setup]
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/ExampleApplicationTestNgTests.java[tags=setup]
|
||||
----
|
||||
|
||||
Lastly, `ManualRestDocumentation.afterTest` must be called after each test. For example,
|
||||
with TestNG:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/ExampleApplicationTestNgTests.java[tags=teardown]
|
||||
----
|
||||
|
||||
[[getting-started-documentation-snippets-invoking-the-service]]
|
||||
==== Invoking the RESTful service
|
||||
|
||||
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.curl.CurlDocumentation.curlRequest;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.restdocs.curl.CurlDocumentation.curlRequest;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomDefaultSnippets {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomEncoding {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomFormat {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomUriConfiguration {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.mockmvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
@@ -38,7 +39,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
public class EveryTestPreprocessing {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(
|
||||
"target/generated-snippets");
|
||||
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 com.example.mockmvc;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.ManualRestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class ExampleApplicationTestNgTests {
|
||||
|
||||
public final ManualRestDocumentation restDocumentation = new ManualRestDocumentation(
|
||||
"target/generated-snippets");
|
||||
// tag::setup[]
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp(Method method) {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
this.restDocumentation.beforeTest(getClass(), method.getName());
|
||||
}
|
||||
|
||||
// end::setup[]
|
||||
|
||||
// tag::teardown[]
|
||||
@AfterMethod
|
||||
public void tearDown() {
|
||||
this.restDocumentation.afterTest();
|
||||
}
|
||||
// end::teardown[]
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ package com.example.mockmvc;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
@@ -29,7 +29,7 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.docu
|
||||
public class ExampleApplicationTests {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(
|
||||
"target/generated-snippets");
|
||||
// tag::setup[]
|
||||
@Autowired
|
||||
@@ -44,4 +44,5 @@ public class ExampleApplicationTests {
|
||||
.build();
|
||||
}
|
||||
// end::setup[]
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.mockmvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
@@ -29,7 +30,7 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.docu
|
||||
public class ParameterizedOutput {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
public class Payload {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
private MockMvc mockMvc;
|
||||
|
||||
public void response() throws Exception {
|
||||
// tag::response[]
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
@@ -29,9 +30,9 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class CustomDefaultSnippets {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
RequestSpecification spec;
|
||||
private RequestSpecification spec;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
@@ -28,7 +29,7 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class CustomEncoding {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
|
||||
@@ -29,7 +30,7 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class CustomFormat {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.restassured.RestDocumentationFilter;
|
||||
|
||||
@@ -38,7 +39,7 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class EveryTestPreprocessing {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(
|
||||
"target/generated-snippets");
|
||||
|
||||
// tag::setup[]
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 com.example.restassured;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.restdocs.ManualRestDocumentation;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class ExampleApplicationTestNgTests {
|
||||
|
||||
private final ManualRestDocumentation restDocumentation = new ManualRestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
// tag::setup[]
|
||||
private RequestSpecification spec;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp(Method method) {
|
||||
this.spec = new RequestSpecBuilder().addFilter(
|
||||
documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
this.restDocumentation.beforeTest(getClass(), method.getName());
|
||||
}
|
||||
|
||||
// end::setup[]
|
||||
|
||||
// tag::teardown[]
|
||||
@AfterMethod
|
||||
public void tearDown() {
|
||||
this.restDocumentation.afterTest();
|
||||
}
|
||||
// end::teardown[]
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
@@ -28,7 +29,7 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class ExampleApplicationTests {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
// tag::setup[]
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
@@ -29,7 +30,7 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
public class ParameterizedOutput {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
Reference in New Issue
Block a user