diff --git a/project.clj b/project.clj index 89036cbf..1c5b5485 100644 --- a/project.clj +++ b/project.clj @@ -31,6 +31,7 @@ :dependencies [[clj-http "3.10.1"] [cheshire "5.9.0"] + [org.clojure/tools.cli "1.0.194"] [org.clojure/tools.logging "0.3.1"] [org.clojure/data.codec "0.1.0"]] diff --git a/src/etaoin/ide/flow.clj b/src/etaoin/ide/flow.clj index c8a40fc6..0041113c 100644 --- a/src/etaoin/ide/flow.clj +++ b/src/etaoin/ide/flow.clj @@ -1,5 +1,5 @@ (ns etaoin.ide.flow - (:require [cheshire.core :refer [parse-stream]] + (:require [cheshire.core :refer [parse-string]] [clojure.java.io :as io] [clojure.spec.alpha :as s] [etaoin.api :refer :all] @@ -93,26 +93,30 @@ suite-tests)) (defn find-tests - [{:keys [test-id test-ids suite-id suite-ids test-name suite-name]} + [{:keys [test-id test-ids suite-id suite-ids test-name suite-name test-names suite-names]} {:keys [tests] :as parsed-file}] (let [test-ids (cond-> #{} - test-id (conj (first (filter #(= test-id (:id %)) tests))) - test-name (conj (first (filter #(= test-name (:name %)) tests))) - suite-id (into (get-tests-by-suite-id suite-id :id parsed-file)) - suite-name (into (get-tests-by-suite-id suite-name :name parsed-file)) - test-ids (into (filter #((set test-ids) (:id %)) tests)) - suite-ids (into (mapcat #(get-tests-by-suite-id % :id parsed-file) suite-ids))) + test-id (conj (first (filter #(= test-id (:id %)) tests))) + test-name (conj (first (filter #(= test-name (:name %)) tests))) + suite-id (into (get-tests-by-suite-id suite-id :id parsed-file)) + suite-name (into (get-tests-by-suite-id suite-name :name parsed-file)) + test-ids (into (filter #((set test-ids) (:id %)) tests)) + suite-ids (into (mapcat #(get-tests-by-suite-id % :id parsed-file) suite-ids)) + test-names (into (filter #((set test-names) (:name %)) tests)) + suite-names (into (mapcat #(get-tests-by-suite-id % :name parsed-file) suite-names))) tests-found (filter test-ids tests)] (if (empty? tests-found) tests tests-found))) (defn run-ide-script - [driver path & [opt]] - (let [parsed-file (with-open [rdr (io/reader path)] - (parse-stream rdr true)) + [driver source & [opt]] + (let [parsed-file (-> source + slurp + (parse-string true)) opt-search (select-keys opt [:test-name :test-id :test-ids - :suite-name :suite-id :suite-ids]) + :suite-name :suite-id :suite-ids + :test-names :suite-names]) tests-found (find-tests opt-search parsed-file) opt (merge {:base-url (:url parsed-file) :vars (atom {})} diff --git a/src/etaoin/ide/main.clj b/src/etaoin/ide/main.clj index 389167bc..b67b88a1 100644 --- a/src/etaoin/ide/main.clj +++ b/src/etaoin/ide/main.clj @@ -1,8 +1,97 @@ (ns etaoin.ide.main - (:require [etaoin.api :refer :all] - [etaoin.ide.flow :refer [run-ide-script]]) - (:gen-class)) + (:require [clojure.java.io :as io] + [clojure.string :as str] + [clojure.tools.cli :refer [parse-opts]] + [etaoin.api :as api] + [etaoin.ide.flow :as flow] + [etaoin.util :refer [exit]]) + (:gen-class)) +(def browsers-set + #{:chrome :safari :firefox :edge :phantom}) -(defn -main - [& args]) +(defn str->vec + [string] + (str/split string #",")) + +(def cli-options + [["-d" "--driver-name name" "The name of driver. The default is `chrome`" + :default :chrome + :parse-fn keyword + :validate [browsers-set + (str "Must be one of the list items - " (str/join ", " (map name browsers-set)))]] + + ["-p" "--params params" "Parameters for the driver represented as edn string" + :default {} + :parse-fn read-string] + + ["-f" "--file path" "Path to the ide file on disk"] + + ["-r" "--resource path" "Path to the resource"] + + [nil "--test-ids ids" "Comma-separeted test ID(s)" + :parse-fn str->vec] + + [nil "--suite-ids ids" "Comma-separeted suite ID(s)" + :parse-fn str->vec] + + [nil "--test-names names" "Comma-separeted test name(s)" + :parse-fn str->vec] + + [nil "--suite-names names" "Comma-separeted suite name(s)" + :parse-fn str->vec] + + [nil "--base-url url" "Base url for test"] + ["-h" "--help"]]) + +(def help + "This is cli interface for running ide files. + +Usage examples: + +lein run -m etaoin.ide.main -d firefox -p '{:port 8888 :args [\"--no-sandbox\"]} -r ide/test.side + +java -cp .../poject.jar -m etaoin.ide.main -d firefox -p '{:port 8888} -f ide/test.side + +Options:") + +(defn usage [options-summary] + (->> [help options-summary] + (str/join \newline))) + +(defn error-msg [errors] + (str "The following errors occurred while parsing your command:\n\n" + (str/join \newline errors))) + +(defn run-script + [source {:keys [driver-name params] :as options}] + (let [opt (select-keys options [:base-url :test-ids + :test-names :suite-ids + :suite-names])] + (api/with-driver driver-name params driver + (flow/run-ide-script driver source opt)))) + +(defn -main [& args] + (let [{:keys [errors summary options]} (parse-opts args cli-options) + {:keys [help file resource]} options] + (cond + errors + (exit 1 (error-msg errors)) + + help + (exit 0 (usage summary)) + + file + (let [ide-file (io/file file)] + (when-not (and (.exists ide-file) + (not (.isDirectory ide-file))) + (exit 1 "The IDE file not found")) + (run-script ide-file options)) + + resource + (if-let [r (io/resource resource)] + (run-script r options) + (exit 1 "Resource not found")) + + :else + (exit 1 "Specify the path to the ide file: `--file` or `--resource`")))) diff --git a/src/etaoin/util.clj b/src/etaoin/util.clj index aa4248ff..1d007b52 100644 --- a/src/etaoin/util.clj +++ b/src/etaoin/util.clj @@ -50,3 +50,13 @@ (when (.isConnected socket) (.close socket) true))) + +(defn exit + [code template & args] + (let [out (if (zero? code) + *out* + *err*)] + (binding [*out* out] + (println (apply format + template args)))) + (System/exit code))