Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions url-shortener/project.clj
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
(defproject url-shortener "0.1.0-SNAPSHOT"
:description "URL shortener app"

:source-paths ["src" "resources"]
:resource-paths ["resources"]

:dependencies [
;; Backend
:dependencies [;; Backend
[org.clojure/clojure "1.11.1"]
[ring/ring-jetty-adapter "1.11.0"]
[ring/ring-json "0.5.1"]
[compojure "1.7.1"]
[org.slf4j/slf4j-simple "2.0.10"]

;; Frontend
[reagent "1.2.0"]
[org.clojure/core.async "1.6.681"]
[cljs-http "0.1.48"
:exclusions [org.clojure/core.async
com.cognitect/transit-cljs
com.cognitect/transit-js]]
[thheller/shadow-cljs "2.27.2"] ; Keep it synced with npm version!
]

[cljs-http
"0.1.48"
:exclusions
[org.clojure/core.async
com.cognitect/transit-cljs
com.cognitect/transit-js]]
[thheller/shadow-cljs "2.27.2"] ; Keep it synced with npm
; version!
;; Testing
[nubank/matcher-combinators "3.8.5"]]
:main ^:skip-aot url-shortener.core

:uberjar-name "url-shortener.jar"

:profiles {:dev {:source-paths ["dev"]
:dependencies [[ring/ring-devel "1.11.0"]]}

:repl {:repl-options {:init-ns user}}

:profiles {:dev {:source-paths ["dev"],
:dependencies [[ring/ring-devel "1.11.0"]]},
:repl {:repl-options {:init-ns user}},
:uberjar {:aot :all}})
59 changes: 59 additions & 0 deletions url-shortener/test/url_shortener/core_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns url-shortener.core-test
(:require [clojure.test :refer [are deftest is testing use-fixtures]]
[matcher-combinators.test]
[url-shortener.core :refer
[alphabet-size id->int int->id list-all shorten! url-for]]))

(defn reset-state
[t]
(with-redefs [url-shortener.core/*counter (atom 0)
url-shortener.core/*mapping (ref {})]
(t)))

(use-fixtures :once reset-state)

(deftest test-int->id
(are [input expected] (= (int->id input) expected)
0 "0"
alphabet-size "10"
9999999999999 "2q3Rktod"
9223372036854775807 "AzL8n0Y58W7"
-1 "")
(is (thrown-with-msg? Exception
#"cannot be cast to class java.lang.Number"
(int->id "asdf")))
(is (thrown-with-msg? Exception #"because [\"]x[\"] is null" (int->id nil))))

(deftest test-id->int
(are [input expected] (= (id->int input) expected)
"0" 0
"z" 61
"clj" 149031
"Clojure" 725410830262
"" 0))
Comment on lines +28 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я бы добавил тестов с некорректными аргументами. И сгруппировал все тесты на legal arguments и illegal arguments при помощи testing


(deftest core
(testing "Empty list" (is (= (list-all) [])))
(testing "Shorten positive"
(are [args result] (= (apply shorten! args) result)
["http://clojurebook.com"] "1"
["http://clojurebook.com"] "2"
["https://clojure.org" "clj"] "clj"
["https://clojure.org" "clj"] nil
["http://id-already-exists.com" "clj"] nil
["https://clojurescript.org" "cljs"] "cljs"
[""] "3"))
(testing "Getting urls"
(are [id result] (= (url-for id) result)
"1" "http://clojurebook.com"
"2" "http://clojurebook.com"
"3" ""
"cljs" "https://clojurescript.org"
"clj" "https://clojure.org"))
(testing "List all"
(is (match? (list-all)
[{:id "1", :url "http://clojurebook.com"}
{:id "2", :url "http://clojurebook.com"}
{:id "clj", :url "https://clojure.org"}
{:id "cljs", :url "https://clojurescript.org"}
{:id "3", :url ""}]))))
7 changes: 7 additions & 0 deletions url-shortener/test/url_shortener/frontend_test.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(ns url-shortener.frontend-test
(:require [clojure.test :refer [deftest is]]
[url-shortener.frontend :refer [header]]))

; pretty useless I think
(deftest test-header
(is (= (header "Test") [:h2 {:style {:margin "8px 4px"}} "Test"])))
Comment on lines +5 to +7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Думаю тест со значением nil не был бы лишним.

49 changes: 49 additions & 0 deletions url-shortener/test/url_shortener/web_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(ns url-shortener.web-test
(:require [clojure.test :refer [are deftest testing use-fixtures]]
[matcher-combinators.test]
[url-shortener.core-test :refer [reset-state]]
[url-shortener.web :refer [handler router]]))

(use-fixtures :once reset-state)

(deftest ^:integration test-handler
(testing "Handlers"
(are [request response] (match? (handler request) response)
; Post
{:uri "/",
:request-method :post,
:params
{:url
"https://github.com/Clojure-Developer/Clojure-Developer-2022-10"}}
{:status 201,
:headers {"Location" "1",
"Content-Type" "application/json; charset=utf-8"},
:body "{\"id\":\"1\"}"}
Comment on lines +13 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Неправильное форматирование. Зачем добавлять отступ, если это параметры одной функции?. Если хочешь их сгруппировать, то лучше добавь пустую строку между парами мап.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я пользуюсь zprint как форматировщиком. Он сам все это делает автоматически. Я по сути код не форматирю.

; Put clj
{:uri "/clj", :request-method :put, :params {:url "https://clojure.org"}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ИМХО, каждую пару ключ-значение лучше помещать на отдельную строку. Аргументы в пользу такого code-style'а:

  1. Это препятствует появлению длинных строк.
  2. Это улучшает читаемость кода.

{:status 201,
:headers {"Location" "clj",
"Content-Type" "application/json; charset=utf-8"},
:body "{\"id\":\"clj\"}"}
; Negative, duplicate
{:uri "/clj", :request-method :put, :params {:url "https://clojure.org"}}
{:status 409,
:headers {"Content-Type" "application/json; charset=utf-8"},
:body "{\"error\":\"Short URL clj is already taken\"}"}
; Get result
{:uri "/clj", :request-method :get} {:status 302,
:headers {"Location"
"https://clojure.org"},
:body ""}))
(testing "Routers"
(are [request response] (match? (router request) response)
; List
{:uri "/list/", :request-method :get}
{:status 200,
:headers {},
:body
{:urls
[{:id "1",
:url
"https://github.com/Clojure-Developer/Clojure-Developer-2022-10"}
{:id "clj", :url "https://clojure.org"}]}})))