Skip to content
Snippets Groups Projects
Commit 803c5ce6 authored by Cam Saul's avatar Cam Saul
Browse files

unit test for POST /api/meta/dataset

parent aa644a08
No related branches found
No related tags found
No related merge requests found
......@@ -7,6 +7,8 @@
(catch-api-exceptions 0)
(context 2)
(expect 1)
(expect-eval-actual-first 1)
(expect-let 1)
(ins 1)
(let-400 1)
(let-404 1)
......
(ns metabase.api.meta.dataset-test
"Unit tests for /api/meta/dataset endpoints."
(:require [expectations :refer :all]
[korma.core :refer :all]
[metabase.db :refer :all]
[metabase.models.query-execution :refer [QueryExecution]]
[metabase.test.util :refer [match-$ expect-eval-actual-first]]
[metabase.test-data :refer :all]))
;;; ## QUERY /api/meta/dataset
;; Just a basic sanity check to make sure Query Processor endpoint is still working correctly.) (rexpect(match-$ (sel :latest QueryExecution)
(expect-eval-actual-first (match-$ (sel :one :fields [QueryExecution :id :uuid] (order :id :desc))
{:data {:rows [[1000]]
:columns ["count"]
:cols [{:base_type "IntegerField", :special_type "number", :name "count", :id nil, :table_id nil, :description nil}]}
:row_count 1
:status "completed"
:id $
:uuid $})
((user->client :rasta) :post 200 "meta/dataset" {:database (:id @test-db)
:type "query"
:query {:aggregation ["count"]
:breakout [nil]
:filter [nil nil]
:limit nil
:source_table (table->id :checkins)}}))
......@@ -3,8 +3,8 @@
(:require [expectations :refer :all]
[metabase.db :refer :all]
(metabase.models [org-perm :refer [OrgPerm]])
(metabase [test-data :refer :all]
[test-utils :refer [deserialize-dates match-$]])))
[metabase.test.util :refer [deserialize-dates match-$]]
[metabase.test-data :refer :all]))
(def rasta-org-perm-id (delay (sel :one :id OrgPerm :organization_id @org-id :user_id (user->id :rasta))))
......
(ns metabase.test.util
"Helper functions and macros for writing unit tests."
(:require [expectations :refer :all]
[medley.core :as medley]
[metabase.util :as u]))
(declare $->prop)
;; ## Response Deserialization
(defn deserialize-dates
"Deserialize date strings with KEYS returned in RESPONSE."
[response & [k & ks]]
{:pre [(map? response)
(keyword? k)]}
(let [response (medley/update response k #(some->> (u/parse-iso8601 %)
.getTime
java.sql.Timestamp.))]
(if (empty? ks) response
(apply deserialize-dates response ks))))
;; ## match-$
(defmacro match-$
"Walk over map DEST-OBJECT and replace values of the form `$` or `$key` as follows:
{k $} -> {k (k SOURCE-OBJECT)}
{k $symb} -> {k (:symb SOURCE-OBJECT)}
ex.
(match-$ m {:a $, :b 3, :c $b}) -> {:a (:a m), b 3, :c (:b m)}"
[source-obj dest-object]
{:pre [(map? dest-object)]}
(let [source## (gensym)
dest-object (->> dest-object
(map (fn [[k v]]
{k (if (= v '$) `(~k ~source##)
v)}))
(reduce merge {}))]
`(let [~source## ~source-obj]
~(clojure.walk/prewalk (partial $->prop source##)
dest-object))))
(defn- $->prop
"If FORM is a symbol starting with a `$`, convert it to the form `(form-keyword SOURCE-OBJ)`.
($->prop my-obj 'fish) -> 'fish
($->prop my-obj '$fish) -> '(:fish my-obj)"
[source-obj form]
(or (when (symbol? form)
(let [[first-char & rest-chars] (name form)]
(when (= first-char \$)
(let [kw (->> rest-chars
(apply str)
keyword)]
`(~kw ~source-obj)))))
form))
;; ## expect-eval-actual-first
;; By default `expect` evaluates EXPECTED first. This isn't always what we want; for example, sometime API tests affect the DB
;; and we'd like to check the results.
(defmacro -doexpect [e a]
`(let [a# (try ~a (catch java.lang.Throwable t# t#))
e# (try ~e (catch java.lang.Throwable t# t#))]
(report
(try (compare-expr e# a# '~e '~a)
(catch java.lang.Throwable e2#
(compare-expr e2# a# '~e '~a))))))
(defmacro expect-eval-actual-first
"Identical to `expect` but evaluates `actual` first (instead of evaluating `expected` first)."
[expected actual]
(let [fn-name (gensym)]
`(def ~(vary-meta fn-name assoc :expectation true)
(fn [] (-doexpect ~expected ~actual)))))
......@@ -2,18 +2,16 @@
(:require [clojure.java.io :as io]
[clojure.tools.logging :as log]
[expectations :refer :all]
[medley.core :as medley]
[ring.adapter.jetty :as ring]
(metabase [core :as core]
[db :refer :all]
[util :as u])))
(declare $->prop)
[db :refer :all])))
;; # FUNCTIONS THAT GET RUN ON TEST SUITE START / STOP
;; ## DB Setup
;; WARNING: BY RUNNING ANY UNIT TESTS THAT REQUIRE THIS FILE OR BY RUNNING YOUR ENTIRE TEST SUITE YOU WILL EFFECTIVELY BE WIPING OUT YOUR DATABASE.
;; SETUP-DB DELETES YOUR DATABASE FILE, AND GETS RAN AUTOMATICALLY BY EXPECTATIONS. USE AT YOUR OWN RISK!
(defn setup-db
"setup database schema"
......@@ -57,58 +55,3 @@
[]
(when @jetty-instance
(.stop ^org.eclipse.jetty.server.Server @jetty-instance)))
;; # FUNCTIONS + MACROS FOR WRITING UNIT TESTS
;; ## Response Deserialization
(defn deserialize-dates
"Deserialize date strings with KEYS returned in RESPONSE."
[response & [k & ks]]
{:pre [(map? response)
(keyword? k)]}
(let [response (medley/update response k #(some->> (u/parse-iso8601 %)
.getTime
java.sql.Timestamp.))]
(if (empty? ks) response
(apply deserialize-dates response ks))))
;; ## match-$
(defmacro match-$
"Walk over map DEST-OBJECT and replace values of the form `$` or `$key` as follows:
{k $} -> {k (k SOURCE-OBJECT)}
{k $symb} -> {k (:symb SOURCE-OBJECT)}
ex.
(match-$ m {:a $, :b 3, :c $b}) -> {:a (:a m), b 3, :c (:b m)}"
[source-obj dest-object]
{:pre [(map? dest-object)]}
(let [source## (gensym)
dest-object (->> dest-object
(map (fn [[k v]]
{k (if (= v '$) `(~k ~source##)
v)}))
(reduce merge {}))]
`(let [~source## ~source-obj]
~(clojure.walk/prewalk (partial $->prop source##)
dest-object))))
(defn- $->prop
"If FORM is a symbol starting with a `$`, convert it to the form `(form-keyword SOURCE-OBJ)`.
($->prop my-obj 'fish) -> 'fish
($->prop my-obj '$fish) -> '(:fish my-obj)"
[source-obj form]
(or (when (symbol? form)
(let [[first-char & rest-chars] (name form)]
(when (= first-char \$)
(let [kw (->> rest-chars
(apply str)
keyword)]
`(~kw ~source-obj)))))
form))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment