1
0
Fork 0
mirror of https://github.com/heyarne/airsonic-ui.git synced 2026-05-06 18:33:38 +02:00

Setup tests

commit 1b86fa1477d9cbad441e7616b6f1adbceec76c9c
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 19:52:48 2018 +0200

    Cache build directories for (hopefully) faster builds

commit b614e1fa8437bb20cb5fcb05d6ab7ad318984f01
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 19:49:34 2018 +0200

    Fix undeclared var in test

commit f0f30e6a546ad0e4a7f65538d485b5544f7733c3
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 19:27:13 2018 +0200

    Configure travis and fix dependencies

commit 5a3f432d9e9ed34e21a6940a18f11fa4d0ef9b7d
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 19:22:33 2018 +0200

    Remove build folders from git

commit 44095cbd34e2ed6f70d43b7c72f5cb4bacb18913
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 19:17:05 2018 +0200

    Add first real test

commit 02a0ef51c61c15ddc6de88f34aa5fd2817fdca88
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 16:38:40 2018 +0200

    Add growl notifications

commit 5b09be97e04e64ecab5aba3e063f584e48d21c0a
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 14:29:02 2018 +0200

    Add karma watcher

commit 6d7859f7fd420e4057277da3605a4df5985d8ae9
Author: Arne Schlüter <arne@schlueter.is>
Date:   Mon May 28 14:20:12 2018 +0200

    Add karma and set it up for single-run tests
This commit is contained in:
Arne Schlüter 2018-05-28 19:57:03 +02:00
commit 629872ec97
11 changed files with 2840 additions and 44 deletions

10
.travis.yml Normal file
View file

@ -0,0 +1,10 @@
language: node_js
node_js:
- "10"
- "8"
addons:
chrome: stable
cache:
directories:
- node_modules
- .shadow-cljs

View file

@ -1,4 +1,4 @@
# Airsonic Web Client # Airsonic Web Client [![Build Status](https://travis-ci.org/heyarne/airsonic-ui.svg?branch=master)](https://travis-ci.org/heyarne/airsonic-ui)
This is just meant for exploration. If you want to see something more serious, take a look at [airsonic-ui](https://github.com/airsonic/airsonic-ui). This is just meant for exploration. If you want to see something more serious, take a look at [airsonic-ui](https://github.com/airsonic/airsonic-ui).
@ -29,6 +29,17 @@ $ npm run build
**Note:** In dev mode this project comes with re-frame-10x. You can hit `Ctrl + h` to display the overlay and have a time traveling debugger. **Note:** In dev mode this project comes with re-frame-10x. You can hit `Ctrl + h` to display the overlay and have a time traveling debugger.
## Tests
This project uses [karma](https://karma-runner.github.io/) for tests. Make sure to have Google Chrome installed, otherwise the watcher will time out. If you want to run tests continuously in the background, you may want to have Growl installed to show notifications ([see setup instructions](https://www.npmjs.com/package/karma-growl-reporter#installation)).
```
# run tests once
$ npm test
# run tests continuously, watching for changes
$ npm run test:watch
```
## Build artifacts ## Build artifacts
Everything you need to serve the app can be found inside the `public` folder. Everything you need to serve the app can be found inside the `public` folder.

34
karma.conf.js Normal file
View file

@ -0,0 +1,34 @@
module.exports = function (config) {
const configuration = {
browsers: ['ChromeHeadless'],
// The directory where the output file lives
basePath: 'public/test',
// The file itself
files: ['ci.js'],
frameworks: ['cljs-test'],
plugins: [
'karma-cljs-test',
'karma-chrome-launcher',
'karma-growl-reporter'
],
colors: true,
logLevel: config.LOG_INFO,
client: {
args: ["shadow.test.karma.init"]
},
// configure travis-ci; based on this: https://stackoverflow.com/questions/19255976/how-to-make-travis-execute-angular-tests-on-chrome-please-set-env-variable-chr#25661593
customLaunchers: {
ChromeHeadlessTravisCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
}
}
if (process.env.TRAVIS) {
configuration.browsers = ['ChromeHeadlessTravisCI']
}
config.set(configuration)
}

2722
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,12 @@
"description": "Airsonic UI written with re-frame", "description": "Airsonic UI written with re-frame",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "run-s test:compile-once test:run-once",
"test:compile-once": "shadow-cljs compile test",
"test:run-once": "karma start --single-run",
"test:compile-watch": "shadow-cljs watch test",
"test:run-watch": "karma start --reporters growl,progress --auto-watch",
"test:watch": "npm-run-all test:compile-once -p test:compile-watch test:run-watch",
"build:cljs": "shadow-cljs release app", "build:cljs": "shadow-cljs release app",
"build:html": "sed 's/\"\\/app\\//\".\\/app\\//g' src/html/index.html > public/index.html", "build:html": "sed 's/\"\\/app\\//\".\\/app\\//g' src/html/index.html > public/index.html",
"build:sass": "node-sass --output-style compressed src/sass/app.sass public/app/style.css", "build:sass": "node-sass --output-style compressed src/sass/app.sass public/app/style.css",
@ -30,6 +35,10 @@
}, },
"devDependencies": { "devDependencies": {
"gh-pages": "^1.1.0", "gh-pages": "^1.1.0",
"karma": "^2.0.2",
"karma-chrome-launcher": "^2.2.0",
"karma-cljs-test": "^0.1.0",
"karma-growl-reporter": "^1.0.0",
"node-sass": "^4.9.0", "node-sass": "^4.9.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"react-flip-move": "^3.0.1", "react-flip-move": "^3.0.1",

View file

@ -1,14 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Airsonic</title>
<link rel="stylesheet" href="./app/style.css">
</head>
<body>
<div id="app"></div>
<script src="./app/js/main.js"></script>
<script>airsonic_ui.core.init()</script>
</body>
</html>

View file

@ -1,6 +1,6 @@
;; shadow-cljs configuration ;; shadow-cljs configuration
{:source-paths {:source-paths
["src/cljs"] ["src/cljs", "test/cljs"]
:dependencies :dependencies
[[reagent "0.7.0"] [[reagent "0.7.0"]
@ -11,8 +11,7 @@
[day8.re-frame/re-frame-10x "0.3.2-react16"] [day8.re-frame/re-frame-10x "0.3.2-react16"]
[day8.re-frame/tracing "0.5.1"] [day8.re-frame/tracing "0.5.1"]
;; for CIDER ;; for CIDER
[cider/cider-nrepl "0.16.0-snapshot"] [cider/cider-nrepl "0.18.0-SNAPSHOT"]]
[refactor-nrepl "2.3.1"]]
:builds :builds
{:app {:target :browser {:app {:target :browser
@ -24,4 +23,7 @@
:devtools {:http-root "public" :devtools {:http-root "public"
:http-port 8080 :http-port 8080
:after-load airsonic-ui.core/mount-root :after-load airsonic-ui.core/mount-root
:preloads [day8.re-frame-10x.preload]}}}} :preloads [day8.re-frame-10x.preload]}}
:test {:target :karma
:output-to "public/test/ci.js"
:ns-regexp "-test$"}}}

View file

@ -3,7 +3,7 @@
[ajax.core :as ajax] [ajax.core :as ajax]
[airsonic-ui.routes :as routes] [airsonic-ui.routes :as routes]
[airsonic-ui.db :as db] [airsonic-ui.db :as db]
[airsonic-ui.api :as api] [airsonic-ui.utils.api :as api]
[day8.re-frame.tracing :refer-macros [fn-traced]])) ; <- useful to debug handlers [day8.re-frame.tracing :refer-macros [fn-traced]])) ; <- useful to debug handlers
;; this is where all of the event handling takes place; the names put the events into ;; this is where all of the event handling takes place; the names put the events into

View file

@ -1,17 +1,18 @@
(ns airsonic-ui.api (ns airsonic-ui.utils.api
(:require [clojure.string :as str] (:require [clojure.string :as str]
[airsonic-ui.config :as config])) [airsonic-ui.config :as config]))
(def default-params {:f "json"
:c "airsonic-ui-cljs"
:v "1.15.0"})
(defn- encode [c] (defn- encode [c]
(js/encodeURIComponent c)) (js/encodeURIComponent c))
(defn url (defn url
"Returns an absolute url to an API endpoint" "Returns an absolute url to an API endpoint"
[server endpoint params] [server endpoint params]
(let [query (->> (assoc params (let [query (->> (merge default-params params)
:f "json"
:c "airsonic-ui-cljs"
:v "1.15.0")
(map (fn [[k v]] (str (encode (name k)) "=" (encode v)))) (map (fn [[k v]] (str (encode (name k)) "=" (encode v))))
(str/join "&"))] (str/join "&"))]
(str server (when-not (str/ends-with? server "/") "/") "rest/" endpoint "?" query))) (str server (when-not (str/ends-with? server "/") "/") "rest/" endpoint "?" query)))
@ -21,14 +22,3 @@
(defn cover-url [server credentials item size] (defn cover-url [server credentials item size]
(url server "getCoverArt" (merge {:id (:coverArt item) :size size} credentials))) (url server "getCoverArt" (merge {:id (:coverArt item) :size size} credentials)))
(defn- api-error?
"We need to look at the message body because the subsonic api always responds
with status 200"
[response]
(= "failed" (-> response :subsonic-response :status)))
(defn- error-message
[response]
(let [{:keys [code message]} (-> response :subsonic-response :error)]
(str "Code " code ": " message)))

View file

@ -1,7 +1,7 @@
(ns airsonic-ui.views.cover (ns airsonic-ui.views.cover
(:require [re-frame.core :refer [subscribe]] (:require [re-frame.core :refer [subscribe]]
[airsonic-ui.subs :as subs] [airsonic-ui.subs :as subs]
[airsonic-ui.api :as api])) [airsonic-ui.utils.api :as api]))
;; FIXME: The direct dependency on these subs is a bit ugly ;; FIXME: The direct dependency on these subs is a bit ugly

View file

@ -0,0 +1,32 @@
(ns airsonic-ui.utils.api-test
(:require [cljs.test :refer [deftest testing is]]
[clojure.string :as str]
[airsonic-ui.utils.api :as api]))
(defn- url
"Construct a url with no params"
[server endpoint]
(api/url server endpoint {}))
(def fixtures
{:default-url (url "http://localhost:8080" "ping")})
(deftest general-url-construction
(testing "Handles missing slashes"
(is (true? (str/starts-with? (fixtures :default-url) "http://localhost:8080/rest/ping")))
(is (true? (str/starts-with? (url "http://localhost:8080/" "ping") "http://localhost:8080/rest/ping"))))
(testing "Should set correct default parameters"
(is (string? (re-find #"f=json" (fixtures :default-url))))
(is (string? (re-find #"v=1\.15\.0" (fixtures :default-url))))))
(deftest song-urls
(testing "Should construct the url based on a song's id"
(let [song {:id 1234}]
(is (true? (str/includes? (api/song-url "http://localhost" {} song) (str "id=" (:id song))))))))
(deftest cover-urls
(let [album {:coverArt "cover-99999"}]
(testing "Should construct the url based on an item's cover-id"
(is (true? (str/includes? (api/cover-url "http://server.tld" {} album -1) (str "id=" (:coverArt album))))))
(testing "Should scale an image to a given size"
(is (true? (str/includes? (api/cover-url "http://server.tld" {} album 48) "size=48"))))))