diff --git a/PostmanSprint11_add-friends-likes.json b/PostmanSprint11_add-friends-likes.json new file mode 100644 index 0000000..64be278 --- /dev/null +++ b/PostmanSprint11_add-friends-likes.json @@ -0,0 +1,3016 @@ +{ + "info": { + "_postman_id": "c48e59d5-4de8-4757-a8c4-c13e763036df", + "name": "add-friends-likes", + "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/23073145-c48e59d5-4de8-4757-a8c4-c13e763036df?action=share&source=collection_link&creator=23073145" + }, + "item": [ + { + "name": "users", + "item": [ + { + "name": "User create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = JSON.parse(pm.request.body.raw)\r", + "\r", + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Has user create response\", 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", + "});\r", + "pm.test(\"Test user 'email' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('email');\r", + " pm.expect(jsonData.email, `\"email\" must be \"${source.mail}\"`).to.eql(source.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", + " pm.expect(jsonData.name, `\"name\" must be \"${source.name}\"`).to.eql(source.name);\r", + "});\r", + "pm.test(\"Test user 'login' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('login');\r", + " pm.expect(jsonData.login, `\"login\" field must be \"${source.login}\"`).to.eql(source.login); \r", + "});\r", + "pm.test(\"Test user 'birthday' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('birthday');\r", + " pm.expect(jsonData.birthday, `\"birthday\" field must be \"${source.birthday}\"`).to.eql(source.birthday);\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = rnd.getUser();\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(user),\r", + " options: { raw: { language: 'json' } }\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" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore\",\n \"name\": \"Nick Name\",\n \"email\": \"mail@mail.ru\",\n \"birthday\": \"1946-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail login", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", 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" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore ullamco\",\n \"email\": \"yandex@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail email", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore ullamco\",\n \"name\": \"\",\n \"email\": \"mail.ru\",\n \"birthday\": \"1980-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail birthday", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore\",\n \"name\": \"\",\n \"email\": \"test@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = pm.collectionVariables.get(\"user\")\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Has user update response\", 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", + " pm.expect(jsonData.id, `\"id\" must be ${source.id}`).to.eql(source.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", + " pm.expect(jsonData.email, '\"email\" must be \"mail@yandex.ru\"').to.eql('mail@yandex.ru');\r", + "});\r", + "pm.test(\"Test user 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"est adipisicing\"').to.eql('est adipisicing');\r", + "});\r", + "pm.test(\"Test user 'login' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('login');\r", + " pm.expect(jsonData.login, '\"login\" field must be \"doloreUpdate\"').to.eql('doloreUpdate'); \r", + "});\r", + "pm.test(\"Test user 'birthday' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('birthday');\r", + " pm.expect(jsonData.birthday, '\"birthday\" field must be \"1976-09-20\"').to.eql('1976-09-20');\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user\", user);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"login\": \"doloreUpdate\",\r", + " \"name\": \"est adipisicing\",\r", + " \"id\": user.id,\r", + " \"email\": \"mail@yandex.ru\",\r", + " \"birthday\": \"1976-09-20\"\r", + " }),\r", + " options: { raw: { language: 'json' } }\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" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User update unknown", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user\", user);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"login\": \"doloreUpdate\",\r", + " \"name\": \"est adipisicing\",\r", + " \"id\": user.id+1,\r", + " \"email\": \"mail@yandex.ru\",\r", + " \"birthday\": \"1976-09-20\"\r", + " }),\r", + " options: { raw: { language: 'json' } }\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": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"doloreUpdate\",\n \"name\": \"est adipisicing\",\n \"id\": 9999,\n \"email\": \"mail@yandex.ru\",\n \"birthday\": \"1976-09-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list user response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test user[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "friends", + "item": [ + { + "name": "Friend add", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 has user2 friend\", function () {\r", + " pm.expect(response.json()[0].id).to.be.equal(user2_id);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 has have user1 friend\", function () {\r", + " pm.expect(response.json()[0].id).to.be.equal(user1_id)\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.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" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend add unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id+1);\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": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend get", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user_friends = pm.collectionVariables.get(\"user_friends\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.test(\"initially user1 should have 0 friends\", function () {\r", + " pm.expect(user_friends.length).to.be.equal(0);\r", + "});\r", + "\r", + "pm.test(\"finally user1 should have 1 friend\", function () {\r", + " pm.expect(pm.response.json().length).to.be.equal(1);\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user1_friends;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user1_friends = await api.getFriends(user1.id);\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"user_friends\", user1_friends);\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" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends" + ] + } + }, + "response": [] + }, + { + "name": "Friend get unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user.id+1);\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": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.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": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Not friend remove", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.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": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id + 4);\r", + " pm.collectionVariables.set(\"friend_id\", user2.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": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove unknown friend id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id+1);\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": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Get common friends", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user3_id = pm.collectionVariables.get(\"user3_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.test(\"user1 should have 1 common friend with user2\", function () {\r", + " pm.expect(pm.response.json().length).to.be.equal(1);\r", + " pm.expect(pm.response.json()[0].id).to.be.equal(user3_id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user3;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user3 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user3.id);\r", + " await api.addFriend(user1.id, user2.id);\r", + " await api.addFriend(user2.id, user3.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " pm.collectionVariables.set(\"user3_id\", user3.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" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/common/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "common", + "{{friend_id}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "films", + "item": [ + { + "name": "Film create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = JSON.parse(pm.request.body.raw)\r", + "\r", + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Has film create response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${source.name}\"`).to.eql(source.name);\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, `\"description\" must be \"${source.description}\"`).to.eql(source.description);\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, `\"releaseDate\" field must be \"${source.releaseDate}\"`).to.eql(source.releaseDate);\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, `\"duration\" field must be %{source.duration}`).to.eql(source.duration); \r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let film;\r", + " try {\r", + " film = rnd.getFilm();\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(film),\r", + " options: { raw: { language: 'json' } }\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" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"nisi eiusmod\",\n \"description\": \"adipisicing\",\n \"releaseDate\": \"1967-03-25\",\n \"duration\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", 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" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"\",\n \"description\": \"Description\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail description", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", 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" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Film name\",\n \"description\": \"Пятеро друзей ( комик-группа «Шарло»), приезжают в город Бризуль. Здесь они хотят разыскать господина Огюста Куглова, который задолжал им деньги, а именно 20 миллионов. о Куглов, который за время «своего отсутствия», стал кандидатом Коломбани.\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail releaseDate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", 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" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Description\",\n \"releaseDate\": \"1890-03-25\",\n \"duration\": 200\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail duration", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", 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" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Descrition\",\n \"releaseDate\": \"1980-03-25\",\n \"duration\": -200\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = pm.collectionVariables.get(\"film\")\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Has film update response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData.id, `\"id\" must be ${source.id}`).to.eql(source.id);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"Film Updated\"').to.eql('Film Updated');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film update decription\"').to.eql('New film update decription');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1989-04-17\"').to.eql('1989-04-17');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 190').to.eql(190); \r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"film\", film);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"id\": film.id,\r", + " \"name\": \"Film Updated\",\r", + " \"releaseDate\": \"1989-04-17\",\r", + " \"description\": \"New film update decription\",\r", + " \"duration\": 190,\r", + " \"rate\": 4\r", + " }),\r", + " options: { raw: { language: 'json' } }\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" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film update unknown", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"film\", film);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"id\": film.id+1,\r", + " \"name\": \"Film Updated\",\r", + " \"releaseDate\": \"1989-04-17\",\r", + " \"description\": \"New film update decription\",\r", + " \"duration\": 190,\r", + " \"rate\": 4\r", + " }),\r", + " options: { raw: { language: 'json' } }\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": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film get Popular", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const film1_id = pm.collectionVariables.get(\"film1_id\");\r", + "const film2_id = pm.collectionVariables.get(\"film2_id\");\r", + "const film3_id = pm.collectionVariables.get(\"film3_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list popular film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "const index1 = pm.response.json().findIndex(x => x.id == film1_id);\r", + "const index2 = pm.response.json().findIndex(x => x.id == film2_id);\r", + "const index3 = pm.response.json().findIndex(x => x.id == film3_id);\r", + "\r", + "pm.test(\"Test films сonsistency\", function () {\r", + " pm.expect(index1).to.be.above(index2);\r", + " pm.expect(index1).to.be.above(index3);\r", + " pm.expect(index3).to.be.above(index2);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user3, film1, film2, film3;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user3 = await api.addUser(rnd.getUser());\r", + " film1 = await api.addFilm(rnd.getFilm());\r", + " film2 = await api.addFilm(rnd.getFilm());\r", + " film3 = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film2.id, user1.id);\r", + " await api.addLike(film2.id, user2.id);\r", + " await api.addLike(film2.id, user3.id);\r", + " await api.addLike(film3.id, user1.id);\r", + " await api.addLike(film3.id, user2.id);\r", + " await api.addLike(film1.id, user1.id);\r", + " pm.collectionVariables.set(\"film1_id\", film1.id);\r", + " pm.collectionVariables.set(\"film2_id\", film2.id);\r", + " pm.collectionVariables.set(\"film3_id\", film3.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" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/popular?count=1000", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "popular" + ], + "query": [ + { + "key": "count", + "value": "1000" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "like", + "item": [ + { + "name": "Add like", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/films/\" + 45,\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " console.log(response.json())\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.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" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Add like unknown film", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.id+1);\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": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Add like unknown user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"id\", user.id+1);\r", + " pm.collectionVariables.set(\"film_id\", film.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": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Remove like", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film.id, user.id);\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.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" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Remove like unknown film", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film.id, user.id);\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.id+1);\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": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Remove like unknown user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film.id, user.id);\r", + " pm.collectionVariables.set(\"id\", user.id+1);\r", + " pm.collectionVariables.set(\"film_id\", film.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": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "API = class {", + " constructor(postman, verbose = false, baseUrl = \"http://localhost:8080\") {", + " this.baseUrl = baseUrl;", + " this.pm = postman;", + " this._verbose = verbose;", + " }", + "", + " async addUser(user, verbose=null) {", + " return this.post(\"/users\", user, \"Ошибка при добавлении нового пользователя: \", verbose);", + " }", + "", + " async addFilm(film, verbose=null) {", + " return this.post(\"/films\", film, \"Ошибка при добавлении нового фильма: \", verbose);", + " }", + "", + " async addFriend(userId, friendId, verbose=null) {", + " return this.put(\"/users/\" + userId + '/friends/' + friendId, null, \"Ошибка при добавлении нового фильма: \", verbose);", + " }", + "", + " async addLike(filmId, userId, verbose=null) {", + " return this.put(\"/films/\" + filmId + '/like/' + userId, null, \"Ошибка при добавлении лайка на фильм: \", verbose);", + " }", + "", + " async getFriends(userId, verbose=null) {", + " return this.get('/users/' + userId + '/friends', null, \"Ошибка при поиске друзей по id пользователя\", verbose);", + " }", + "", + " async post(path, body, errorText = \"Ошибка при выполнении post-запроса: \", verbose=null) {", + " return this.sendRequest(\"POST\", path, body, errorText, verbose);", + " }", + "", + " async patch(path, body = null, errorText = \"Ошибка при выполнении patch-запроса: \", verbose=null) {", + " return this.sendRequest(\"PATCH\", path, body, errorText, verbose);", + " }", + "", + " async get(path, body = null, errorText = \"Ошибка при выполнении get-запроса: \", verbose=null) {", + " return this.sendRequest(\"GET\", path, body, errorText, verbose);", + " }", + "", + " async put(path, body = null, errorText = \"Ошибка при выполнении put-запроса: \", verbose=null) {", + " return this.sendRequest(\"PUT\", path, body, errorText, verbose);", + " }", + "", + " async sendRequest(method, path, body=null, errorText = \"Ошибка при выполнении запроса: \", verbose=null) {", + " return new Promise((resolve, reject) => {", + " verbose = verbose == null ? this._verbose : verbose;", + " const request = {", + " url: this.baseUrl + path,", + " method: method,", + " body: body == null ? \"\" : JSON.stringify(body),", + " header: { \"Content-Type\": \"application/json\" },", + " };", + " if(verbose) {", + " console.log(\"Отправляю запрос: \", request);", + " }", + "", + " try {", + " this.pm.sendRequest(request, (error, response) => {", + " if(error || (response.code >= 400 && response.code <= 599)) {", + " let err = error ? error : JSON.stringify(response.json());", + " console.error(\"При выполнении запроса к серверу возникла ошика.\\n\", err,", + " \"\\nДля отладки проблемы повторите такой же запрос к вашей программе \" + ", + " \"на локальном компьютере. Данные запроса:\\n\", JSON.stringify(request));", + "", + " reject(new Error(errorText + err));", + " }", + " if(verbose) {", + " console.log(\"Результат обработки запроса: код состояния - \", response.code, \", тело: \", response.json());", + " }", + " if (response.stream.length === 0){", + " resolve(null);", + " }else{", + " resolve(response.json());", + " }", + " });", + " ", + " } catch(err) {", + " if(verbose) {", + " console.error(errorText, err);", + " }", + " return Promise.reject(err);", + " }", + " });", + " }", + "};", + "", + "RandomUtils = class {", + " constructor() {}", + "", + " getUser() {", + " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));", + " return {", + " name: pm.variables.replaceIn('{{$randomFullName}}'),", + " login: this.getWord(10),", + " email: pm.variables.replaceIn('{{$randomEmail}}'),", + " birthday: date.toISOString().slice(0,10)", + " };", + " }", + "", + " getFilm() {", + " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));", + " return {", + " name: this.getWord(15),", + " description: this.getWord(50),", + " releaseDate: date.toISOString().slice(0,10),", + " duration: Math.floor(Math.random() * (180 - 60 + 1) + 60)", + " };", + " }", + "", + " getWord(length = 1) {", + " let result = '';", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " const charactersLength = characters.length;", + " let counter = 0;", + " while (counter < length) {", + " result += characters.charAt(Math.floor(Math.random() * charactersLength));", + " counter += 1;", + " }", + " return result;", + " }", + "", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:8080", + "type": "string" + }, + { + "key": "id", + "value": "0" + }, + { + "key": "friend_id", + "value": "0" + }, + { + "key": "user_friends", + "value": "" + }, + { + "key": "is", + "value": "" + }, + { + "key": "user3_id", + "value": "" + }, + { + "key": "film1_id", + "value": "" + }, + { + "key": "film2_id", + "value": "" + }, + { + "key": "film3_id", + "value": "" + }, + { + "key": "film_id", + "value": "" + }, + { + "key": "user", + "value": "" + }, + { + "key": "film", + "value": "" + } + ] +} diff --git a/README.md b/README.md index 74abbb1..9f00859 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ _java-filmorate_ # Рейтинг фильмов -### Согласно задания спринта № 10 +### Согласно задания спринта № 11 ## выполнено Филипповских Сергеем _**Когорта-53**_ + +в файле PostmanSprint11_add-friends-likes.json находится скрипт для проверки API diff --git a/pom.xml b/pom.xml index c8dd765..57fafc4 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,12 @@ org.springframework.boot spring-boot-starter-validation + + org.zalando + logbook-spring-boot-starter + 3.9.0 + + diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java index dca451b..843905e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java +++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java @@ -5,8 +5,8 @@ @SpringBootApplication public class FilmorateApplication { - public static void main(String[] args) { - SpringApplication.run(FilmorateApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(FilmorateApplication.class, args); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java new file mode 100644 index 0000000..5694d83 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java @@ -0,0 +1,64 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Slf4j +@RestControllerAdvice +public class ErrorHandler { + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleValidationException(final ValidationException e) { + log.error(HttpStatus.BAD_REQUEST + " - " + e.getMessage()); + return new ErrorResponse(e.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) { + BindingResult bindingResult = e.getBindingResult(); + List allErrors = bindingResult.getAllErrors(); + String defaultMessage = allErrors.stream() + .map(error -> Objects.requireNonNull(error.getDefaultMessage())) + .collect(Collectors.joining(", ")); + log.error(HttpStatus.BAD_REQUEST + " - " + defaultMessage); + return new ErrorResponse(defaultMessage); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleNotFoundException(final NotFoundException e) { + log.error(HttpStatus.NOT_FOUND + " - " + e.getMessage()); + return new ErrorResponse(e.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse handleRunTimeException(final RuntimeException e) { + log.error(HttpStatus.INTERNAL_SERVER_ERROR + " - " + e.getMessage()); + return new ErrorResponse(e.getMessage()); + } + + @Getter + private static class ErrorResponse { + private final String error; + + public ErrorResponse(String error) { + this.error = error; + } + + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 19ca717..313431c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -1,80 +1,67 @@ package ru.yandex.practicum.filmorate.controller; import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.service.FilmService; -import java.time.LocalDate; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; -@RestController @Slf4j +@RestController @RequestMapping("/films") +@RequiredArgsConstructor public class FilmController { - private final Map films = new HashMap<>(); - - // получаем список фильмов - @GetMapping - public Collection findAll() { - return films.values(); - } + private final FilmService filmService; // добавляем фильм + @ResponseStatus(HttpStatus.CREATED) @PostMapping public Film create(@RequestBody @Valid Film film) { - // проверяем выполнение необходимых условий - checkFilm(film); - // формируем дополнительные данные - film.setId(getNextId()); - // сохраняем данные фильма - films.put(film.getId(), film); + filmService.create(film); return film; } - // вспомогательный метод для генерации идентификатора фильма - private long getNextId() { - long currentMaxId = films.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } - // обновляем данные о фильме @PutMapping - public Film update(@RequestBody @Valid Film newFilm) { - // проверяем необходимые условия - if (newFilm.getId() == null) { - throw new ValidationException("Id фильма должен быть указан"); - } - if (films.containsKey(newFilm.getId())) { - checkFilm(newFilm); - // если фильм с таким id найден и все условия соблюдены, обновляем его содержимое - films.put(newFilm.getId(), newFilm); - return newFilm; - } - throw new ValidationException("Фильм с id = " + newFilm.getId() + " не найден"); + public Film update(@RequestBody @Valid Film film) { + filmService.update(film); + return film; + } + + // получаем список фильмов + @GetMapping + public List findAll() { + return filmService.findAll(); + } + + // Получаем фильм по id + @GetMapping("/{filmId}") + public Film getFilmById(@PathVariable Integer filmId) { + return filmService.getById(filmId); } - // вспомогательный метод для проверки условий фильма - private void checkFilm(Film newFilm) { - if (newFilm.getName() == null || newFilm.getName().isBlank()) { - throw new ValidationException("Название фильма не может быть пустым"); - } - if (newFilm.getDescription().length() > 200) { - throw new ValidationException("Максимальная длина описания фильма - 200 символов"); - } - if (newFilm.getDuration() < 1) { - throw new ValidationException("Продолжительность фильма должна быть больше 1 секунды"); - } - if (newFilm.getReleaseDate().isBefore(LocalDate.parse("1895-12-28"))) { - throw new ValidationException("Минимальная дата выхода фильма 28.12.1895"); - } + // Добавляем like пользователя userId к фильму filmId + @PutMapping("/{filmId}/like/{userId}") + public Film addLike(@PathVariable Integer filmId, @PathVariable Integer userId) { + filmService.addLike(filmId, userId); + return filmService.getById(filmId); } + + // Удаляем like пользователя userId к фильму filmId + @DeleteMapping("/{filmId}/like/{userId}") + public Film deleteLike(@PathVariable Integer filmId, @PathVariable Integer userId) { + filmService.deleteLike(filmId, userId); + return filmService.getById(filmId); + } + + @GetMapping("/popular") + public List getListBestFilms(@RequestParam(defaultValue = "10") Integer count) { + return filmService.listBestFilms(count); + } + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 1ec812c..e63da94 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -1,94 +1,73 @@ package ru.yandex.practicum.filmorate.controller; import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.service.UserService; -import java.time.LocalDate; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; -@RestController @Slf4j +@RestController @RequestMapping("/users") +@RequiredArgsConstructor public class UserController { - private final Map users = new HashMap<>(); - - //Получаем список всех пользователей - @GetMapping - public Collection findAll() { - return users.values(); - } + private final UserService userService; // Добавляем пользователя + @ResponseStatus(HttpStatus.CREATED) @PostMapping public User create(@RequestBody @Valid User user) { - // проверяем выполнение необходимых условий - if (users.values().stream() - .anyMatch(u -> u.getEmail().equals(user.getEmail()))) { - throw new ValidationException("Этот email уже используется"); - } - checkUser(user); - // формируем дополнительные данные - if (user.getName() == null || user.getName().isBlank()) { - user.setName(user.getLogin()); - } - user.setId(getNextId()); - // сохраняем нового пользователя - users.put(user.getId(), user); + userService.create(user); + return user; + } + + // Обновляем данные пользователя + @PutMapping + public User update(@RequestBody @Valid User user) { + userService.update(user); return user; } + // Получаем список всех пользователей + @GetMapping + public List findAll() { + return userService.findAll(); + } - // вспомогательный метод для генерации идентификатора нового пользователя - private long getNextId() { - long currentMaxId = users.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; + // Получаем пользователя по id + @GetMapping("/{userId}") + public User getUserById(@PathVariable Integer userId) { + return userService.getById(userId); } - // Обновляем данные пользователя - @PutMapping - public User update(@RequestBody @Valid User newUser) { - // проверяем необходимые условия - if (newUser.getId() == null) { - throw new ValidationException("Id пользователя должен быть указан"); - } - if (users.containsKey(newUser.getId())) { - User oldUser = users.get(newUser.getId()); - checkUser(newUser); - if (!oldUser.getEmail().equals(newUser.getEmail())) { - if (users.values().stream() - .anyMatch(u -> u.getEmail().equals(newUser.getEmail()))) { - throw new ValidationException("Этот email уже используется"); - } - } - if (newUser.getName() == null || newUser.getName().isBlank()) { - newUser.setName(newUser.getLogin()); - } - users.put(newUser.getId(), newUser); - return newUser; - } - throw new ValidationException("Пользователь с id = " + newUser.getId() + " не найден"); + // Добавляем друга friendId для пользователя userId + @PutMapping("/{userId}/friends/{friendId}") + public User addFriend(@PathVariable Integer userId, @PathVariable Integer friendId) { + userService.addFriend(userId, friendId); + return userService.getById(userId); + } + + // Удаляем друга friendId у пользователя userId + @DeleteMapping("/{userId}/friends/{friendId}") + public User deleteFriend(@PathVariable Integer userId, @PathVariable Integer friendId) { + userService.deleteFriend(userId, friendId); + return userService.getById(userId); + } + + // Получаем список друзей пользователя userId + @GetMapping("/{userId}/friends") + public List getUserFriends(@PathVariable Integer userId) { + return userService.userFriends(userId); } - // вспомогательный метод для проверки данных условий пользователя - private void checkUser(User user) { - if (user.getEmail() == null || user.getEmail().isBlank() || !user.getEmail().contains("@")) { - throw new ValidationException("Email должен быть указан корректно"); - } - if (user.getLogin() == null || user.getLogin().isBlank() || user.getLogin().contains(" ")) { - throw new ValidationException("Логин должен быть задан и без пробелов"); - } - if (user.getBirthday().isAfter(LocalDate.now())) { - throw new ValidationException("День рождения не должен быть позже текущей даты"); - } + // Получаем общий список друзей пользователя userId и и пользователя otherUserId + @GetMapping("/{userId}/friends/common/{otherUserId}") + public List getCrossingFriends(@PathVariable Integer userId, @PathVariable Integer otherUserId) { + return userService.crossingFriends(userId, otherUserId); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java new file mode 100644 index 0000000..82e3f72 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package ru.yandex.practicum.filmorate.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index cc3b9b4..1c5b382 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,29 +1,43 @@ package ru.yandex.practicum.filmorate.model; -import jakarta.validation.constraints.*; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Data @Slf4j -@EqualsAndHashCode(of = { "name", "releaseDate" }) public class Film { - private Long id; + private Integer id; + + private Set likes = new HashSet<>(); @NotNull(message = "Необходимо указать название фильма") - @NotBlank(message = "Необходимо указать название фильма") + @NotBlank(message = "Название фильма не может быть пустым") private String name; @Size(min = 1, max = 200, message = "Описание фильма должно быть от 1 до 200 символов") private String description; - @MinimumDate(message = "Некорректная дата выхода фильма") + @MinimumDate(message = "Фильм не может выйти в прокат ранее 28.12.1895") private LocalDate releaseDate; - @Min(value = 1, message = "Продолжительность фильма должна быть не меньше 1 секунды") @NotNull(message = "Необходимо указать продолжительность фильма") + @Min(value = 1, message = "Продолжительность фильма должна быть не меньше 1 секунды") private int duration; + + public void addLike(Integer id) { + likes.add(id); + } + + public void removeLike(Integer id) { + likes.remove(id); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index b30bd5e..71c1c8c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -1,31 +1,40 @@ package ru.yandex.practicum.filmorate.model; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Past; +import jakarta.validation.constraints.*; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Data @Slf4j -@EqualsAndHashCode(of = { "email", "login" }) public class User { - private Long id; + private Integer id; - @Email(message = "Некорректный email") + private Set friends = new HashSet<>(); + + @Email(message = "Укажите корректный email") @NotNull(message = "Необходимо указать email") + @NotBlank(message = "Email не может быть пустым") private String email; @NotNull(message = "Необходимо указать логин") - @NotBlank(message = "Необходимо указать логин") + @NotBlank(message = "Логин не может быть пустым") + @Pattern(regexp = "^[A-Za-z0-9]+$", message = "Логин может содержать только буквы и цифры без пробелов и спецсимволов") private String login; private String name; - @Past(message = "Некорректная дата рождения") + @PastOrPresent(message = "Дата рождения не должна находиться в будущем") private LocalDate birthday; + + public void addFriend(Integer id) { + friends.add(id); + } + + public void removeFriend(Integer id) { + friends.remove(id); + } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java new file mode 100644 index 0000000..a925140 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -0,0 +1,73 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.FilmStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class FilmService { + private final FilmStorage filmStorage; + private final UserStorage userStorage; + + public Film create(Film film) { + return filmStorage.create(film); + } + + public Film update(Film film) { + return filmStorage.update(film); + } + + public Film getById(Integer id) { + return filmStorage.getById(id); + } + + public List findAll() { + return filmStorage.findAll(); + } + + // Ставим лайк фильму + public void addLike(Integer idFilm, Integer idUser) { + checkForLike(idFilm, idUser); + filmStorage.getById(idFilm).addLike(idUser); + } + + // Убираем лайк фильму + public void deleteLike(Integer idFilm, Integer idUser) { + checkForLike(idFilm, idUser); + filmStorage.getById(idFilm).removeLike(idUser); + } + + // Получаем список лучших фильмов + public List listBestFilms(int count) { + return filmStorage.findAll().stream() + .sorted((f1, f2) -> f2.getLikes().size() - f1.getLikes().size()) + .limit(count) + .collect(Collectors.toList()); + } + + // проверка условий для установки и удаления лайка + private void checkForLike(Integer idFilm, Integer idUser) { + if (idFilm == null) { + throw new ValidationException("Не указан id фильма"); + } + if (idUser == null) { + throw new ValidationException("Не указан id пользователя"); + } + if (filmStorage.getById(idFilm) == null) { + throw new NotFoundException("Фильм с id = " + idFilm + " не найден"); + } + if (userStorage.getById(idUser) == null) { + throw new NotFoundException("Пользователь с id = " + idUser + " не найден"); + } + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java new file mode 100644 index 0000000..d30b7bb --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -0,0 +1,87 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserStorage userStorage; + + public User create(User user) { + return userStorage.create(user); + } + + public User update(User user) { + return userStorage.update(user); + } + + public User getById(Integer id) { + return userStorage.getById(id); + } + + public List findAll() { + return userStorage.findAll(); + } + + // Добавляем друга в список друзей + public void addFriend(Integer idUser, Integer idFriend) { + if (idUser.equals(idFriend)) { + throw new ValidationException("Нельзя добавить себя в друзья"); + } + checkForFriend(idUser, idFriend); + userStorage.getById(idUser).addFriend(idFriend); + userStorage.getById(idFriend).addFriend(idUser); + } + + // Удаляем друга из списка друзей + public void deleteFriend(Integer idUser, Integer idFriend) { + checkForFriend(idUser, idFriend); + userStorage.getById(idUser).removeFriend(idFriend); + userStorage.getById(idFriend).removeFriend(idUser); + } + + // Получаем список друзей + public List userFriends(Integer idUser) { + User user = userStorage.getById(idUser); + return userStorage.findAll().stream() + .filter(u -> user.getFriends().contains(u.getId())) + .collect(Collectors.toList()); + } + + // Получаем общий список друзей + public List crossingFriends(Integer idUser, Integer idFriend) { + User user = userStorage.getById(idUser); + User friend = userStorage.getById(idFriend); + Set commonFriends = new HashSet<>(user.getFriends()); + commonFriends.retainAll(friend.getFriends()); + return userStorage.findAll().stream() + .filter(u -> commonFriends.contains(u.getId())) + .collect(Collectors.toList()); + } + + // Проверка для установки или удаления друзей + private void checkForFriend(Integer idUser, Integer idFriend) { + if (idUser == null || idFriend == null) { + throw new ValidationException("Не указаны id пользователя или его друга"); + } + if (userStorage.getById(idUser) == null) { + throw new NotFoundException("Пользователь с id = " + idUser + " не найден"); + } + if (userStorage.getById(idFriend) == null) { + throw new NotFoundException("Друг с id = " + idFriend + " не найден"); + } + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java new file mode 100644 index 0000000..7e575e9 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -0,0 +1,21 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.List; + +public interface FilmStorage { + + // добавляем фильм + Film create(Film film); + + // обновляем данные о фильме + Film update(Film film); + + // Ищем фильм по его id + Film getById(Integer id); + + // получаем список фильмов + List findAll(); + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java new file mode 100644 index 0000000..f20811e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -0,0 +1,65 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Repository("inMemoryFilmStorage") +@Primary +public class InMemoryFilmStorage implements FilmStorage { + + private final Map films = new HashMap<>(); + + // добавляем фильм + @Override + public Film create(Film film) { + film.setId(getNextId()); + films.put(film.getId(), film); + return film; + } + + // обновляем данные о фильме + @Override + public Film update(Film film) { + if (film.getId() == null) { + throw new ValidationException("Для изменения данных, Id фильма должен быть указан"); + } + if (films.containsKey(film.getId())) { + films.put(film.getId(), film); + return film; + } + throw new NotFoundException("Фильм с id = " + film.getId() + " не найден"); + } + + // Ищем фильм по его id + @Override + public Film getById(Integer id) { + if (!films.containsKey(id)) { + throw new NotFoundException("Фильм с id " + id + " не найден"); + } + return films.get(id); + } + + // получаем список фильмов + @Override + public List findAll() { + return films.values().stream().toList(); + } + + // вспомогательный метод для генерации идентификатора фильма + private Integer getNextId() { + return films.keySet() + .stream() + .mapToInt(id -> id) + .max() + .orElse(0) + 1; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java new file mode 100644 index 0000000..de24788 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -0,0 +1,81 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Repository("inMemoryUserStorage") +@Primary +public class InMemoryUserStorage implements UserStorage { + + private final Map users = new HashMap<>(); + + // Добавляем пользователя + @Override + public User create(User user) { + if (users.values().stream() + .anyMatch(u -> u.getEmail().equals(user.getEmail()))) { + throw new ValidationException("Этот email уже кем-то используется"); + } + if (user.getName() == null || user.getName().isBlank()) { + user.setName(user.getLogin()); + } + user.setId(getNextId()); + users.put(user.getId(), user); + return user; + } + + // Обновляем данные пользователя + @Override + public User update(User newUser) { + if (newUser.getId() == null) { + throw new ValidationException("Для изменения данных, Id пользователя должен быть указан"); + } + if (users.containsKey(newUser.getId())) { + User oldUser = users.get(newUser.getId()); + if (!oldUser.getEmail().equals(newUser.getEmail())) { + if (users.values().stream() + .anyMatch(u -> u.getEmail().equals(newUser.getEmail()))) { + throw new ValidationException("Этот email уже кем-то используется"); + } + } + if (newUser.getName() == null || newUser.getName().isBlank()) { + newUser.setName(newUser.getLogin()); + } + users.put(newUser.getId(), newUser); + return newUser; + } + throw new NotFoundException("Пользователь с id = " + newUser.getId() + " не найден"); + } + + // Ищем пользователя по его id + @Override + public User getById(Integer id) { + if (!users.containsKey(id)) { + throw new NotFoundException("Пользователь с id " + id + " не найден"); + } + return users.get(id); + } + + //Получаем список всех пользователей + @Override + public List findAll() { + return users.values().stream().toList(); + } + + // вспомогательный метод для генерации идентификатора нового пользователя + private Integer getNextId() { + return users.keySet().stream() + .mapToInt(id -> id) + .max() + .orElse(0) + 1; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java new file mode 100644 index 0000000..d7e930a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -0,0 +1,21 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.model.User; + +import java.util.List; + +public interface UserStorage { + + // Добавляем пользователя + User create(User user); + + // Обновляем данные пользователя + User update(User user); + + // Ищем пользователя по его id + User getById(Integer id); + + //Получаем список всех пользователей + List findAll(); + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..92ee3fc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ - +logging.level.org.zalando.logbook= ERROR diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java deleted file mode 100644 index c669d6f..0000000 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package ru.yandex.practicum.filmorate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import ru.yandex.practicum.filmorate.controller.FilmController; -import ru.yandex.practicum.filmorate.exception.ValidationException; -import ru.yandex.practicum.filmorate.model.Film; - -import java.time.LocalDate; -import java.util.Collection; - - -import static org.junit.jupiter.api.Assertions.*; - -class FilmControllerTest { - - private FilmController filmController; - - private Film film; - - @BeforeEach - void setUp() { - filmController = new FilmController(); - film = new Film(); - film.setName("Test Film"); - film.setDescription("Test description"); - film.setDuration(120); - film.setReleaseDate(LocalDate.of(2000, 1, 1)); - } - - @Test - void findAll() { - Collection films = filmController.findAll(); - assertNotNull(films); - } - - @Test - void create() { - Film createdFilm = filmController.create(film); - assertNotNull(createdFilm); - assertEquals(film.getName(), createdFilm.getName()); - assertEquals(film.getDescription(), createdFilm.getDescription()); - assertEquals(film.getDuration(), createdFilm.getDuration()); - assertEquals(film.getReleaseDate(), createdFilm.getReleaseDate()); - } - - @Test - void createWithInvalidName() { - film.setName(""); - assertThrows(ValidationException.class, () -> filmController.create(film)); - } - - @Test - void createWithLongDescription() { - film.setDescription("a".repeat(201)); - assertThrows(ValidationException.class, () -> filmController.create(film)); - } - - @Test - void createWithInvalidDuration() { - film.setDuration(0); - assertThrows(ValidationException.class, () -> filmController.create(film)); - } - - @Test - void createWithInvalidReleaseDate() { - film.setReleaseDate(LocalDate.of(1895, 12, 27)); - assertThrows(ValidationException.class, () -> filmController.create(film)); - } - - @Test - void update() { - Film createdFilm = filmController.create(film); - Film newFilm = new Film(); - newFilm.setId(createdFilm.getId()); - newFilm.setName("New Test Film"); - newFilm.setDescription("New test description"); - newFilm.setDuration(180); - newFilm.setReleaseDate(LocalDate.of(2001, 1, 1)); - Film updatedFilm = filmController.update(newFilm); - assertNotNull(updatedFilm); - assertEquals(newFilm.getName(), updatedFilm.getName()); - assertEquals(newFilm.getDescription(), updatedFilm.getDescription()); - assertEquals(newFilm.getDuration(), updatedFilm.getDuration()); - assertEquals(newFilm.getReleaseDate(), updatedFilm.getReleaseDate()); - } - - @Test - void updateWithInvalidId() { - Film newFilm = new Film(); - newFilm.setId(1L); - assertThrows(ValidationException.class, () -> filmController.update(newFilm)); - } - - @Test - void updateWithInvalidName() { - Film createdFilm = filmController.create(film); - Film newFilm = new Film(); - newFilm.setId(createdFilm.getId()); - newFilm.setName(""); - newFilm.setDescription("New test description"); - newFilm.setDuration(180); - newFilm.setReleaseDate(LocalDate.of(2001, 1, 1)); - assertThrows(ValidationException.class, () -> filmController.update(newFilm)); - } - - @Test - void updateWithLongDescription() { - Film createdFilm = filmController.create(film); - Film newFilm = new Film(); - newFilm.setId(createdFilm.getId()); - newFilm.setName("New Test Film"); - newFilm.setDescription("a".repeat(201)); - newFilm.setDuration(180); - newFilm.setReleaseDate(LocalDate.of(2001, 1, 1)); - assertThrows(ValidationException.class, () -> filmController.update(newFilm)); - } - - @Test - void updateWithInvalidDuration() { - Film createdFilm = filmController.create(film); - Film newFilm = new Film(); - newFilm.setId(createdFilm.getId()); - newFilm.setName("New Test Film"); - newFilm.setDescription("New test description"); - newFilm.setDuration(0); - newFilm.setReleaseDate(LocalDate.of(2001, 1, 1)); - assertThrows(ValidationException.class, () -> filmController.update(newFilm)); - } - - @Test - void updateWithInvalidReleaseDate() { - Film createdFilm = filmController.create(film); - Film newFilm = new Film(); - newFilm.setId(createdFilm.getId()); - newFilm.setName("New Test Film"); - newFilm.setDescription("New test description"); - newFilm.setDuration(180); - newFilm.setReleaseDate(LocalDate.of(1895, 12, 27)); - assertThrows(ValidationException.class, () -> filmController.update(newFilm)); - } -} diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java index 660412e..7f2b8d9 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java @@ -1,13 +1,10 @@ package ru.yandex.practicum.filmorate; -import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest -class FilmorateApplicationTests { - - @Test - void contextLoads() { - } +public class FilmorateApplicationTests { } + + diff --git a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java deleted file mode 100644 index 6702f0e..0000000 --- a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java +++ /dev/null @@ -1,126 +0,0 @@ -package ru.yandex.practicum.filmorate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import ru.yandex.practicum.filmorate.controller.UserController; -import ru.yandex.practicum.filmorate.exception.ValidationException; -import ru.yandex.practicum.filmorate.model.User; - -import java.time.LocalDate; -import java.util.Collection; - -import static org.junit.jupiter.api.Assertions.*; - -class UserControllerTest { - - private UserController userController; - - private User user; - - @BeforeEach - void setUp() { - userController = new UserController(); - user = new User(); - user.setEmail("test@test.ru"); - user.setLogin("test"); - user.setBirthday(LocalDate.of(2000, 1, 1)); - } - - @Test - void findAll() { - Collection users = userController.findAll(); - assertNotNull(users); - } - - @Test - void create() { - User createdUser = userController.create(user); - assertNotNull(createdUser); - assertEquals(user.getEmail(), createdUser.getEmail()); - assertEquals(user.getLogin(), createdUser.getLogin()); - assertEquals(user.getBirthday(), createdUser.getBirthday()); - } - - @Test - void createWithInvalidEmail() { - user.setEmail("testtest.ru"); - assertThrows(ValidationException.class, () -> userController.create(user)); - } - - @Test - void createWithExistingEmail() { - userController.create(user); - User newUser = new User(); - newUser.setEmail("test@test.ru"); - newUser.setLogin("newUser"); - newUser.setBirthday(LocalDate.of(2000, 1, 1)); - assertThrows(ValidationException.class, () -> userController.create(newUser)); - } - - @Test - void createWithInvalidLogin() { - user.setLogin(" "); - assertThrows(ValidationException.class, () -> userController.create(user)); - } - - @Test - void createWithFutureBirthday() { - user.setBirthday(LocalDate.now().plusDays(1)); - assertThrows(ValidationException.class, () -> userController.create(user)); - } - - @Test - void update() { - User createdUser = userController.create(user); - User newUser = new User(); - newUser.setId(createdUser.getId()); - newUser.setEmail("newEmail@test.ru"); - newUser.setLogin("newUser"); - newUser.setBirthday(LocalDate.of(2000, 1, 1)); - User updatedUser = userController.update(newUser); - assertNotNull(updatedUser); - assertEquals(newUser.getEmail(), updatedUser.getEmail()); - assertEquals(newUser.getLogin(), updatedUser.getLogin()); - assertEquals(newUser.getBirthday(), updatedUser.getBirthday()); - } - - @Test - void updateWithInvalidId() { - User newUser = new User(); - newUser.setId(1L); - assertThrows(ValidationException.class, () -> userController.update(newUser)); - } - - @Test - void updateWithInvalidEmail() { - User createdUser = userController.create(user); - User newUser = new User(); - newUser.setId(createdUser.getId()); - newUser.setEmail("newEmailtest.ru"); - newUser.setLogin("newUser"); - newUser.setBirthday(LocalDate.of(2000, 1, 1)); - assertThrows(ValidationException.class, () -> userController.update(newUser)); - } - - @Test - void updateWithInvalidLogin() { - User createdUser = userController.create(user); - User newUser = new User(); - newUser.setId(createdUser.getId()); - newUser.setEmail("newEmail@test.ru"); - newUser.setLogin(" "); - newUser.setBirthday(LocalDate.of(2000, 1, 1)); - assertThrows(ValidationException.class, () -> userController.update(newUser)); - } - - @Test - void updateWithFutureBirthday() { - User createdUser = userController.create(user); - User newUser = new User(); - newUser.setId(createdUser.getId()); - newUser.setEmail("newEmail@test.ru"); - newUser.setLogin("newUser"); - newUser.setBirthday(LocalDate.now().plusDays(1)); - assertThrows(ValidationException.class, () -> userController.update(newUser)); - } -}