diff --git a/er_diagram_shareIt.png b/er_diagram_shareIt.png
index 861fba7..ffa297d 100644
Binary files a/er_diagram_shareIt.png and b/er_diagram_shareIt.png differ
diff --git a/pom.xml b/pom.xml
index fa8a467..2185679 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,7 +37,6 @@
org.postgresql
postgresql
- runtime
@@ -57,11 +56,6 @@
spring-boot-starter-validation
-
- com.h2database
- h2
-
-
org.springframework.boot
spring-boot-starter-data-jpa
diff --git a/postman_for_shareit_15.json b/postman_for_shareit_15.json
new file mode 100644
index 0000000..26845fe
--- /dev/null
+++ b/postman_for_shareit_15.json
@@ -0,0 +1,4811 @@
+{
+ "info": {
+ "_postman_id": "069d256e-037e-4bd9-a5de-be6910726adc",
+ "name": "Sprint 15 ShareIt (add-bookings)",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "23073145",
+ "_collection_link": "https://universal-shadow-295426.postman.co/workspace/My-Workspace~4200f6aa-0504-44b1-8a1d-707d0dcbd5ce/collection/13708500-069d256e-037e-4bd9-a5de-be6910726adc?action=share&source=collection_link&creator=23073145"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "Create user",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " pm.collectionVariables.set(\"userName\", user.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", user.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200 or 201\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/users",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create user without email",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user2 = rnd.getUser();\r",
+ " pm.collectionVariables.set(\"userName\", user2.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", user2.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\"\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/users",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create 2 users with same email",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user1 = rnd.getUser();\r",
+ " us = await api.addUser(user1);\r",
+ " user2 = rnd.getUser();\r",
+ " user2.email = user1.email;\r",
+ " pm.collectionVariables.set(\"userName\", user2.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", user2.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 409\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([409, 500]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/users",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create user with invalid email",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " pm.collectionVariables.set(\"userName\", user.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", user.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"user.com\"\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/users",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "User update",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " pm.collectionVariables.set(\"userId\", us.id);\r",
+ " us = rnd.getUser()\r",
+ " pm.collectionVariables.set(\"userName\", us.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", us.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.be.ok;\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ "pm.test(\"Test user 'id' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('id');\r",
+ " var id = pm.collectionVariables.get(\"userId\");\r",
+ " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(id));\r",
+ "});\r",
+ "pm.test(\"Test user 'email' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('email');\r",
+ " var email = pm.collectionVariables.get(\"userEmail\");\r",
+ " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(email);\r",
+ "});\r",
+ "pm.test(\"Test user 'name' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('name');\r",
+ " var name = pm.collectionVariables.get(\"userName\");\r",
+ " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "User update name",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " pm.collectionVariables.set(\"userId\", us.id);\r",
+ " us = rnd.getUser()\r",
+ " pm.collectionVariables.set(\"userName\", us.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", us.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.be.ok;\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ "pm.test(\"Test user 'id' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('id');\r",
+ " var id = pm.collectionVariables.get(\"userId\");\r",
+ " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(id));\r",
+ "});\r",
+ "pm.test(\"Test user 'name' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('name');\r",
+ " var name = pm.collectionVariables.get(\"userName\");\r",
+ " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "User update email",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " pm.collectionVariables.set(\"userId\", us.id);\r",
+ " us = rnd.getUser()\r",
+ " pm.collectionVariables.set(\"userName\", us.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", us.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.be.ok;\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ "pm.test(\"Test user 'id' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('id');\r",
+ " var id = pm.collectionVariables.get(\"userId\");\r",
+ " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(id));\r",
+ "});\r",
+ "pm.test(\"Test user 'email' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('email');\r",
+ " var email = pm.collectionVariables.get(\"userEmail\");\r",
+ " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(email);\r",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"email\": \"{{userEmail}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "User update with existing email",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " user2 = rnd.getUser();\r",
+ " us2 = await api.addUser(user2)\r",
+ " pm.collectionVariables.set(\"userId\", us2.id);\r",
+ " usa = rnd.getUser()\r",
+ " pm.collectionVariables.set(\"userName\", usa.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", user.email);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 409\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([409, 500]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get user",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " pm.collectionVariables.set(\"userId\", us.id);\r",
+ " pm.collectionVariables.set(\"userName\", us.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", us.email);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.be.ok;\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ "pm.test(\"Test user 'id' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('id');\r",
+ " var id = pm.collectionVariables.get(\"userId\");\r",
+ " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(id));\r",
+ "});\r",
+ "pm.test(\"Test user 'email' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('email');\r",
+ " var email = pm.collectionVariables.get(\"userEmail\");\r",
+ " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(email);\r",
+ "});\r",
+ "pm.test(\"Test user 'name' field\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('name');\r",
+ " var name = pm.collectionVariables.get(\"userName\");\r",
+ " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "User delete",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([200,204]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = rnd.getUser();\r",
+ " us = await api.addUser(user);\r",
+ " pm.collectionVariables.set(\"userId\", us.id);\r",
+ " pm.collectionVariables.set(\"userName\", us.name);\r",
+ " pm.collectionVariables.set(\"userEmail\", us.email);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "DELETE",
+ "header": [
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/users/{{userId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "users",
+ "{{userId}}"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "items",
+ "item": [
+ {
+ "name": "Item create",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200 or 201\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r",
+ "});\r",
+ "pm.test(\"Response have body\", function () {\r",
+ " pm.response.to.be.withBody;\r",
+ " pm.response.to.be.json;\r",
+ "});\r",
+ "var item = pm.collectionVariables.get(\"item\");\r",
+ "\r",
+ "pm.test(\"Response data equal to request\", function () {\r",
+ " var jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.have.property('id');\r",
+ " pm.expect(jsonData).to.have.property('name');\r",
+ " pm.expect(jsonData).to.have.property('description');\r",
+ " pm.expect(jsonData).to.have.property('available');\r",
+ " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);\r",
+ " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);\r",
+ " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());\r",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/items",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item create without X-Sharer-User-Id",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400 or 500\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([500, 400]);\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/items",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item create with non-existent user",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id + '1');\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 404\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([404]);\r",
+ "});\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/items",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item create without available field",
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\"\n}"
+ },
+ "url": {
+ "raw": "localhost:8080/items",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item create with empty name field",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"\",\n \"description\": \"Аккумуляторная отвертка\",\n \"available\": true\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item create with empty description field",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"Отвертка\",\n \"available\": true\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('name');",
+ " pm.expect(jsonData).to.have.property('description');",
+ " pm.expect(jsonData).to.have.property('available');",
+ " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);",
+ " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);",
+ " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update without X-Sharer-User-Id",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 500\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([500, 400]);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text",
+ "disabled": true
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update with other user",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 404\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([404, 403]);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id + 1);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update available field",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('available');",
+ " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"available\": {{itemAvailable}}\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update description field",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('name');",
+ " pm.expect(jsonData).to.have.property('description');",
+ " pm.expect(jsonData).to.have.property('available');",
+ " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"description\": \"{{itemDescription}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item update name field",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('name');",
+ " pm.expect(jsonData).to.have.property('description');",
+ " pm.expect(jsonData).to.have.property('available');",
+ " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = rnd.getItem();\r",
+ " var it = await api.addItem(item, user.id)\r",
+ " item = rnd.getItem();\r",
+ " pm.collectionVariables.set(\"item\", item); \r",
+ " pm.collectionVariables.set(\"itemId\", it.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"{{itemName}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item get",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('name');",
+ " pm.expect(jsonData).to.have.property('description');",
+ " pm.expect(jsonData).to.have.property('available');",
+ " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);",
+ " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);",
+ " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " item = await api.addItem(rnd.getItem(), user.id)\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get all items from user",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Test list item response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.length, 'List length must be 2').to.eql(2);",
+ "});",
+ "",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " await api.addItem(rnd.getItem(), user.id)\r",
+ " await api.addItem(rnd.getItem(), user.id)\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item search",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Test list item response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.length, 'List length must be 1').to.eql(1);",
+ " pm.expect(jsonData[0].name.toUpperCase(), 'Name should include ' + pm.collectionVariables.get(\"searchString\")).to.eql(pm.collectionVariables.get(\"searchString\"))",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user.id)\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"searchString\", item.name.toUpperCase());\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items/search?text={{searchString}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "search"
+ ],
+ "query": [
+ {
+ "key": "text",
+ "value": "{{searchString}}"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item search unavailable",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Test list item response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.length, 'List length must be 0').to.eql(0);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user.id)\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"itemName\", item.name);\r",
+ " pm.collectionVariables.set(\"searchString\", item.name.toUpperCase());\r",
+ " pm.collectionVariables.set(\"itemAvailable\", item.available);\r",
+ " pm.collectionVariables.set(\"itemDescription\", item.description);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items/search?text={{searchString}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "search"
+ ],
+ "query": [
+ {
+ "key": "text",
+ "value": "{{searchString}}"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Item search empty",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Test search item response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.length, 'List length must be 0').to.eql(0);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items/search?text=",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "search"
+ ],
+ "query": [
+ {
+ "key": "text",
+ "value": ""
+ }
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "bookings",
+ "item": [
+ {
+ "name": "Booking unavailable item",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by wrong userId",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 500\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([500, 404, 403]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id + 1);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by not found itemId",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 404\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([404]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id + 1);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by end in past",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().subtract(3, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().subtract(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by start equal end",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by start equal null",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "var moment = require('moment');\r",
+ "\r",
+ "var start = moment().add(2, 'd');\r",
+ "pm.environment.set('start_null', start.format('YYYY-MM-DDTHH:mm:ss'));\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by end equal null",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "var moment = require('moment');\r",
+ "\r",
+ "var start = moment().add(2, 'd');\r",
+ "pm.environment.set('end_null', start.format('YYYY-MM-DDTHH:mm:ss'));\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking create failed by start in past",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500]);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().subtract(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = false\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking available item",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200 or 201\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201]);",
+ "});",
+ "pm.test(\"Has booking create response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get('item')",
+ "var user1 = pm.collectionVariables.get('user1')",
+ "var user2 = pm.collectionVariables.get('user2')",
+ "var start = pm.collectionVariables.get('start')",
+ "var end = pm.collectionVariables.get('end')",
+ "pm.test(\"Test booking 'start' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('start');",
+ " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));",
+ "});",
+ "pm.test(\"Test booking 'end' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('end');",
+ " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));",
+ "});",
+ "pm.test(\"Test booking 'status' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('status');",
+ " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');",
+ "});",
+ "pm.test(\"Test booking 'booker.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('booker');",
+ " pm.expect(jsonData.booker).to.have.property('id');",
+ " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);",
+ "});",
+ "pm.test(\"Test booking 'item.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('id');",
+ " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);",
+ "});",
+ "pm.test(\"Test booking 'item.name' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('name');",
+ " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking approve",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([200]);",
+ "});",
+ "pm.test(\"Has booking patch response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get('item')",
+ "var book = pm.collectionVariables.get('booking')",
+ "var user1 = pm.collectionVariables.get('user1')",
+ "var user2 = pm.collectionVariables.get('user2')",
+ "pm.test(\"Test booking 'id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData.id, '\"id\" must be ${book.id}').to.eql(book.id);",
+ "});",
+ "pm.test(\"Test booking 'start' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('start');",
+ " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));",
+ "});",
+ "pm.test(\"Test booking 'end' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('end');",
+ " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));",
+ "});",
+ "pm.test(\"Test booking 'status' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('status');",
+ " pm.expect(jsonData.status, '\"status\" must be \"APPROVED\"').to.eql('APPROVED');",
+ "});",
+ "pm.test(\"Test booking 'booker.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('booker');",
+ " pm.expect(jsonData.booker).to.have.property('id');",
+ " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);",
+ "});",
+ "pm.test(\"Test booking 'item.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('id');",
+ " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);",
+ "});",
+ "pm.test(\"Test booking 'item.name' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('name');",
+ " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user1.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings/{{bookingId}}?approved=true",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings",
+ "{{bookingId}}"
+ ],
+ "query": [
+ {
+ "key": "approved",
+ "value": "true"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Booking approve by wrong user",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 403\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 403, 500]);",
+ "});",
+ "pm.test(\"Has booking patch response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user1.id + 2);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings/{{bookingId}}?approved=true",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings",
+ "{{bookingId}}"
+ ],
+ "query": [
+ {
+ "key": "approved",
+ "value": "true"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get booking by booker",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Has booking create response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get('item')",
+ "var user1 = pm.collectionVariables.get('user1')",
+ "var user2 = pm.collectionVariables.get('user2')",
+ "var start = pm.collectionVariables.get('start')",
+ "var end = pm.collectionVariables.get('end')",
+ "pm.test(\"Test booking 'start' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('start');",
+ " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));",
+ "});",
+ "pm.test(\"Test booking 'end' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('end');",
+ " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));",
+ "});",
+ "pm.test(\"Test booking 'status' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('status');",
+ " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');",
+ "});",
+ "pm.test(\"Test booking 'booker.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('booker');",
+ " pm.expect(jsonData.booker).to.have.property('id');",
+ " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);",
+ "});",
+ "pm.test(\"Test booking 'item.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('id');",
+ " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);",
+ "});",
+ "pm.test(\"Test booking 'item.name' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('name');",
+ " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings/{{bookingId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings",
+ "{{bookingId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get booking by owner",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Has booking create response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get('item')",
+ "var user1 = pm.collectionVariables.get('user1')",
+ "var user2 = pm.collectionVariables.get('user2')",
+ "var start = pm.collectionVariables.get('start')",
+ "var end = pm.collectionVariables.get('end')",
+ "pm.test(\"Test booking 'start' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('start');",
+ " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));",
+ "});",
+ "pm.test(\"Test booking 'end' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('end');",
+ " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));",
+ "});",
+ "pm.test(\"Test booking 'status' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('status');",
+ " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');",
+ "});",
+ "pm.test(\"Test booking 'booker.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('booker');",
+ " pm.expect(jsonData.booker).to.have.property('id');",
+ " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);",
+ "});",
+ "pm.test(\"Test booking 'item.id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('id');",
+ " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);",
+ "});",
+ "pm.test(\"Test booking 'item.name' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('name');",
+ " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings/{{bookingId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings",
+ "{{bookingId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get all bookings from wrong user",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 500\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([500,404,403]);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"userId\", user2.id + 1);\r",
+ "\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings/owner",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings",
+ "owner"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get all user bookings",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Has booking patch response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get('item')",
+ "var book = pm.collectionVariables.get('booking')",
+ "var user1 = pm.collectionVariables.get('user1')",
+ "var user2 = pm.collectionVariables.get('user2')",
+ "var jsonData = pm.response.json()[0];",
+ "",
+ "pm.test(\"Test booking 'id' field\", function () {",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData.id, '\"id\" must be ${book.id}').to.eql(book.id);",
+ "});",
+ "pm.test(\"Test booking 'start' field\", function () {",
+ " pm.expect(jsonData).to.have.property('start');",
+ " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));",
+ "});",
+ "pm.test(\"Test booking 'end' field\", function () {",
+ " pm.expect(jsonData).to.have.property('end');",
+ " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));",
+ "});",
+ "pm.test(\"Test booking 'status' field\", function () {",
+ " pm.expect(jsonData).to.have.property('status');",
+ " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');",
+ "});",
+ "pm.test(\"Test booking 'booker.id' field\", function () {",
+ " pm.expect(jsonData).to.have.property('booker');",
+ " pm.expect(jsonData.booker).to.have.property('id');",
+ " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);",
+ "});",
+ "pm.test(\"Test booking 'item.id' field\", function () {",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('id');",
+ " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);",
+ "});",
+ "pm.test(\"Test booking 'item.name' field\", function () {",
+ " pm.expect(jsonData).to.have.property('item');",
+ " pm.expect(jsonData.item).to.have.property('name');",
+ " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ "\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/bookings",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "bookings"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "comments",
+ "item": [
+ {
+ "name": "Comment past booking",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200 or 201\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201]);",
+ "});",
+ "pm.test(\"Response have body\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "var item = pm.collectionVariables.get(\"item\");",
+ "var user1 = pm.collectionVariables.get(\"user1\");",
+ "var user2 = pm.collectionVariables.get(\"user2\");",
+ "var text = pm.collectionVariables.get(\"commentText\")",
+ "pm.test(\"Response data equal to request\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ " pm.expect(jsonData).to.have.property('text');",
+ " pm.expect(jsonData).to.have.property('authorName');",
+ " pm.expect(jsonData).to.have.property('created');",
+ " pm.expect(jsonData.text, `\"text\" must be ` + text).to.eql(text);",
+ " pm.expect(jsonData.authorName, `\"authorName\" must be ${user2.name}`).to.eql(user2.name);",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " await api.approveBooking(book.id, user1.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\r",
+ " setTimeout(function(){}, 3000);\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"text\": \"{{commentText}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}/comment",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}",
+ "comment"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Comment approved booking",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.expect(pm.response.code).to.be.oneOf([400, 500])",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " await api.approveBooking(book.id, user1.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ },
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"text\": \"{{commentText}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}/comment",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}",
+ "comment"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get item with comments",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.be.ok;",
+ "});",
+ "pm.test(\"Has item create response\", function () {",
+ " pm.response.to.be.withBody;",
+ " pm.response.to.be.json;",
+ "});",
+ "pm.test(\"Test item 'id' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('id');",
+ "});",
+ "pm.test(\"Test item 'name' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('name');",
+ "});",
+ "pm.test(\"Test item 'description' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('description');",
+ "});",
+ "pm.test(\"Test item 'available' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('available');",
+ "});",
+ "pm.test(\"Test item 'lastBooking' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('lastBooking');",
+ " pm.expect(jsonData.lastBooking, '\"lastBooking\" must be \"null\"').null;",
+ "});",
+ "pm.test(\"Test item 'nextBooking' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('nextBooking');",
+ " pm.expect(jsonData.nextBooking, '\"nextBooking\" must be \"null\"').null;",
+ "});",
+ "pm.test(\"Test item 'comments' field\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData).to.have.property('comments');",
+ " pm.expect(jsonData.comments.length, 'length of \"comments\" must be \"1\"').to.eql(1);",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "const main = async () => {\r",
+ " const api = new API(pm);\r",
+ " const rnd = new RandomUtils();\r",
+ "\r",
+ " try {\r",
+ " var moment = require('moment');\r",
+ " const currentDate = moment();\r",
+ " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r",
+ " pm.collectionVariables.set('start', start);\r",
+ " pm.collectionVariables.set('end', end);\r",
+ " \r",
+ " user1 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user1\", user1);\r",
+ " user2 = await api.addUser(rnd.getUser());\r",
+ " pm.collectionVariables.set(\"user2\", user2);\r",
+ " pm.collectionVariables.set(\"userId\", user2.id);\r",
+ " it = rnd.getItem()\r",
+ " it.available = true\r",
+ " item = await api.addItem(it, user1.id)\r",
+ " pm.collectionVariables.set(\"itemId\", item.id);\r",
+ " pm.collectionVariables.set(\"item\", item);\r",
+ " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r",
+ " await api.approveBooking(book.id, user1.id)\r",
+ " pm.collectionVariables.set(\"bookingId\", book.id);\r",
+ " pm.collectionVariables.set(\"booking\", book);\r",
+ " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\r",
+ " pausecomp(3000);\r",
+ " await api.getBooking(book.id, user1.id)\r",
+ " comment = await api.addComment({\"text\": rnd.getWord(50)}, item.id, user2.id)\r",
+ " } catch(err) {\r",
+ " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r",
+ " }\r",
+ "\r",
+ "};\r",
+ "\r",
+ "const interval = setInterval(() => {}, 1000);\r",
+ "function pausecomp(millis)\r",
+ " {\r",
+ " var date = new Date();\r",
+ " var curDate = null;\r",
+ " do { curDate = new Date(); }\r",
+ " while(curDate-date < millis);\r",
+ "}\r",
+ "setTimeout(async () => \r",
+ " {\r",
+ " try {\r",
+ " await main();\r",
+ " } catch (e) {\r",
+ " console.error(e);\r",
+ " } finally {\r",
+ " clearInterval(interval);\r",
+ " }\r",
+ " }, \r",
+ " 100 \r",
+ ");"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "X-Sharer-User-Id",
+ "value": "{{userId}}",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/items/{{itemId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "items",
+ "{{itemId}}"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ "API = class {\r",
+ " constructor(postman, verbose = false, baseUrl = \"http://localhost:8080\") {\r",
+ " this.baseUrl = baseUrl;\r",
+ " this.pm = postman;\r",
+ " this._verbose = verbose;\r",
+ " }\r",
+ "\r",
+ " async addUser(user, id=0, verbose=null) {\r",
+ " return this.post(\"/users\", user, id, \"Ошибка при добавлении нового пользователя: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async addItem(item, id=0, verbose=null) {\r",
+ " return this.post(\"/items\", item, id, \"Ошибка при добавлении новой вещи: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async addBooking(booking, id=0, verbose=null) {\r",
+ " return this.post(\"/bookings\", booking, id, \"Ошибка при добавлении нового бронирования: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async addComment(comment, itemId, id=0, verbose=null) {\r",
+ " return this.post(\"/items/\" + itemId + \"/comment\", comment, id, \"Ошибка при добавлении нового комментария: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async getBooking(bookingId, id=0, verbose=null) {\r",
+ " return this.get(\"/bookings/\"+bookingId, {}, id, \"Ошибка при получении информации о бронировании: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async approveBooking(bookingId, id=0, verbose=null) {\r",
+ " return this.patch(\"/bookings/\"+bookingId+\"?approved=true\", {}, id, \"Ошибка при подтверждении бронирования: \", verbose);\r",
+ " }\r",
+ "\r",
+ " async addRequest(request, id=0, verbose=null) {\r",
+ " return this.post(\"/requests\", request, id, \"Ошибка при добавлении нового запроса: \", verbose);\r",
+ " }\r",
+ " \r",
+ " async post(path, body, id=0, errorText = \"Ошибка при выполнении post-запроса: \", verbose=null) {\r",
+ " return this.sendRequest(\"POST\", path, body, id, errorText, verbose);\r",
+ " }\r",
+ "\r",
+ " async patch(path, body = null, id=0, errorText = \"Ошибка при выполнении patch-запроса: \", verbose=null) {\r",
+ " return this.sendRequest(\"PATCH\", path, body, id, errorText, verbose);\r",
+ " }\r",
+ "\r",
+ " async get(path, body = null, id=0, errorText = \"Ошибка при выполнении get-запроса: \", verbose=null) {\r",
+ " return this.sendRequest(\"GET\", path, body, id, errorText, verbose);\r",
+ " }\r",
+ "\r",
+ " async put(path, body = null, id=0, errorText = \"Ошибка при выполнении put-запроса: \", verbose=null) {\r",
+ " return this.sendRequest(\"PUT\", path, body, id, errorText, verbose);\r",
+ " }\r",
+ "\r",
+ " async delete(path, body = null, id=0, errorText = \"Ошибка при выполнении delte-запроса: \", verbose=null) {\r",
+ " return this.sendRequest(\"DELETE\", path, body, id, errorText, verbose);\r",
+ " }\r",
+ "\r",
+ " async sendRequest(method, path, body=null, id=0, errorText = \"Ошибка при выполнении запроса: \", verbose=null) {\r",
+ " return new Promise((resolve, reject) => {\r",
+ " verbose = verbose == null ? this._verbose : verbose;\r",
+ " var req = {};\r",
+ " if (id == 0){\r",
+ " req = {\r",
+ " url: this.baseUrl + path,\r",
+ " method: method,\r",
+ " body: body == null ? \"\" : JSON.stringify(body),\r",
+ " header: { \"Content-Type\": \"application/json\"},\r",
+ " };\r",
+ " }else{\r",
+ " req = {\r",
+ " url: this.baseUrl + path,\r",
+ " method: method,\r",
+ " body: body == null ? \"\" : JSON.stringify(body),\r",
+ " header: [{\r",
+ " \"key\": \"X-Sharer-User-Id\",\r",
+ " \"value\": id,\r",
+ " \"type\": \"text\",\r",
+ " },\r",
+ " {\r",
+ " \"key\": \"Content-Type\",\r",
+ " \"name\": \"Content-Type\",\r",
+ " \"value\": \"application/json\",\r",
+ " \"type\": \"text\"\r",
+ " }]\r",
+ " };\r",
+ " }\r",
+ " if(verbose) {\r",
+ " console.log(\"Отправляю запрос: \", req);\r",
+ " }\r",
+ "\r",
+ " try {\r",
+ " this.pm.sendRequest(req, (error, response) => {\r",
+ " if(error || (response.code >= 400 && response.code <= 599)) {\r",
+ " let err = error ? error : JSON.stringify(response.json());\r",
+ " console.error(\"При выполнении запроса к серверу возникла ошибка.\\n\", err,\r",
+ " \"\\nДля отладки проблемы повторите такой же запрос к вашей программе \" + \r",
+ " \"на локальном компьютере. Данные запроса:\\n\", JSON.stringify(request));\r",
+ "\r",
+ " reject(new Error(errorText + err));\r",
+ " }\r",
+ " if(verbose) {\r",
+ " console.log(\"Результат обработки запроса: код состояния - \", response.code, \", тело: \", response.json());\r",
+ " }\r",
+ " if (response.stream.length === 0){\r",
+ " resolve(null);\r",
+ " }else{\r",
+ " resolve(response.json());\r",
+ " }\r",
+ " });\r",
+ " \r",
+ " } catch(err) {\r",
+ " if(verbose) {\r",
+ " console.error(errorText, err);\r",
+ " }\r",
+ " return Promise.reject(err);\r",
+ " }\r",
+ " });\r",
+ " }\r",
+ "};\r",
+ "\r",
+ "RandomUtils = class {\r",
+ " constructor() {}\r",
+ "\r",
+ " getUser() {\r",
+ " return {\r",
+ " name: pm.variables.replaceIn('{{$randomFullName}}'),\r",
+ " email: pm.variables.replaceIn('{{$randomEmail}}'),\r",
+ " };\r",
+ " }\r",
+ "\r",
+ " getRequest() {\r",
+ " return {\r",
+ " description: this.getWord(50)\r",
+ " };\r",
+ " }\r",
+ "\r",
+ " getBooking(id, startBook, endBook) {\r",
+ " return {\r",
+ " itemId: id, \r",
+ " start: startBook,\r",
+ " end: endBook \r",
+ " };\r",
+ " }\r",
+ "\r",
+ " getItem() {\r",
+ " return {\r",
+ " name: this.getWord(10),\r",
+ " description: this.getWord(50),\r",
+ " available: pm.variables.replaceIn('{{$randomBoolean}}')\t\r",
+ " };\r",
+ " }\r",
+ "\r",
+ " getItemForRequest(id) {\r",
+ " return {\r",
+ " name: this.getWord(10),\r",
+ " description: this.getWord(50),\r",
+ " available: pm.variables.replaceIn('{{$randomBoolean}}'),\r",
+ " requestId: id\r",
+ " };\r",
+ " }\r",
+ "\r",
+ " getFilm(director=null) {\r",
+ " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));\r",
+ " var toReturn = {\r",
+ " name: this.getWord(15),\r",
+ " description: this.getWord(50),\r",
+ " releaseDate: date.toISOString().slice(0,10),\r",
+ " duration: Math.floor(Math.random() * (180 - 60 + 1) + 60),\r",
+ " mpa: { id: Math.floor(Math.random() * (5 - 1 + 1) + 1)},\r",
+ " genres: [{ id: Math.floor(Math.random() * (6 - 1 + 1) + 1)}]\r",
+ " };\r",
+ " if (director!==null)\r",
+ " toReturn.directors = [{ id: director.id}];\r",
+ " return toReturn;\r",
+ " }\r",
+ "\r",
+ "\r",
+ " getWord(length = 1) {\r",
+ " let result = '';\r",
+ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r",
+ " const charactersLength = characters.length;\r",
+ " let counter = 0;\r",
+ " while (counter < length) {\r",
+ " result += characters.charAt(Math.floor(Math.random() * charactersLength));\r",
+ " counter += 1;\r",
+ " }\r",
+ " return result;\r",
+ " }\r",
+ "\r",
+ " getName(length = 1) {\r",
+ " let result = '';\r",
+ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\r",
+ " const charactersLength = characters.length;\r",
+ " let counter = 0;\r",
+ " while (counter < length) {\r",
+ " result += characters.charAt(Math.floor(Math.random() * charactersLength));\r",
+ " counter += 1;\r",
+ " }\r",
+ " return result;\r",
+ " }\r",
+ "\r",
+ "}"
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "variable": [
+ {
+ "key": "baseUrl",
+ "value": "http://localhost:8080"
+ },
+ {
+ "key": "userName",
+ "value": ""
+ },
+ {
+ "key": "userEmail",
+ "value": ""
+ },
+ {
+ "key": "userId",
+ "value": ""
+ },
+ {
+ "key": "item",
+ "value": ""
+ },
+ {
+ "key": "itemName",
+ "value": ""
+ },
+ {
+ "key": "itemAvailable",
+ "value": ""
+ },
+ {
+ "key": "itemDescription",
+ "value": ""
+ },
+ {
+ "key": "itemId",
+ "value": ""
+ },
+ {
+ "key": "searchString",
+ "value": ""
+ },
+ {
+ "key": "start",
+ "value": ""
+ },
+ {
+ "key": "end",
+ "value": ""
+ },
+ {
+ "key": "user1",
+ "value": ""
+ },
+ {
+ "key": "user2",
+ "value": ""
+ },
+ {
+ "key": "bookingId",
+ "value": ""
+ },
+ {
+ "key": "booking",
+ "value": ""
+ },
+ {
+ "key": "commentText",
+ "value": ""
+ }
+ ]
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/src/main/java/ru/practicum/shareit/booking/Booking.java
index f14b217..ccfe012 100644
--- a/src/main/java/ru/practicum/shareit/booking/Booking.java
+++ b/src/main/java/ru/practicum/shareit/booking/Booking.java
@@ -9,9 +9,9 @@
@Getter
@Setter
+@ToString
@RequiredArgsConstructor
@AllArgsConstructor
-@ToString
@EqualsAndHashCode(of = {"id"})
@Entity
@Table(name = "bookings")
@@ -20,20 +20,22 @@ public class Booking {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
- @Column(name = "start_", nullable = false)
+ @Column(name = "start_date", nullable = false)
private LocalDateTime start;
- @Column(name = "end_", nullable = false)
+ @Column(name = "end_date", nullable = false)
private LocalDateTime end;
@ManyToOne
- @JoinColumn(name = "item", nullable = false)
+ @JoinColumn(name = "item_id", nullable = false)
private Item item;
@ManyToOne
- @JoinColumn(name = "booker", nullable = false)
+ @JoinColumn(name = "booker_id", nullable = false)
private User booker;
@Column(length = 10)
- private String status;
+ @Enumerated(EnumType.STRING)
+ private BookingStatus status;
+
}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/src/main/java/ru/practicum/shareit/booking/BookingController.java
index b94493d..40df0bc 100644
--- a/src/main/java/ru/practicum/shareit/booking/BookingController.java
+++ b/src/main/java/ru/practicum/shareit/booking/BookingController.java
@@ -1,12 +1,86 @@
package ru.practicum.shareit.booking;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
-/**
- * TODO Sprint add-bookings.
- */
@RestController
@RequestMapping(path = "/bookings")
+@RequiredArgsConstructor
public class BookingController {
-}
+
+ private final BookingService bookingService;
+
+ /**
+ * • Добавление нового запроса на бронирование. Запрос может быть создан любым пользователем,
+ * а затем подтверждён владельцем вещи. Эндпоинт — POST /bookings.
+ * После создания запрос находится в статусе WAITING — «ожидает подтверждения».
+ */
+ @PostMapping
+ public BookingDtoOutput addBooking(@RequestHeader("X-Sharer-User-Id") Long bookerId,
+ @Valid @RequestBody BookingDtoInput bookingDto) {
+ return BookingMapper.toBookingDtoOutput(bookingService.addBooking(bookerId, bookingDto));
+ }
+
+ /**
+ * • Подтверждение или отклонение запроса на бронирование. Может быть выполнено только владельцем вещи.
+ * Затем статус бронирования становится либо APPROVED, либо REJECTED.
+ * Эндпоинт — PATCH /bookings/{bookingId}?approved={approved}, параметр approved может принимать
+ * значения true или false.
+ *
+ * @param ownerId ID владельца вещи.
+ * @param bookingId ID брони.
+ * @param approved True - подтверждено, False - отклонено.
+ * @return Обновленная бронь.
+ */
+ @PatchMapping("/{bookingId}")
+ public BookingDtoOutput updateByOwner(@RequestHeader("X-Sharer-User-Id") Long ownerId,
+ @PathVariable Long bookingId,
+ @RequestParam Boolean approved) {
+ return BookingMapper.toBookingDtoOutput(bookingService.updateBooking(ownerId, bookingId, approved));
+ }
+
+ /**
+ * • Получение данных о конкретном бронировании (включая его статус).
+ * Может быть выполнено либо автором бронирования, либо владельцем вещи,
+ * к которой относится бронирование.
+ * Эндпоинт — GET /bookings/{bookingId}.
+ */
+ @GetMapping("/{bookingId}")
+ public BookingDtoOutput getWithStatusById(@RequestHeader("X-Sharer-User-Id") Long userId,
+ @PathVariable Long bookingId) {
+ return BookingMapper.toBookingDtoOutput(bookingService.getWithStatusById(userId, bookingId));
+ }
+
+ /**
+ * • Получение списка всех бронирований текущего пользователя.
+ * Эндпоинт — GET /bookings?state={state}.
+ * Параметр state необязательный и по умолчанию равен ALL (англ. «все»).
+ * Также он может принимать значения CURRENT (англ. «текущие»), PAST (англ. «завершённые»),
+ * FUTURE (англ. «будущие»), WAITING (англ. «ожидающие подтверждения»), REJECTED (англ. «отклонённые»).
+ * Бронирования должны возвращаться отсортированными по дате от более новых к более старым.
+ */
+ @GetMapping
+ public List getByUserId(@RequestHeader("X-Sharer-User-Id") Long userId,
+ @RequestParam(value = "state",
+ defaultValue = "ALL", required = false) String state) {
+ return bookingService.getByUserId(userId, state)
+ .stream().map(BookingMapper::toBookingDtoOutput).toList();
+ }
+
+ /**
+ * • Получение списка бронирований для всех вещей текущего пользователя.
+ * Эндпоинт — GET /bookings/owner?state={state}.
+ * Этот запрос имеет смысл для владельца хотя бы одной вещи.
+ * Работа параметра state аналогична его работе в предыдущем сценарии.
+ */
+ @GetMapping("/owner")
+ public List getByOwnerId(@RequestHeader("X-Sharer-User-Id") Long userId,
+ @RequestParam(value = "state", defaultValue = "ALL",
+ required = false) String state) {
+ return bookingService.getByOwnerId(userId, state)
+ .stream().map(BookingMapper::toBookingDtoOutput).toList();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/BookingDto.java
index 5bce3d5..07632f8 100644
--- a/src/main/java/ru/practicum/shareit/booking/BookingDto.java
+++ b/src/main/java/ru/practicum/shareit/booking/BookingDto.java
@@ -1,7 +1,28 @@
package ru.practicum.shareit.booking;
-/**
- * TODO Sprint add-bookings.
- */
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.item.Item;
+import ru.practicum.shareit.user.User;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
public class BookingDto {
+
+ private Long id;
+
+ private LocalDateTime start;
+
+ private LocalDateTime end;
+
+ private Item item;
+
+ private User booker;
+
+ private BookingStatus status;
+
}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingDtoInput.java b/src/main/java/ru/practicum/shareit/booking/BookingDtoInput.java
new file mode 100644
index 0000000..b39e330
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingDtoInput.java
@@ -0,0 +1,28 @@
+package ru.practicum.shareit.booking;
+
+import jakarta.validation.constraints.FutureOrPresent;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.validation.CreateObject;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BookingDtoInput {
+
+ @NotNull(groups = {CreateObject.class}, message = "При создании брони должна быть информация о вещи.")
+ private Long itemId;
+
+ @FutureOrPresent(groups = {CreateObject.class}, message = "Дата не должна быть в прошлом")
+ @NotNull(groups = {CreateObject.class}, message = "Дата не должна быть пустой")
+ private LocalDateTime start;
+
+ @FutureOrPresent(groups = {CreateObject.class}, message = "Дата не должна быть в прошлом")
+ @NotNull(groups = {CreateObject.class}, message = "Дата не должна быть пустой")
+ private LocalDateTime end;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingDtoOutput.java b/src/main/java/ru/practicum/shareit/booking/BookingDtoOutput.java
new file mode 100644
index 0000000..c3b3476
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingDtoOutput.java
@@ -0,0 +1,30 @@
+package ru.practicum.shareit.booking;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.item.ItemDtoShort;
+import ru.practicum.shareit.user.UserDtoShort;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BookingDtoOutput {
+
+ private Long id;
+
+ private LocalDateTime start;
+
+ private LocalDateTime end;
+
+ private ItemDtoShort item;
+
+ private UserDtoShort booker;
+
+ @JsonProperty("status")
+ private BookingStatus status;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingDtoShort.java b/src/main/java/ru/practicum/shareit/booking/BookingDtoShort.java
new file mode 100644
index 0000000..de9f8b7
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingDtoShort.java
@@ -0,0 +1,24 @@
+package ru.practicum.shareit.booking;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BookingDtoShort {
+
+ private Long id;
+
+ private LocalDateTime start;
+
+ private LocalDateTime end;
+
+ @JsonProperty("status")
+ private BookingStatus status;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/BookingMapper.java
new file mode 100644
index 0000000..adf3f3d
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingMapper.java
@@ -0,0 +1,65 @@
+package ru.practicum.shareit.booking;
+
+import ru.practicum.shareit.item.ItemMapper;
+import ru.practicum.shareit.user.UserMapper;
+
+public class BookingMapper {
+
+ public static BookingDtoOutput toBookingDtoOutput(Booking booking) {
+ if (booking == null) {
+ return null;
+ }
+ BookingDtoOutput bookingDto = new BookingDtoOutput();
+
+ bookingDto.setId(booking.getId());
+ bookingDto.setStart(booking.getStart());
+ bookingDto.setEnd(booking.getEnd());
+ bookingDto.setItem(ItemMapper.toItemDtoShort(booking.getItem()));
+ bookingDto.setBooker(UserMapper.toUserDtoShort(booking.getBooker()));
+ bookingDto.setStatus(booking.getStatus());
+
+ return bookingDto;
+ }
+
+ public static BookingDtoShort toBookingDtoShort(Booking booking) {
+ if (booking == null) {
+ return null;
+ }
+ BookingDtoShort bookingDto = new BookingDtoShort();
+
+ bookingDto.setId(booking.getId());
+ bookingDto.setStart(booking.getStart());
+ bookingDto.setEnd(booking.getEnd());
+ bookingDto.setStatus(booking.getStatus());
+
+ return bookingDto;
+ }
+
+ public static Booking toBooking(BookingDto bookingDto) {
+ Booking booking = new Booking();
+
+ if (bookingDto.getId() != null) {
+ if (bookingDto.getId() > 0) {
+ booking.setId(bookingDto.getId());
+ }
+ }
+ if (bookingDto.getStart() != null) {
+ booking.setStart(bookingDto.getStart());
+ }
+ if (bookingDto.getEnd() != null) {
+ booking.setEnd(bookingDto.getEnd());
+ }
+ if (bookingDto.getItem() != null) {
+ booking.setItem(bookingDto.getItem());
+ }
+ if (bookingDto.getBooker() != null) {
+ booking.setBooker(bookingDto.getBooker());
+ }
+ if (bookingDto.getStatus() != null) {
+ booking.setStatus(bookingDto.getStatus());
+ }
+
+ return booking;
+ }
+
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/BookingRepository.java
new file mode 100644
index 0000000..72ad8ac
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingRepository.java
@@ -0,0 +1,32 @@
+package ru.practicum.shareit.booking;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import ru.practicum.shareit.user.User;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Repository
+public interface BookingRepository extends JpaRepository {
+
+ List findAllByBookerOrderByStartDesc(User bookerFromDb);
+
+ List findAllByBookerAndStartBeforeAndEndAfterOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime, LocalDateTime nowDateTime1);
+
+ List findAllByBookerAndEndIsBeforeOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime);
+
+ List findAllByBookerAndStartIsAfterOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime);
+
+ List findAllByBookerAndStatusEqualsOrderByStartDesc(User bookerFromDb, BookingState bookingState);
+
+ List findAllByItem_OwnerOrderByStartDesc(User bookerFromDb);
+
+ List findAllByItem_OwnerAndStartIsBeforeAndEndIsAfterOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime, LocalDateTime nowDateTime1);
+
+ List findAllByItem_OwnerAndEndIsBeforeOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime);
+
+ List findAllByItem_OwnerAndStartIsAfterOrderByStartDesc(User bookerFromDb, LocalDateTime nowDateTime);
+
+ List findAllByItem_OwnerAndStatusEqualsOrderByStartDesc(User bookerFromDb, BookingState bookingState);
+}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingService.java b/src/main/java/ru/practicum/shareit/booking/BookingService.java
new file mode 100644
index 0000000..9a731d5
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingService.java
@@ -0,0 +1,16 @@
+package ru.practicum.shareit.booking;
+
+import java.util.List;
+
+public interface BookingService {
+
+ Booking addBooking(Long bookerId, BookingDtoInput bookingDto);
+
+ Booking updateBooking(Long ownerId, Long bookingId, Boolean approved);
+
+ Booking getWithStatusById(Long userId, Long bookingId);
+
+ List getByUserId(Long userId, String state);
+
+ List getByOwnerId(Long userId, String state);
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java
new file mode 100644
index 0000000..991eba2
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java
@@ -0,0 +1,280 @@
+package ru.practicum.shareit.booking;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import ru.practicum.shareit.exception.NotFoundException;
+import ru.practicum.shareit.exception.RestrictedAccessException;
+import ru.practicum.shareit.exception.ValidationException;
+import ru.practicum.shareit.item.Item;
+import ru.practicum.shareit.item.ItemRepository;
+import ru.practicum.shareit.user.User;
+import ru.practicum.shareit.user.UserRepository;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class BookingServiceImpl implements BookingService {
+ private final BookingRepository bookingRepository;
+ private final ItemRepository itemRepository;
+ private final UserRepository userRepository;
+
+ /**
+ * Создание брони в БД.
+ *
+ * @param bookerId пользователь, пытающийся забронировать вещь.
+ * @param inputBookingDto создаваемая бронь.
+ * @return бронь из БД.
+ */
+ @Override
+ public Booking addBooking(Long bookerId, BookingDtoInput inputBookingDto) {
+ Item itemFromDB = itemRepository.findById(inputBookingDto.getItemId())
+ .orElseThrow(() -> new NotFoundException("При создании бронирования не найдена " +
+ "вещь с ID = " + inputBookingDto.getItemId() + " в БД."));
+ BookingDto bookingDto = new BookingDto();
+ bookingDto.setStart(inputBookingDto.getStart());
+ bookingDto.setEnd(inputBookingDto.getEnd());
+ bookingDto.setItem(itemFromDB);
+ User bookerFromDb = userRepository.findById(bookerId)
+ .orElseThrow(() -> new NotFoundException("При " +
+ "создании бронирования не найден пользователь с ID = " + bookerId + " в БД."));
+ validateBooking(bookingDto, itemFromDB, bookerFromDb);
+ if (!itemFromDB.getAvailable()) {
+ throw new ValidationException("Вещь нельзя забронировать, поскольку available = false.");
+ }
+ bookingDto.setStatus(BookingStatus.WAITING);
+ bookingDto.setItem(itemFromDB);
+ bookingDto.setBooker(bookerFromDb);
+ Booking result = bookingRepository.save(BookingMapper.toBooking(bookingDto));
+ log.info("Создано бронирование с ID = [ {} ].", result.getId());
+ return result;
+ }
+
+ /**
+ * Обновить бронь в БД.
+ *
+ * @param ownerId хозяин вещи.
+ * @param bookingId ID брони.
+ * @param approved True - подтверждение со стороны хозяина вещи,
+ * False - отклонено хозяином вещи.
+ * @return обновлённая бронь.
+ */
+ @Override
+ public Booking updateBooking(Long ownerId, Long bookingId, Boolean approved) {
+ Booking bookingFromBd = bookingRepository.findById(bookingId).orElseThrow(() -> new NotFoundException(
+ "При обновлении бронирования не найдено бронирование с ID = '" + bookingId + "' в БД."));
+ if (bookingFromBd.getStatus().equals(BookingStatus.APPROVED) && approved) {
+ String message = "Данное бронирование уже было обработано и имеет статус '"
+ + bookingFromBd.getStatus() + "'.";
+ log.info(message);
+ throw new ValidationException(message);
+ }
+ User ownerFromDb = userRepository.findById(ownerId).orElseThrow(() -> new RestrictedAccessException("При " +
+ "обновлении бронирования не найден пользователь с ID = '" + ownerId + "' в БД."));
+ List- items = ownerFromDb.getItems();
+ for (Item i : ownerFromDb.getItems()) {
+ if (i.getId().equals(bookingFromBd.getItem().getId())) {
+ bookingFromBd.setStatus(approved ? BookingStatus.APPROVED : BookingStatus.REJECTED);
+ Booking result = bookingRepository.save(bookingFromBd);
+ log.info("Бронирование с ID = [ {} ] обновлено.", bookingId);
+ return result;
+ }
+ }
+ String message = "При обновлении брони у хозяина вещи эта вещь не найдена. Ошибка в запросе.";
+ log.info(message);
+ throw new NotFoundException(message);
+ }
+
+ /**
+ * • Получение данных о конкретном бронировании (включая его статус).
+ * Может быть выполнено либо автором бронирования, либо владельцем вещи,
+ * к которой относится бронирование.
+ *
+ * @param userId ID пользователя, делающего запрос.
+ * @param bookingId ID брони.
+ */
+ @Override
+ public Booking getWithStatusById(Long userId, Long bookingId) {
+ Booking booking = bookingRepository.findById(bookingId)
+ .orElseThrow(() -> new NotFoundException("Бронирование с ID = '" + bookingId
+ + "не найдено в БД при его получении."));
+ if (userId.equals(booking.getBooker().getId()) || userId.equals(booking.getItem().getOwner().getId())) {
+ return booking;
+ }
+ throw new NotFoundException("Ошибка при получении брони с ID = '" + bookingId
+ + "'. Пользователь с ID = '" + userId
+ + "' не является ни хозяином, ни пользователем, забронировавшим вещь.");
+ }
+
+ /**
+ * • Получение списка всех бронирований текущего пользователя.
+ * Параметр state необязательный и по умолчанию равен ALL (англ. «все»).
+ * Также он может принимать значения CURRENT (англ. «текущие»), PAST (англ. «завершённые»),
+ * FUTURE (англ. «будущие»), WAITING (англ. «ожидающие подтверждения»), REJECTED (англ. «отклонённые»).
+ * Бронирования должны возвращаться отсортированными по дате от более новых к более старым.
+ *
+ * @param userId ID пользователя.
+ * @param state статус бронирования.
+ */
+ @Override
+ public List getByUserId(Long userId, String state) {
+ final LocalDateTime nowDateTime = LocalDateTime.now();
+ BookingState bookingState;
+
+ if (state.isBlank()) {
+ bookingState = BookingState.ALL;
+ } else {
+ try {
+ bookingState = BookingState.valueOf(state);
+ } catch (IllegalArgumentException ex) {
+ throw new ValidationException("Неизвестное состояние бронирования.");
+ }
+ }
+ User bookerFromDb = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("При " +
+ "получении списка бронирований не найден пользователь (арендующий) с ID = " + userId + " в БД."));
+ List result = new ArrayList<>();
+
+ switch (bookingState) {
+ case ALL: {
+ result = bookingRepository.findAllByBookerOrderByStartDesc(bookerFromDb);
+ break;
+ }
+ case CURRENT: {
+ result = bookingRepository.findAllByBookerAndStartBeforeAndEndAfterOrderByStartDesc(
+ bookerFromDb, nowDateTime, nowDateTime);
+ break;
+ }
+ case PAST: {
+ result = bookingRepository.findAllByBookerAndEndIsBeforeOrderByStartDesc(
+ bookerFromDb, nowDateTime);
+ break;
+ }
+ case FUTURE: {
+ result = bookingRepository.findAllByBookerAndStartIsAfterOrderByStartDesc(
+ bookerFromDb, nowDateTime);
+ break;
+ }
+ case WAITING: {
+ result = bookingRepository.findAllByBookerAndStatusEqualsOrderByStartDesc(
+ bookerFromDb, BookingState.WAITING);
+ break;
+ }
+ case REJECTED: {
+ result = bookingRepository.findAllByBookerAndStatusEqualsOrderByStartDesc(
+ bookerFromDb, BookingState.REJECTED);
+ break;
+ }
+ default: {
+ throw new ValidationException("Неизвестное состояние бронирования.");
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * • Получение списка бронирований для всех вещей текущего пользователя, то есть хозяина вещей.
+ *
+ * @param userId ID хозяина вещей.
+ * @param state Параметр state необязательный и по умолчанию равен ALL (англ. «все»).
+ * Также он может принимать значения CURRENT (англ. «текущие»), PAST (англ. «завершённые»),
+ * FUTURE (англ. «будущие»), WAITING (англ. «ожидающие подтверждения»),
+ * REJECTED (англ. «отклонённые»).
+ * @return Бронирования должны возвращаться отсортированными по дате от более новых к более старым.
+ */
+ @Override
+ public List getByOwnerId(Long userId, String state) {
+ final LocalDateTime nowDateTime = LocalDateTime.now();
+ BookingState bookingState;
+
+ try {
+ bookingState = BookingState.valueOf(state);
+ } catch (IllegalArgumentException ex) {
+ throw new ValidationException("Неизвестное состояние бронирования.");
+ }
+ User bookerFromDb = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("При " +
+ "получении списка бронирований не найден хозяин с ID = " + userId + " в БД."));
+ List result = new ArrayList<>();
+
+ switch (bookingState) {
+ case ALL: {
+ result = bookingRepository.findAllByItem_OwnerOrderByStartDesc(bookerFromDb);
+ System.out.println(result);
+ break;
+ }
+ case CURRENT: {
+ result = bookingRepository.findAllByItem_OwnerAndStartIsBeforeAndEndIsAfterOrderByStartDesc(
+ bookerFromDb, nowDateTime, nowDateTime);
+ break;
+ }
+ case PAST: {
+ result = bookingRepository.findAllByItem_OwnerAndEndIsBeforeOrderByStartDesc(
+ bookerFromDb, nowDateTime);
+ break;
+ }
+ case FUTURE: {
+ result = bookingRepository.findAllByItem_OwnerAndStartIsAfterOrderByStartDesc(
+ bookerFromDb, nowDateTime);
+ break;
+ }
+ case WAITING: {
+ result = bookingRepository.findAllByItem_OwnerAndStatusEqualsOrderByStartDesc(
+ bookerFromDb, BookingState.WAITING);
+ break;
+ }
+ case REJECTED: {
+ result = bookingRepository.findAllByItem_OwnerAndStatusEqualsOrderByStartDesc(
+ bookerFromDb, BookingState.REJECTED);
+ break;
+ }
+ default: {
+ throw new ValidationException("Неизвестное состояние бронирования.");
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Проверка при создании бронирования вещи.
+ *
+ * @param bookingDto бронь.
+ * @param item вещь.
+ * @param booker пользователь.
+ */
+ private void validateBooking(BookingDto bookingDto, Item item, User booker) {
+ if (item.getOwner().equals(booker)) {
+ String message = "Создать бронь на свою вещь нельзя.";
+ log.info(message);
+ throw new ValidationException(message);
+ }
+
+ if (bookingDto.getStart().equals(bookingDto.getEnd())) {
+ String message = "Начало и окончание бронирования не может быть одним и тем же временем.";
+ log.info(message);
+ throw new ValidationException(message);
+ }
+
+ if (bookingDto.getEnd().isBefore(bookingDto.getStart())) {
+ String message = "Окончание бронирования не может быть раньше его начала.";
+ log.info(message);
+ throw new ValidationException(message);
+ }
+
+ List bookings = item.getBookings();
+ if (!bookings.isEmpty()) {
+ for (Booking b : bookings) {
+ if (!(b.getEnd().isBefore(bookingDto.getStart()) ||
+ b.getStart().isAfter(bookingDto.getStart()))) {
+ String message = "Найдено пересечение дат бронирования на вещь с name = " + item.getName() + ".";
+ log.debug(message);
+ throw new ValidationException(message);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingState.java b/src/main/java/ru/practicum/shareit/booking/BookingState.java
new file mode 100644
index 0000000..75be8b4
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingState.java
@@ -0,0 +1,5 @@
+package ru.practicum.shareit.booking;
+
+public enum BookingState {
+ ALL, CURRENT, PAST, FUTURE, WAITING, REJECTED;
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/src/main/java/ru/practicum/shareit/booking/BookingStatus.java
index 51269e0..22928de 100644
--- a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java
+++ b/src/main/java/ru/practicum/shareit/booking/BookingStatus.java
@@ -3,6 +3,5 @@
public enum BookingStatus {
WAITING,
APPROVED,
- REJECTED,
- CANCELED
+ REJECTED
}
diff --git a/src/main/java/ru/practicum/shareit/item/Comment.java b/src/main/java/ru/practicum/shareit/item/Comment.java
new file mode 100644
index 0000000..107457e
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/Comment.java
@@ -0,0 +1,36 @@
+package ru.practicum.shareit.item;
+
+import jakarta.persistence.*;
+import lombok.*;
+import ru.practicum.shareit.user.User;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@RequiredArgsConstructor
+@AllArgsConstructor
+@ToString
+@EqualsAndHashCode(of = {"id"})
+@Entity
+@Table(name = "comments")
+public class Comment {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(length = 250)
+ private String text;
+
+ @ManyToOne
+ @JoinColumn(name = "item_id", nullable = false)
+ private Item item;
+
+ @ManyToOne
+ @JoinColumn(name = "user_id")
+ private User user;
+
+ @Column(name = "created", nullable = false)
+ private LocalDateTime created;
+
+}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/item/CommentDto.java b/src/main/java/ru/practicum/shareit/item/CommentDto.java
new file mode 100644
index 0000000..bd2daa4
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/CommentDto.java
@@ -0,0 +1,30 @@
+package ru.practicum.shareit.item;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.user.User;
+import ru.practicum.shareit.validation.CreateObject;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CommentDto {
+
+ private Long id;
+
+ @NotNull(groups = {CreateObject.class}, message = "комментарий должен быть указан.")
+ @NotBlank(groups = {CreateObject.class}, message = "Комментарий не может быть пустым.")
+ private String text;
+
+ private Item item;
+
+ private User user;
+
+ private LocalDateTime created;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/CommentDtoOutput.java b/src/main/java/ru/practicum/shareit/item/CommentDtoOutput.java
new file mode 100644
index 0000000..2e76ce5
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/CommentDtoOutput.java
@@ -0,0 +1,24 @@
+package ru.practicum.shareit.item;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CommentDtoOutput {
+
+ private Long id;
+
+ private String text;
+
+ private ItemDtoShort item;
+
+ private String authorName;
+
+ private LocalDateTime created;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/CommentDtoShort.java b/src/main/java/ru/practicum/shareit/item/CommentDtoShort.java
new file mode 100644
index 0000000..2e4fa12
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/CommentDtoShort.java
@@ -0,0 +1,24 @@
+package ru.practicum.shareit.item;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CommentDtoShort {
+
+ private Long id;
+
+ private String text;
+
+ private ItemDtoShort item;
+
+ private String authorName;
+
+ private LocalDateTime created;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/CommentMapper.java
new file mode 100644
index 0000000..60d09b9
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/CommentMapper.java
@@ -0,0 +1,84 @@
+package ru.practicum.shareit.item;
+
+import java.time.LocalDateTime;
+
+public class CommentMapper {
+
+ public static CommentDto toCommentDto(Comment comment) {
+ if (comment == null) {
+ return null;
+ }
+ CommentDto commentDto = new CommentDto();
+
+ commentDto.setId(comment.getId());
+ commentDto.setText(comment.getText());
+ commentDto.setItem(comment.getItem());
+ commentDto.setUser(comment.getUser());
+ commentDto.setCreated(comment.getCreated());
+
+ return commentDto;
+ }
+
+ public static CommentDtoOutput toCommentDtoOutput(Comment comment) {
+ if (comment == null) {
+ return null;
+ }
+ CommentDtoOutput commentDto = new CommentDtoOutput();
+
+ commentDto.setId(comment.getId());
+ commentDto.setText(comment.getText());
+ commentDto.setItem(ItemMapper.toItemDtoShort(comment.getItem()));
+ commentDto.setAuthorName(comment.getUser().getName());
+ commentDto.setCreated(comment.getCreated());
+
+ return commentDto;
+ }
+
+ public static CommentDtoShort toCommentDtoShort(Comment comment) {
+ if (comment == null) {
+ return null;
+ }
+ CommentDtoShort commentDto = new CommentDtoShort();
+
+ commentDto.setId(comment.getId());
+ commentDto.setText(comment.getText());
+ commentDto.setItem(ItemMapper.toItemDtoShort(comment.getItem()));
+ commentDto.setAuthorName(comment.getUser().getName());
+ commentDto.setCreated(comment.getCreated());
+
+ return commentDto;
+ }
+
+ public static Comment toComment(CommentDto commentDto) {
+ Comment comment = new Comment();
+
+ if (commentDto.getId() != null) {
+ if (commentDto.getId() > 0) {
+ comment.setId(commentDto.getId());
+ }
+ }
+ if (commentDto.getText() != null) {
+ if (!commentDto.getText().trim().isEmpty()) {
+ comment.setText(commentDto.getText().trim());
+ }
+ }
+ if (commentDto.getItem().getId() != null) {
+ if (commentDto.getItem().getId() > 0) {
+ comment.setItem(commentDto.getItem());
+ }
+ }
+ if (commentDto.getUser().getId() != null) {
+ if (commentDto.getUser().getId() > 0) {
+ comment.setUser(commentDto.getUser());
+ }
+ }
+ if (commentDto.getCreated() != null) {
+ if (!commentDto.getCreated().isBefore(LocalDateTime.now())) {
+ comment.setCreated(commentDto.getCreated());
+ }
+ }
+
+ return comment;
+ }
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/CommentRepository.java
new file mode 100644
index 0000000..55f2ae5
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/CommentRepository.java
@@ -0,0 +1,9 @@
+package ru.practicum.shareit.item;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface CommentRepository extends JpaRepository {
+
+}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/item/Item.java b/src/main/java/ru/practicum/shareit/item/Item.java
index 70da0eb..99e8100 100644
--- a/src/main/java/ru/practicum/shareit/item/Item.java
+++ b/src/main/java/ru/practicum/shareit/item/Item.java
@@ -1,16 +1,24 @@
package ru.practicum.shareit.item;
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.*;
import lombok.*;
-import ru.practicum.shareit.request.ItemRequest;
+import ru.practicum.shareit.booking.Booking;
+import ru.practicum.shareit.request.Request;
import ru.practicum.shareit.user.User;
+import java.util.List;
+
@Getter
@Setter
@RequiredArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode(of = {"id"})
+@JsonIdentityInfo(
+ generator = ObjectIdGenerators.PropertyGenerator.class,
+ property = "id")
@Entity
@Table(name = "items")
public class Item {
@@ -24,14 +32,21 @@ public class Item {
@Column(length = 250)
private String description;
- @Column(nullable = false)
+ @Column(name = "is_available", nullable = false)
private Boolean available;
@ManyToOne
- @JoinColumn(name = "owner", nullable = false)
+ @JoinColumn(name = "owner_id", nullable = false)
private User owner;
@OneToOne
- @JoinColumn(name = "request")
- private ItemRequest request;
+ @JoinColumn(name = "request_id")
+ private Request request;
+
+ @OneToMany(mappedBy = "item")
+ private List comments;
+
+ @OneToMany(mappedBy = "item")
+ private List bookings;
+
}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java
index 349551e..affabdd 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemController.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemController.java
@@ -1,5 +1,6 @@
package ru.practicum.shareit.item;
+import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -10,34 +11,34 @@
@RestController
@RequestMapping("/items")
+@RequiredArgsConstructor
public class ItemController {
private final ItemService itemService;
- public ItemController(ItemService itemService) {
- this.itemService = itemService;
- }
-
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
- public ItemDto addItem(@Validated(CreateObject.class) @RequestBody ItemDto itemDto,
- @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
- return ItemMapper.toItemDto(itemService.addItem(idUser, itemDto));
+ public ItemDtoOutput addItem(@Validated(CreateObject.class) @RequestBody ItemDto itemDto,
+ @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
+ return ItemMapper.toItemDtoOutput(itemService.addItem(idUser, itemDto), idUser);
}
@PatchMapping("/{idItem}")
- public ItemDto updateItem(@PathVariable Long idItem, @Validated(UpdateObject.class) @RequestBody ItemDto itemDto,
- @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
- return ItemMapper.toItemDto(itemService.updateItem(idUser, idItem, itemDto));
+ public ItemDtoOutput updateItem(@PathVariable Long idItem,
+ @Validated(UpdateObject.class) @RequestBody ItemDto itemDto,
+ @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
+ return ItemMapper.toItemDtoOutput(itemService.updateItem(idUser, idItem, itemDto), idUser);
}
@GetMapping("/{idItem}")
- public ItemDto getItemById(@PathVariable Long idItem) {
- return ItemMapper.toItemDto(itemService.getItemById(idItem));
+ public ItemDtoOutput getItemById(@PathVariable Long idItem,
+ @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
+ return ItemMapper.toItemDtoOutput(itemService.getItemById(idItem), idUser);
}
@GetMapping
- public List getAllItemsByUser(@RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
- return itemService.getAllItems(idUser).stream().map(ItemMapper::toItemDto).toList();
+ public List getAllItemsByUser(@RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
+ return itemService.getAllItems(idUser).stream()
+ .map(item -> ItemMapper.toItemDtoOutput(item, idUser)).toList();
}
@DeleteMapping("/{idItem}")
@@ -47,8 +48,15 @@ public void removeItem(@PathVariable Long idItem,
}
@GetMapping("/search")
- public List searchItemsByText(@RequestParam String text) {
- return itemService.searchItems(text).stream().map(ItemMapper::toItemDto).toList();
+ public List searchItemsByText(@RequestParam String text,
+ @RequestHeader(value = "X-Sharer-User-Id") Long idUser) {
+ return itemService.searchItems(text).stream()
+ .map(item -> ItemMapper.toItemDtoOutput(item, idUser)).toList();
}
+ @PostMapping("/{itemId}/comment")
+ public CommentDtoOutput addCommentToItem(@RequestHeader("X-Sharer-User-Id") Long userId,
+ @PathVariable Long itemId, @RequestBody CommentDto commentDto) {
+ return CommentMapper.toCommentDtoOutput((itemService.saveComment(userId, itemId, commentDto)));
+ }
}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemDto.java b/src/main/java/ru/practicum/shareit/item/ItemDto.java
index a024656..2fb9d3e 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemDto.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemDto.java
@@ -1,15 +1,17 @@
package ru.practicum.shareit.item;
-import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
-import ru.practicum.shareit.request.ItemRequest;
+import ru.practicum.shareit.booking.Booking;
+import ru.practicum.shareit.request.Request;
import ru.practicum.shareit.user.User;
import ru.practicum.shareit.validation.CreateObject;
+import java.util.List;
+
@Data
@AllArgsConstructor
@NoArgsConstructor
@@ -30,9 +32,14 @@ public class ItemDto {
private User owner;
- private ItemRequest request;
+ private Request request;
+
+ private List comments;
+ private List bookings;
+ private Booking lastBooking;
+ private Booking nextBooking;
}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemDtoOutput.java b/src/main/java/ru/practicum/shareit/item/ItemDtoOutput.java
new file mode 100644
index 0000000..36ff82c
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/ItemDtoOutput.java
@@ -0,0 +1,37 @@
+package ru.practicum.shareit.item;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.booking.BookingDtoShort;
+import ru.practicum.shareit.request.Request;
+import ru.practicum.shareit.user.UserDtoShort;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ItemDtoOutput {
+
+ private Long id;
+
+ private String name;
+
+ private String description;
+
+ private Boolean available;
+
+ private UserDtoShort owner;
+
+ private Request request;
+
+ private List comments;
+
+ private List bookings;
+
+ private BookingDtoShort lastBooking;
+
+ private BookingDtoShort nextBooking;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemDtoShort.java b/src/main/java/ru/practicum/shareit/item/ItemDtoShort.java
new file mode 100644
index 0000000..8dc3627
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/ItemDtoShort.java
@@ -0,0 +1,20 @@
+package ru.practicum.shareit.item;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ItemDtoShort {
+
+ private Long id;
+
+ private String name;
+
+ private String description;
+
+ private Boolean available;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/ItemMapper.java
index b2c081b..d076fa1 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemMapper.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java
@@ -1,33 +1,159 @@
package ru.practicum.shareit.item;
+import ru.practicum.shareit.booking.Booking;
+import ru.practicum.shareit.booking.BookingMapper;
+import ru.practicum.shareit.booking.BookingStatus;
+import ru.practicum.shareit.user.UserMapper;
+
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+
public class ItemMapper {
public static ItemDto toItemDto(Item item) {
- return new ItemDto(
- item.getId(),
- item.getName(),
- item.getDescription(),
- item.getAvailable(),
- item.getOwner(),
- item.getRequest()
- );
+ if (item == null) {
+ return null;
+ }
+ ItemDto itemDto = new ItemDto();
+
+ itemDto.setId(item.getId());
+ itemDto.setName(item.getName());
+ itemDto.setDescription(item.getDescription());
+ itemDto.setAvailable(item.getAvailable());
+ itemDto.setOwner(item.getOwner());
+ itemDto.setRequest(item.getRequest());
+ itemDto.setComments(item.getComments());
+ itemDto.setBookings(item.getBookings());
+
+ return itemDto;
+ }
+
+ public static ItemDtoOutput toItemDtoOutput(Item item, Long userId) {
+ if (item == null) {
+ return null;
+ }
+ ItemDtoOutput itemDto = new ItemDtoOutput();
+
+ itemDto.setId(item.getId());
+ itemDto.setName(item.getName());
+ itemDto.setDescription(item.getDescription());
+ itemDto.setAvailable(item.getAvailable());
+ itemDto.setOwner(UserMapper.toUserDtoShort(item.getOwner()));
+ itemDto.setRequest(item.getRequest());
+ List comments = Optional.ofNullable(item.getComments()).orElse(Collections.emptyList());
+ if (!comments.isEmpty()) {
+ itemDto.setComments(comments.stream().map(CommentMapper::toCommentDtoShort).toList());
+ } else {
+ itemDto.setComments(Collections.emptyList());
+ }
+ List bookings = Optional.ofNullable(item.getBookings()).orElse(Collections.emptyList());
+ if (!bookings.isEmpty()) {
+ if (itemDto.getOwner().getId().equals(userId)) {
+ itemDto.setBookings(bookings.stream().map(BookingMapper::toBookingDtoShort).toList());
+ itemDto.setLastBooking(BookingMapper.toBookingDtoShort(findLastBooking(bookings)));
+ itemDto.setNextBooking(BookingMapper.toBookingDtoShort(findNextBooking(bookings)));
+ } else {
+ itemDto.setBookings(Collections.emptyList());
+ itemDto.setLastBooking(null);
+ itemDto.setNextBooking(null);
+ }
+ } else {
+ itemDto.setBookings(Collections.emptyList());
+ itemDto.setLastBooking(null);
+ itemDto.setNextBooking(null);
+ }
+
+ return itemDto;
+ }
+
+ public static ItemDtoShort toItemDtoShort(Item item) {
+ if (item == null) {
+ return null;
+ }
+ ItemDtoShort itemDto = new ItemDtoShort();
+
+ itemDto.setId(item.getId());
+ itemDto.setName(item.getName());
+ itemDto.setDescription(item.getDescription());
+ itemDto.setAvailable(item.getAvailable());
+
+ return itemDto;
}
public static Item toItem(ItemDto itemDto) {
+ Item item = new Item();
+
+ if (itemDto.getId() != null) {
+ if (itemDto.getId() > 0) {
+ item.setId(itemDto.getId());
+ }
+ }
if (itemDto.getName() != null) {
- itemDto.setName(itemDto.getName().trim());
+ item.setName(itemDto.getName().trim());
}
if (itemDto.getDescription() != null) {
- itemDto.setDescription(itemDto.getDescription().trim());
- }
- return new Item(
- null,
- itemDto.getName(),
- itemDto.getDescription(),
- itemDto.getAvailable(),
- null,
- null
- );
+ item.setDescription(itemDto.getDescription().trim());
+ }
+ if (itemDto.getAvailable() != null) {
+ item.setAvailable(itemDto.getAvailable());
+ }
+ if (itemDto.getOwner().getId() != null) {
+ if (itemDto.getOwner().getId() > 0) {
+ item.setOwner(itemDto.getOwner());
+ }
+ }
+ if (itemDto.getRequest() != null) {
+ if (itemDto.getRequest().getId() > 0) {
+ item.setRequest(itemDto.getRequest());
+ }
+ }
+ if (itemDto.getComments() != null) {
+ if (!itemDto.getComments().isEmpty()) {
+ item.setComments(itemDto.getComments());
+ }
+ }
+ if (itemDto.getBookings() != null) {
+ if (!itemDto.getBookings().isEmpty()) {
+ item.setBookings(itemDto.getBookings());
+ }
+ }
+
+ return item;
}
+ /**
+ * Метод поиска первой аренды после текущего момента времени.
+ *
+ * @param bookings список бронирований.
+ * @return следующее бронирование после текущего момента времени.
+ */
+ private static Booking findNextBooking(List bookings) {
+ return Optional.ofNullable(bookings)
+ .filter(list -> !list.isEmpty())
+ .flatMap(list -> list.stream()
+ .filter(b -> b.getStart().isAfter(LocalDateTime.now()))
+ .filter(b -> b.getStatus().equals(BookingStatus.APPROVED) ||
+ b.getStatus().equals(BookingStatus.WAITING))
+ .min(Comparator.comparing(Booking::getStart)))
+ .orElse(null);
+ }
+
+ /**
+ * Метод поиска последней аренды до текущего момента времени.
+ *
+ * @param bookings список бронирований.
+ * @return последнее бронирование до текущего момента времени.
+ */
+ private static Booking findLastBooking(List bookings) {
+ return Optional.ofNullable(bookings)
+ .filter(list -> !list.isEmpty())
+ .flatMap(list -> list.stream()
+ .filter(b -> b.getEnd().isBefore(LocalDateTime.now()))
+ .filter(b -> b.getStatus().equals(BookingStatus.APPROVED))
+ .max(Comparator.comparing(Booking::getEnd)))
+ .orElse(null);
+ }
}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/src/main/java/ru/practicum/shareit/item/ItemService.java
index d89d720..ba5bf8a 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemService.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemService.java
@@ -15,4 +15,7 @@ public interface ItemService {
List
- getAllItems(Long idUser);
List
- searchItems(String text);
+
+ Comment saveComment(Long userId, Long itemId, CommentDto inputCommentDto);
+
}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java
index 8459a79..edaf54d 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java
@@ -3,12 +3,15 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
+import ru.practicum.shareit.booking.Booking;
import ru.practicum.shareit.exception.NotFoundException;
import ru.practicum.shareit.exception.RestrictedAccessException;
import ru.practicum.shareit.exception.ValidationException;
import ru.practicum.shareit.user.User;
+import ru.practicum.shareit.user.UserMapper;
import ru.practicum.shareit.user.UserRepository;
+import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@@ -18,10 +21,12 @@ public class ItemServiceImpl implements ItemService {
private final ItemRepository itemRepository;
private final UserRepository userRepository;
+ private final CommentRepository commentRepository;
- public ItemServiceImpl(ItemRepository itemRepository, UserRepository userRepository) {
+ public ItemServiceImpl(ItemRepository itemRepository, UserRepository userRepository, CommentRepository commentRepository) {
this.itemRepository = itemRepository;
this.userRepository = userRepository;
+ this.commentRepository = commentRepository;
}
/**
@@ -40,10 +45,10 @@ public Item addItem(Long idUser, ItemDto itemDto) {
log.info(error);
throw new NotFoundException(error);
}
+ itemDto.setOwner(userRepository.findById(idUser).get());
Item result = ItemMapper.toItem(itemDto);
- result.setOwner(userRepository.findById(idUser).get());
itemRepository.save(result);
- log.info("Добавлена вещь [ {} ] пользователем [ {} ]", result, idUser);
+ log.info("Добавлена вещь [ {} ] пользователем [ {} ]", result.getId(), idUser);
return result;
}
@@ -76,21 +81,21 @@ public Item updateItem(Long idUser, Long idItem, ItemDto itemDto) {
log.info(error);
throw new RestrictedAccessException(error);
}
- Item newItem = ItemMapper.toItem(itemDto);
- newItem.setId(idItem);
- newItem.setOwner(oldItem.get().getOwner());
- newItem.setRequest(oldItem.get().getRequest());
- if (newItem.getName() == null) {
- newItem.setName(oldItem.get().getName());
+ itemDto.setId(idItem);
+ itemDto.setOwner(oldItem.get().getOwner());
+ itemDto.setRequest(oldItem.get().getRequest());
+ if (itemDto.getName() == null) {
+ itemDto.setName(oldItem.get().getName());
}
- if (newItem.getDescription() == null) {
- newItem.setDescription(oldItem.get().getDescription());
+ if (itemDto.getDescription() == null) {
+ itemDto.setDescription(oldItem.get().getDescription());
}
- if (newItem.getAvailable() == null) {
- newItem.setAvailable(oldItem.get().getAvailable());
+ if (itemDto.getAvailable() == null) {
+ itemDto.setAvailable(oldItem.get().getAvailable());
}
+ Item newItem = ItemMapper.toItem(itemDto);
itemRepository.save(newItem);
- log.info("Обновлены данные вещи [ {} ]", newItem);
+ log.info("Обновлены данные вещи [ {} ]", ItemMapper.toItemDtoShort(newItem));
return newItem;
}
@@ -154,7 +159,7 @@ public List
- getAllItems(Long idUser) {
throw new NotFoundException(error);
}
List
- result = itemRepository.findAllByOwner(user.get(), Sort.by("name"));
- log.info("Получен список всех вещей пользователя [ {} ] : [ {} ]", user.get(), result);
+ log.info("Получен список всех вещей пользователя [ {} ] : [ {} ]", UserMapper.toUserDtoShort(user.get()), result.size());
return result;
}
@@ -170,7 +175,43 @@ public List
- searchItems(String text) {
return List.of();
}
List
- result = itemRepository.findAllByText(text);
- log.info("Получен список вещей по поисковому запросу [ {} ] : [ {} ]", text, result);
+ log.info("Получен список вещей по поисковому запросу [ {} ] : [ {} ]", text, result.size());
+ return result;
+ }
+
+ /**
+ * Добавить комментарий к вещи пользователем, действительно бравшим вещь в аренду.
+ *
+ * @param bookerId ID пользователя, добавляющего комментарий.
+ * @param itemId ID вещи, которой оставляется комментарий.
+ */
+ @Override
+ public Comment saveComment(Long bookerId, Long itemId, CommentDto commentDto) {
+
+ User userFromBd = userRepository.findById(bookerId).orElseThrow(() ->
+ new NotFoundException("Ошибка при сохранении комментария к вещи с ID = " + itemId
+ + " пользователя с ID = " + bookerId + " в БД. В БД отсутствует запись о пользователе."));
+ Item itemFromBd = itemRepository.findById(itemId).orElseThrow(() ->
+ new NotFoundException("Ошибка при сохранении комментария к вещи с ID = " + itemId
+ + " пользователя с ID = " + bookerId + " в БД. В БД отсутствует запись о вещи."));
+ List bookings = itemFromBd.getBookings();
+ boolean isBooker = false;
+ for (Booking b : bookings) {
+ if (b.getBooker().getId().equals(bookerId) && b.getEnd().isBefore(LocalDateTime.now())) {
+ isBooker = true;
+ break;
+ }
+ }
+ if (!isBooker) {
+ throw new ValidationException("Ошибка при сохранении комментария к вещи с ID = " + itemId
+ + " пользователя с ID = " + bookerId + " в БД. Пользователь не арендовал эту вещь.");
+ }
+ commentDto.setItem(itemFromBd);
+ commentDto.setUser(userFromBd);
+ commentDto.setCreated(LocalDateTime.now());
+ Comment result = CommentMapper.toComment(commentDto);
+ result = commentRepository.save(result);
+ log.info("Комментарий к вещи успешно добавлен. Данные комментария: {}", CommentMapper.toCommentDtoShort(result));
return result;
}
diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/Request.java
similarity index 71%
rename from src/main/java/ru/practicum/shareit/request/ItemRequest.java
rename to src/main/java/ru/practicum/shareit/request/Request.java
index e1d70a5..2e67520 100644
--- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java
+++ b/src/main/java/ru/practicum/shareit/request/Request.java
@@ -2,6 +2,7 @@
import jakarta.persistence.*;
import lombok.*;
+import ru.practicum.shareit.item.Item;
import ru.practicum.shareit.user.User;
import java.time.LocalDateTime;
@@ -13,8 +14,8 @@
@ToString
@EqualsAndHashCode(of = {"id"})
@Entity
-@Table(name = "item_requests")
-public class ItemRequest {
+@Table(name = "requests")
+public class Request {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@@ -23,9 +24,12 @@ public class ItemRequest {
private String description;
@ManyToOne
- @JoinColumn(name = "requestor", nullable = false)
+ @JoinColumn(name = "requestor_id", nullable = false)
private User requestor;
+ @OneToOne(mappedBy = "request")
+ private Item requestItem;
+
@Column(nullable = false)
private LocalDateTime created;
}
diff --git a/src/main/java/ru/practicum/shareit/user/User.java b/src/main/java/ru/practicum/shareit/user/User.java
index a1c7b66..07d790c 100644
--- a/src/main/java/ru/practicum/shareit/user/User.java
+++ b/src/main/java/ru/practicum/shareit/user/User.java
@@ -2,12 +2,17 @@
import jakarta.persistence.*;
import lombok.*;
+import ru.practicum.shareit.booking.Booking;
+import ru.practicum.shareit.item.Comment;
+import ru.practicum.shareit.item.Item;
+
+import java.util.List;
@Getter
@Setter
+@ToString
@RequiredArgsConstructor
@AllArgsConstructor
-@ToString
@EqualsAndHashCode(of = {"id"})
@Entity
@Table(name = "users")
@@ -21,4 +26,14 @@ public class User {
@Column(length = 50, unique = true)
private String email;
+
+ @OneToMany(mappedBy = "owner")
+ private List
- items;
+
+ @OneToMany(mappedBy = "booker")
+ private List bookings;
+
+ @OneToMany(mappedBy = "user")
+ private List comments;
+
}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java
index 2c9a481..38dff38 100644
--- a/src/main/java/ru/practicum/shareit/user/UserController.java
+++ b/src/main/java/ru/practicum/shareit/user/UserController.java
@@ -1,5 +1,6 @@
package ru.practicum.shareit.user;
+import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -10,32 +11,29 @@
@RestController
@RequestMapping("/users")
+@RequiredArgsConstructor
public class UserController {
private final UserService userService;
- public UserController(UserService userService) {
- this.userService = userService;
- }
-
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
- public UserDto addUser(@Validated(CreateObject.class) @RequestBody UserDto userDto) {
- return UserMapper.toUserDto(userService.addUser(userDto));
+ public UserDtoOutput addUser(@Validated(CreateObject.class) @RequestBody UserDto userDto) {
+ return UserMapper.toUserDtoOutput(userService.addUser(userDto));
}
@PatchMapping("/{idUser}")
- public UserDto updateUser(@PathVariable Long idUser, @Validated(UpdateObject.class) @RequestBody UserDto userDto) {
- return UserMapper.toUserDto(userService.updateUser(idUser, userDto));
+ public UserDtoOutput updateUser(@PathVariable Long idUser, @Validated(UpdateObject.class) @RequestBody UserDto userDto) {
+ return UserMapper.toUserDtoOutput(userService.updateUser(idUser, userDto));
}
@GetMapping("/{idUser}")
- public UserDto getUserById(@PathVariable Long idUser) {
- return UserMapper.toUserDto(userService.getUserById(idUser));
+ public UserDtoOutput getUserById(@PathVariable Long idUser) {
+ return UserMapper.toUserDtoOutput(userService.getUserById(idUser));
}
@GetMapping
- public List getAllUsers() {
- return userService.getAllUsers().stream().map(UserMapper::toUserDto).toList();
+ public List getAllUsers() {
+ return userService.getAllUsers().stream().map(UserMapper::toUserDtoOutput).toList();
}
@DeleteMapping("/{idUser}")
diff --git a/src/main/java/ru/practicum/shareit/user/UserDto.java b/src/main/java/ru/practicum/shareit/user/UserDto.java
index eb3315f..122a434 100644
--- a/src/main/java/ru/practicum/shareit/user/UserDto.java
+++ b/src/main/java/ru/practicum/shareit/user/UserDto.java
@@ -6,9 +6,14 @@
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import ru.practicum.shareit.booking.Booking;
+import ru.practicum.shareit.item.Comment;
+import ru.practicum.shareit.item.Item;
import ru.practicum.shareit.validation.CreateObject;
import ru.practicum.shareit.validation.UpdateObject;
+import java.util.List;
+
@Data
@AllArgsConstructor
@NoArgsConstructor
@@ -24,4 +29,10 @@ public class UserDto {
@Email(groups = {CreateObject.class, UpdateObject.class}, message = "Email должен быть указан корректно.")
private String email;
+ private List
- items;
+
+ private List bookings;
+
+ private List comments;
+
}
diff --git a/src/main/java/ru/practicum/shareit/user/UserDtoOutput.java b/src/main/java/ru/practicum/shareit/user/UserDtoOutput.java
new file mode 100644
index 0000000..fd7a87b
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/UserDtoOutput.java
@@ -0,0 +1,29 @@
+package ru.practicum.shareit.user;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.booking.BookingDtoShort;
+import ru.practicum.shareit.item.CommentDtoShort;
+import ru.practicum.shareit.item.ItemDtoShort;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserDtoOutput {
+
+ private Long id;
+
+ private String name;
+
+ private String email;
+
+ private List items;
+
+ private List bookings;
+
+ private List comments;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/user/UserDtoShort.java b/src/main/java/ru/practicum/shareit/user/UserDtoShort.java
new file mode 100644
index 0000000..7bb1143
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/UserDtoShort.java
@@ -0,0 +1,18 @@
+package ru.practicum.shareit.user;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserDtoShort {
+
+ private Long id;
+
+ private String name;
+
+ private String email;
+
+}
diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/src/main/java/ru/practicum/shareit/user/UserMapper.java
index 9e29e22..400b2ec 100644
--- a/src/main/java/ru/practicum/shareit/user/UserMapper.java
+++ b/src/main/java/ru/practicum/shareit/user/UserMapper.java
@@ -1,27 +1,96 @@
package ru.practicum.shareit.user;
+import ru.practicum.shareit.booking.BookingMapper;
+import ru.practicum.shareit.item.ItemMapper;
+import ru.practicum.shareit.item.CommentMapper;
+
+import java.util.Collections;
+import java.util.Optional;
+
public class UserMapper {
public static UserDto toUserDto(User user) {
- return new UserDto(
- user.getId(),
- user.getName(),
- user.getEmail()
- );
+ if (user == null) {
+ return null;
+ }
+ UserDto userDto = new UserDto();
+
+ userDto.setId(user.getId());
+ userDto.setName(user.getName());
+ userDto.setEmail(user.getEmail());
+ userDto.setItems(user.getItems());
+ userDto.setBookings(user.getBookings());
+ userDto.setComments(user.getComments());
+
+ return userDto;
+ }
+
+ public static UserDtoOutput toUserDtoOutput(User user) {
+ if (user == null) {
+ return null;
+ }
+ UserDtoOutput userDto = new UserDtoOutput();
+
+ userDto.setId(user.getId());
+ userDto.setName(user.getName());
+ userDto.setEmail(user.getEmail());
+ userDto.setItems(Optional.ofNullable(user.getItems())
+ .map(items -> items.stream().map(ItemMapper::toItemDtoShort).toList())
+ .orElse(Collections.emptyList()));
+ userDto.setBookings(Optional.ofNullable(user.getBookings())
+ .map(bookings -> bookings.stream().map(BookingMapper::toBookingDtoShort).toList())
+ .orElse(Collections.emptyList()));
+ userDto.setComments(Optional.ofNullable(user.getComments())
+ .map(comments -> comments.stream().map(CommentMapper::toCommentDtoShort).toList())
+ .orElse(Collections.emptyList()));
+
+ return userDto;
+ }
+
+ public static UserDtoShort toUserDtoShort(User user) {
+ if (user == null) {
+ return null;
+ }
+ UserDtoShort userDto = new UserDtoShort();
+
+ userDto.setId(user.getId());
+ userDto.setName(user.getName());
+ userDto.setEmail(user.getEmail());
+
+ return userDto;
}
public static User toUser(UserDto userDto) {
- if (userDto.getEmail() != null) {
- userDto.setEmail(userDto.getEmail().trim());
+ User user = new User();
+
+ if (userDto.getId() != null) {
+ if (userDto.getId() > 0) {
+ user.setId(userDto.getId());
+ }
}
if (userDto.getName() != null) {
- userDto.setName(userDto.getName().trim());
+ user.setName(userDto.getName().trim());
}
- return new User(
- null,
- userDto.getName(),
- userDto.getEmail()
- );
+ if (userDto.getEmail() != null) {
+ user.setEmail(userDto.getEmail().trim());
+ }
+ if (userDto.getItems() != null) {
+ if (!userDto.getItems().isEmpty()) {
+ user.setItems(userDto.getItems());
+ }
+ }
+ if (userDto.getBookings() != null) {
+ if (!userDto.getBookings().isEmpty()) {
+ user.setBookings(userDto.getBookings());
+ }
+ }
+ if (userDto.getComments() != null) {
+ if (!userDto.getComments().isEmpty()) {
+ user.setComments(userDto.getComments());
+ }
+ }
+
+ return user;
}
}
diff --git a/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java
index a0bdc7e..0ca64a0 100644
--- a/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java
+++ b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java
@@ -58,21 +58,21 @@ public User updateUser(Long idUser, UserDto userDto) {
log.error(error);
throw new DataConflictException(error);
}
- User newUser = UserMapper.toUser(userDto);
- newUser.setId(idUser);
+ userDto.setId(idUser);
oldUser = userRepository.findById(idUser);
if (oldUser.isPresent()) {
- if (newUser.getName() == null) {
- newUser.setName(oldUser.get().getName());
+ if (userDto.getName() == null) {
+ userDto.setName(oldUser.get().getName());
}
- if (newUser.getEmail() == null) {
- newUser.setEmail(oldUser.get().getEmail());
+ if (userDto.getEmail() == null) {
+ userDto.setEmail(oldUser.get().getEmail());
}
} else {
String error = "Пользователь с id [ " + idUser + " ] не найден в БД при обновлении данных пользователя.";
log.info(error);
throw new NotFoundException(error);
}
+ User newUser = UserMapper.toUser(userDto);
userRepository.save(newUser);
log.info("Обновлен пользователь [ {} ]", newUser);
return newUser;
@@ -125,7 +125,8 @@ public void removeUser(Long idUser) {
throw new NotFoundException(error);
}
userRepository.delete(oldUser.get());
- log.info("По id [ {} ] успешно удален пользователь [ {} ].", idUser, oldUser.get());
+ log.info("По id [ {} ] успешно удален пользователь.", idUser);
+ // log.info("По id [ {} ] успешно удален пользователь [ {} ].", idUser, oldUser.get());
}
}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index 3dc5c53..0000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-spring.jpa.hibernate.ddl-auto=none
-spring.jpa.properties.hibernate.format_sql=true
-spring.sql.init.mode=always
-
-logging.level.org.springframework.orm.jpa=INFO
-logging.level.org.springframework.transaction=INFO
-logging.level.org.springframework.transaction.interceptor=TRACE
-logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
-
-spring.datasource.url=jdbc:h2:file:./db/shareit
-spring.datasource.driverClassName=org.h2.Driver
-spring.datasource.username=sa
-spring.datasource.password=password
-
-server.port=8080
-
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
new file mode 100644
index 0000000..faf6257
--- /dev/null
+++ b/src/main/resources/application.yaml
@@ -0,0 +1,20 @@
+spring:
+ application.name: shareit
+ main.banner-mode: off
+ datasource:
+ url: jdbc:postgresql://localhost:5432/shareit
+ driver-class-name: org.postgresql.Driver
+ username: shareituser
+ password: 12345678
+ jpa:
+ show-sql: true
+ hibernate:
+ ddl-auto: update
+ properties:
+ hibernate.jdbc.time_zone: UTC
+ dialect: org.hibernate.dialect.PostgreSQL95Dialect
+ format_sql: true
+ sql:
+ init:
+ mode: always
+
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index b3a1d1e..0f68bd1 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -1,36 +1,44 @@
-DROP TABLE IF EXISTS bookings;
-DROP TABLE IF EXISTS items;
-DROP TABLE IF EXISTS item_requests;
-DROP TABLE IF EXISTS users;
+DROP TABLE IF EXISTS requests CASCADE;
+DROP TABLE IF EXISTS comments CASCADE;
+DROP TABLE IF EXISTS bookings CASCADE;
+DROP TABLE IF EXISTS users CASCADE;
+DROP TABLE IF EXISTS items CASCADE;
-CREATE TABLE users (
- id LONG GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- name VARCHAR(100),
- email VARCHAR(50) UNIQUE
+CREATE TABLE IF NOT EXISTS users (
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ name VARCHAR(100),
+ email VARCHAR(50) UNIQUE
);
-CREATE TABLE item_requests (
- id LONG GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- description VARCHAR(250),
- requestor LONG NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
- created DATETIME DEFAULT (now())
+CREATE TABLE IF NOT EXISTS requests (
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ description VARCHAR(250) NOT NULL,
+ requestor_id BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ created TIMESTAMP WITHOUT TIME ZONE DEFAULT (now())
);
-CREATE TABLE items (
- id LONG GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- name VARCHAR(100),
- description VARCHAR(250),
- available BOOL,
- owner LONG NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
- request LONG DEFAULT NULL REFERENCES item_requests (id) ON DELETE SET NULL ON UPDATE CASCADE
+CREATE TABLE IF NOT EXISTS items (
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ name VARCHAR(100),
+ description VARCHAR(250),
+ is_available BOOL DEFAULT FALSE,
+ owner_id BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ request_id BIGINT DEFAULT NULL REFERENCES requests (id) ON DELETE SET NULL ON UPDATE CASCADE
);
-CREATE TABLE bookings (
- id LONG GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- start_ DATETIME,
- end_ DATETIME,
- item LONG NOT NULL REFERENCES items (id) ON DELETE CASCADE ON UPDATE CASCADE,
- booker LONG NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
- status VARCHAR(10) DEFAULT 'WAITING'
+CREATE TABLE IF NOT EXISTS bookings (
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ start_date TIMESTAMP WITHOUT TIME ZONE,
+ end_date TIMESTAMP WITHOUT TIME ZONE,
+ item_id BIGINT NOT NULL REFERENCES items (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ booker_id BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ status VARCHAR(10) DEFAULT 'WAITING'
);
+CREATE TABLE IF NOT EXISTS comments (
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ text VARCHAR(250),
+ item_id BIGINT NOT NULL REFERENCES items (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ user_id BIGINT DEFAULT NULL REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
+ created TIMESTAMP WITHOUT TIME ZONE DEFAULT (now())
+);
diff --git a/src/test/java/ru/practicum/shareit/ShareItTests.java b/src/test/java/ru/practicum/shareit/ShareItTests.java
deleted file mode 100644
index 4d79052..0000000
--- a/src/test/java/ru/practicum/shareit/ShareItTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package ru.practicum.shareit;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class ShareItTests {
-
- @Test
- void contextLoads() {
- }
-
-}