Permalink
Browse files

Add cancellation

  • Loading branch information...
1 parent 9ccbd95 commit dfafe704229dab99ccdc4b6bf9ca2aca12ef23bc @sattvik committed Apr 7, 2011
Showing with 148 additions and 20 deletions.
  1. +29 −5 src/clojure/neko/dialog/alert.clj
  2. +119 −15 test/src/clojure/neko/dialog/alert_test.clj
@@ -27,22 +27,46 @@
"Defines the functionality needed to build new alert dialogues."
(create [builder]
"Actually creates the AlertDialog.")
+ (with-cancellation [builder cancellable?]
+ "Sets whether or not the dialog may be cancelled.")
)
(defrecord FunctionalAlertDialogBuilder
- [^android.content.Context context]
+ [^android.content.Context context
+ ^boolean cancellable])
+
+(defn- new-builder?
+ "Predicate used for testing whether a new builder is a functional builder but
+ is different from the original builder."
+ [old-builder new-builder]
+ (and (instance? FunctionalAlertDialogBuilder old-builder)
+ (not (identical? old-builder new-builder))))
+
+(extend-type FunctionalAlertDialogBuilder
AlertDialogBuilder
- (create [_]
- #_{:post [(instance? android.app.AlertDialog %)]}
- (let [builder (AlertDialog$Builder. context)]
+ (create [this]
+ {:post [(instance? android.app.AlertDialog %)]}
+ (let [^AlertDialog$Builder builder (AlertDialog$Builder. (.context this))]
+ (doto builder
+ (.setCancelable (.cancellable this))
+ )
(.create builder)))
+
+ (with-cancellation [this cancellable?]
+ {:post [(new-builder? this %)
+ (= (:cancellable %) cancellable?)]}
+ (assoc this :cancellable (boolean cancellable?)))
)
(extend-type AlertDialog$Builder
AlertDialogBuilder
(create [this]
{:post [(instance? android.app.AlertDialog %)]}
(.create this))
+
+ (with-cancellation [this cancellable?]
+ {:post [(identical? this %)]}
+ (.setCancelable this (boolean cancellable?)))
)
(defn new-builder
@@ -55,4 +79,4 @@
([context]
{:pre [(context? context)]
:post [(instance? FunctionalAlertDialogBuilder %)]}
- (FunctionalAlertDialogBuilder. context)))
+ (FunctionalAlertDialogBuilder. context true)))
@@ -13,28 +13,62 @@
"Tests for the neko.alert-dialog namespace."
{:author "Daniel Solano Gómez"}
(:gen-class :main false
- :extends android.test.AndroidTestCase
- :methods [[testNewBuilder [] void]
- [testBasicCreate [] void]
+ :extends android.test.InstrumentationTestCase
+ :methods [[^{android.test.UiThreadTest {}} testNewBuilder [] void]
+ [^{android.test.UiThreadTest {}} testBasicCreate [] void]
+ [testCancellationDefaultWithObject [] void]
+ [testCancellationTrueWithObject [] void]
+ [testCancellationFalseWithObject [] void]
+ [testCancellationDefaultFunctional [] void]
+ [testCancellationTrueFunctional [] void]
+ [testCancellationFalseFunctional [] void]
]
- :exposes-methods {setUp superSetUp}
+ :exposes-methods {runTest superRunTest
+ setUp superSetUp
+ tearDown superTearDown}
)
(:import android.app.AlertDialog$Builder
+ android.test.UiThreadTest
+ [java.util.concurrent CountDownLatch TimeUnit]
neko.dialog.alert.FunctionalAlertDialogBuilder)
(:use junit.assert
- neko.context
- neko.find-view
+ [neko activity
+ find-view]
neko.dialog.alert
+ neko.listeners.dialog
)
)
-(def context (atom nil))
+(def the-test (atom nil))
+(def activity (atom nil))
+
+(defn start-activity []
+ (when-not @activity
+ (let [package (.. @the-test getInstrumentation getTargetContext getPackageName) ]
+ (reset! activity (.launchActivity @the-test package com.sattvik.neko.test_app.TestActivity nil))))
+ @activity)
(defn -setUp
- "Sets up the context atom"
[this]
- (.superSetUp this)
- (reset! context (.getContext this)))
+ (doto this
+ (.superSetUp))
+ (reset! the-test this))
+
+(defn -tearDown
+ [this]
+ (when @activity
+ (.finish @activity)
+ (reset! activity nil))
+ (reset! the-test nil)
+ (.superTearDown this))
+
+(defn -runTest
+ [this]
+ (let [method-name (.getName this)
+ method (.. this getClass (getMethod method-name (into-array Class [])))]
+ (when (.isAnnotationPresent method UiThreadTest)
+ (start-activity)))
+ (.superRunTest this))
(defn -testNewBuilder
"Tests the new-builder function."
@@ -43,8 +77,8 @@
(does-throw AssertionError (new-builder))
; non-context argument
(does-throw AssertionError (new-builder "neko"))
- (is (instance? FunctionalAlertDialogBuilder (new-builder @context)))
- (with-context @context
+ (is (instance? FunctionalAlertDialogBuilder (new-builder @activity)))
+ (with-activity @activity
(is (instance? FunctionalAlertDialogBuilder (new-builder)))))
(defn -testBasicCreate
@@ -53,8 +87,78 @@
(let [test-builder (fn [builder]
; a simple test that just ensures a view exists
(let [dialog (create builder)]
- (is-not-nil (find-view dialog :android/icon))))]
+ (.show dialog)
+ (is-not-nil (find-view dialog :android/icon))
+ (.dismiss dialog)))]
; test with android builder
- (test-builder (AlertDialog$Builder. @context))
+ (test-builder (AlertDialog$Builder. @activity))
; test with functional builder
- (test-builder (new-builder @context))))
+ (test-builder (new-builder @activity))))
+
+(defn test-cancellation
+ [build-fn cancellable?]
+ (let [dialog (atom nil)
+ latch (CountDownLatch. 1)
+ cancel-test
+ (reify Runnable
+ (run [_]
+ (let [builder (build-fn)]
+ (reset! dialog (create builder))
+ (doto @dialog
+ (.setOnCancelListener
+ (on-cancel (.countDown latch)))
+ (.show)
+ (.onBackPressed)))))]
+ (.runTestOnUiThread @the-test cancel-test)
+ (is-eq cancellable?
+ (.await latch 250 TimeUnit/MILLISECONDS))))
+
+(defn -testCancellationDefaultWithObject
+ "Tests that by default an object-based builder is cancellable."
+ [this]
+ (start-activity)
+ (test-cancellation #(AlertDialog$Builder. @activity)
+ true))
+
+(defn -testCancellationTrueWithObject
+ "Tests that enabling cancellation with an object works."
+ [this]
+ (start-activity)
+ (test-cancellation #(let [builder (AlertDialog$Builder. @activity)]
+ (with-cancellation builder true))
+ true))
+
+(defn -testCancellationFalseWithObject
+ "Tests that disabling cancellation with an object works."
+ [this]
+ (start-activity)
+ (test-cancellation #(let [builder (AlertDialog$Builder. @activity)]
+ (with-cancellation builder false))
+ false))
+
+(defn -testCancellationDefaultFunctional
+ "Tests that by default a functional builder is cancellable."
+ [this]
+ (start-activity)
+ (test-cancellation #(new-builder @activity)
+ true))
+
+(defn -testCancellationTrueFunctional
+ "Tests that enabling cancellation on a functional builder works."
+ [this]
+ (start-activity)
+ (test-cancellation #(let [builder (new-builder @activity)
+ builder (with-cancellation builder true)]
+ (is (:cancellable builder))
+ builder)
+ true))
+
+(defn -testCancellationFalseFunctional
+ "Tests that disabling cancellation on a functional builder works."
+ [this]
+ (start-activity)
+ (test-cancellation #(let [builder (new-builder @activity)
+ builder (with-cancellation builder false)]
+ (is-not (:cancellable builder))
+ builder)
+ false))

0 comments on commit dfafe70

Please sign in to comment.