diff --git a/notebook/2AU6K8KS2/note.json b/notebook/2AU6K8KS2/note.json new file mode 100644 index 00000000000..0af0d4bf661 --- /dev/null +++ b/notebook/2AU6K8KS2/note.json @@ -0,0 +1,241 @@ +{ + "paragraphs": [ + { + "text": "%md\n## Welcome to Zeppelin.\n##### This is a quickly start on zeppelin map visualization tutorial. It is using Leaflet mapping basics, including setting up a Leaflet map, working with markers, polylines and popups, and dealing with events.you can run the code yourself. (Shift-Enter to Run)", + "config": { + "colWidth": 12.0, + "graph": { + "mode": "table", + "height": 300.0, + "optionOpen": false, + "keys": [], + "values": [], + "groups": [], + "scatter": {} + }, + "editorHide": false, + "tableHide": true + }, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1437313582566_-967040274", + "id": "20150719-191622_9501079", + "result": { + "code": "SUCCESS", + "type": "HTML", + "msg": "\u003ch2\u003eWelcome to Zeppelin.\u003c/h2\u003e\n\u003ch5\u003eThis is a quickly start on zeppelin map visualization tutorial. It is using Leaflet mapping basics, including setting up a Leaflet map, working with markers, polylines and popups, and dealing with events.you can run the code yourself. (Shift-Enter to Run)\u003c/h5\u003e\n" + }, + "dateCreated": "Jul 19, 2015 7:16:22 PM", + "dateStarted": "Jul 25, 2015 8:43:03 AM", + "dateFinished": "Jul 25, 2015 8:43:03 AM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "text": "import org.apache.commons.io.IOUtils\nimport java.net.URL\nimport java.nio.charset.Charset\n\n// Zeppelin creates and injects sc (SparkContext) and sqlContext (HiveContext or SqlContext)\n// So you don\u0027t need create them manually\n\n// load map data\nval myMapText \u003d sc.parallelize(\n IOUtils.toString(\n new URL(\"https://gist.githubusercontent.com/Madhuka/74cb9a6577c87aa7d2fd/raw/2f758d33d28ddc01c162293ad45dc16be2806a6b/data.csv\"),\n Charset.forName(\"utf8\")).split(\"\\n\"))\n\n\ncase class Map(Country:String, Name:String, lat : Float, lan : Float, Altitude : Float)\n\nval myMap \u003d myMapText.map(s\u003d\u003es.split(\",\")).filter(s\u003d\u003es(0)!\u003d\"Country\").map(\n s\u003d\u003eMap(s(0), \n s(1),\n s(2).toFloat,\n s(3).toFloat,\n s(4).toFloat\n )\n)\n\n// Below line works only in spark 1.3.0.\n// For spark 1.1.x and spark 1.2.x,\n// use myMap.registerTempTable(\"myMap\") instead.\nmyMap.toDF().registerTempTable(\"myMap\")\n", + "config": { + "colWidth": 12.0, + "graph": { + "mode": "table", + "height": 300.0, + "optionOpen": false, + "keys": [], + "values": [], + "groups": [], + "scatter": {} + } + }, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1437314214306_141157507", + "id": "20150719-192654_12434929", + "result": { + "code": "SUCCESS", + "type": "TEXT", + "msg": "import org.apache.commons.io.IOUtils\nimport java.net.URL\nimport java.nio.charset.Charset\nmyMapText: org.apache.spark.rdd.RDD[String] \u003d ParallelCollectionRDD[28] at parallelize at \u003cconsole\u003e:35\ndefined class Map\nmyMap: org.apache.spark.rdd.RDD[Map] \u003d MapPartitionsRDD[31] at map at \u003cconsole\u003e:35\n" + }, + "dateCreated": "Jul 19, 2015 7:26:54 PM", + "dateStarted": "Jul 25, 2015 8:42:17 AM", + "dateFinished": "Jul 25, 2015 8:42:24 AM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "text": "%sql \nselect * from myMap\nwhere Country \u003d \"${Country\u003d\u0027United States\u0027}\"", + "config": { + "colWidth": 6.0, + "graph": { + "mode": "mapChart", + "height": 300.0, + "optionOpen": false, + "keys": [ + { + "name": "Country", + "index": 0.0, + "aggr": "sum" + } + ], + "values": [ + { + "name": "Name", + "index": 1.0, + "aggr": "sum" + } + ], + "groups": [], + "scatter": { + "xAxis": { + "name": "Country", + "index": 0.0, + "aggr": "sum" + }, + "yAxis": { + "name": "Name", + "index": 1.0, + "aggr": "sum" + } + } + }, + "editorHide": true + }, + "settings": { + "params": { + "Country": "United States" + }, + "forms": { + "Country": { + "name": "Country", + "defaultValue": "\u0027United States\u0027", + "hidden": false + } + } + }, + "jobName": "paragraph_1437316940442_271264979", + "id": "20150719-201220_10279868", + "result": { + "code": "SUCCESS", + "type": "TABLE", + "msg": "Country\tName\tlat\tlan\tAltitude\nUnited States\tNew York City\t40.714268\t-74.005974\t2.0\nUnited States\tLos Angeles\t34.052235\t-118.24368\t115.0\nUnited States\tChicago\t41.850033\t-87.650055\t181.0\nUnited States\tHouston\t29.763283\t-95.36327\t15.0\nUnited States\tPhiladelphia\t39.952335\t-75.16379\t8.0\nUnited States\tPhoenix\t33.448376\t-112.074036\t0.0\nUnited States\tSan Antonio\t29.424122\t-98.49363\t196.0\nUnited States\tSan Diego\t32.71533\t-117.15726\t26.0\nUnited States\tDallas\t32.783054\t-96.80666\t137.0\nUnited States\tDetroit\t42.33143\t-83.04575\t181.0\nUnited States\tSan Jose\t37.339386\t-121.89496\t24.0\nUnited States\tJacksonville\t30.332184\t-81.65565\t7.0\nUnited States\tIndianapolis\t39.768375\t-86.15804\t222.0\nUnited States\tColumbus\t39.961174\t-82.998795\t237.0\nUnited States\tSan Francisco\t37.77493\t-122.41942\t60.0\nUnited States\tAustin\t30.267153\t-97.74306\t163.0\nUnited States\tMemphis\t35.149536\t-90.04898\t75.0\nUnited States\tNew South Memphis\t35.086758\t-90.056755\t74.0\nUnited States\tFort Worth\t32.72541\t-97.32085\t199.0\nUnited States\tBaltimore\t39.290386\t-76.61219\t2.0\nUnited States\tCharlotte\t35.227085\t-80.843124\t229.0\nUnited States\tBoston\t42.35843\t-71.05978\t11.0\nUnited States\tMilwaukee\t43.038902\t-87.90647\t195.0\nUnited States\tSouth Boston\t42.33343\t-71.04949\t10.0\nUnited States\tSeattle\t47.60621\t-122.33207\t60.0\nUnited States\tEl Paso\t31.75872\t-106.48693\t1147.0\nUnited States\tDenver\t39.739155\t-104.9847\t1598.0\nUnited States\tWashington\t38.89511\t-77.03637\t11.0\nUnited States\tPortland\t45.523453\t-122.67621\t61.0\nUnited States\tOklahoma City\t35.46756\t-97.516426\t364.0\nUnited States\tNashville\t36.16589\t-86.78445\t151.0\nUnited States\tTucson\t32.221745\t-110.926476\t751.0\nUnited States\tAlbuquerque\t35.08449\t-106.65114\t1510.0\nUnited States\tNew Orleans\t29.954649\t-90.07507\t0.0\nUnited States\tLong Beach\t33.766964\t-118.18923\t1.0\nUnited States\tLas Vegas\t36.17497\t-115.13722\t609.0\nUnited States\tSacramento\t38.581573\t-121.4944\t5.0\nUnited States\tFresno\t36.747726\t-119.77237\t91.0\nUnited States\tCleveland\t41.499496\t-81.69541\t185.0\nUnited States\tNorth Kansas City\t39.130005\t-94.56218\t223.0\nUnited States\tKansas City\t39.099728\t-94.57857\t271.0\nUnited States\tVirginia Beach\t36.85293\t-75.97798\t3.0\nUnited States\tAtlanta\t33.748997\t-84.387985\t305.0\nUnited States\tOakland\t37.80437\t-122.270805\t0.0\nUnited States\tMesa\t33.422268\t-111.82264\t386.0\nUnited States\tTulsa\t36.15398\t-95.992775\t213.0\nUnited States\tOmaha\t41.25861\t-95.93779\t0.0\nUnited States\tMiami\t25.774265\t-80.19366\t2.0\nUnited States\tHonolulu\t21.306944\t-157.85834\t0.0\nUnited States\tMinneapolis\t44.979965\t-93.26384\t259.0\nUnited States\tColorado Springs\t38.83388\t-104.821365\t1829.0\nUnited States\tWichita\t37.692238\t-97.33755\t402.0\nUnited States\tSanta Ana\t33.745575\t-117.867836\t30.0\nUnited States\tWest Raleigh\t35.78682\t-78.663895\t122.0\nUnited States\tArlington\t32.735687\t-97.10806\t184.0\nUnited States\tAnaheim\t33.835293\t-117.914505\t40.0\nUnited States\tTampa\t27.947521\t-82.45843\t1.0\nUnited States\tSaint Louis\t38.627274\t-90.19789\t135.0\nUnited States\tPittsburgh\t40.440624\t-79.99589\t235.0\nUnited States\tToledo\t41.663937\t-83.555214\t191.0\nUnited States\tCincinnati\t39.162003\t-84.45689\t203.0\nUnited States\tRiverside\t33.95335\t-117.39616\t262.0\nUnited States\tBakersfield\t35.37329\t-119.018715\t122.0\nUnited States\tStockton\t37.957703\t-121.29078\t4.0\nUnited States\tNewark\t40.735657\t-74.17236\t16.0\nUnited States\tBuffalo\t42.886448\t-78.87837\t183.0\nUnited States\tCorpus Christi\t27.800583\t-97.39638\t6.0\nUnited States\tAurora\t39.72943\t-104.83192\t1647.0\nUnited States\tRaleigh\t35.772095\t-78.63861\t91.0\nUnited States\tSaint Paul\t44.94441\t-93.09328\t235.0\nUnited States\tLexington-Fayette\t38.0498\t-84.45855\t312.0\nUnited States\tAnchorage\t61.218056\t-149.90028\t0.0\nUnited States\tPlano\t33.019844\t-96.69888\t200.0\nUnited States\tSaint Petersburg\t27.77086\t-82.67927\t14.0\nUnited States\tLouisville\t38.25424\t-85.75941\t128.0\nUnited States\tLincoln\t40.8\t-96.66696\t382.0\nUnited States\tGlendale\t33.53865\t-112.18599\t336.0\nUnited States\tHenderson\t36.0397\t-114.98193\t580.0\nUnited States\tJersey City\t40.728157\t-74.077644\t14.0\nUnited States\tNorfolk\t36.846813\t-76.28522\t3.0\nUnited States\tChandler\t33.30616\t-111.84125\t380.0\nUnited States\tGreensboro\t36.072636\t-79.79198\t244.0\nUnited States\tBirmingham\t33.52066\t-86.80249\t173.0\nUnited States\tFort Wayne\t41.130604\t-85.12886\t243.0\nUnited States\tLexington\t37.98869\t-84.477715\t298.0\nUnited States\tHialeah\t25.857595\t-80.27811\t2.0\nUnited States\tMadison\t43.07305\t-89.40123\t270.0\nUnited States\tBaton Rouge\t30.450747\t-91.15455\t0.0\nUnited States\tGarland\t32.912624\t-96.638885\t165.0\nUnited States\tModesto\t37.639095\t-120.99688\t12.0\nUnited States\tParadise\t36.097195\t-115.14667\t626.0\nUnited States\tChula Vista\t32.640053\t-117.0842\t23.0\nUnited States\tLubbock\t33.57786\t-101.85516\t976.0\nUnited States\tRochester\t43.154785\t-77.615555\t155.0\nUnited States\tLaredo\t27.506407\t-99.507545\t115.0\nUnited States\tAkron\t41.081444\t-81.519005\t290.0\nUnited States\tOrlando\t28.538336\t-81.379234\t34.0\nUnited States\tDurham\t35.994034\t-78.89862\t122.0\nUnited States\tNorth Glendale\t34.160564\t-118.26452\t174.0\nUnited States\tScottsdale\t33.50921\t-111.89903\t386.0\n" + }, + "dateCreated": "Jul 19, 2015 8:12:20 PM", + "dateStarted": "Jul 25, 2015 8:42:17 AM", + "dateFinished": "Jul 25, 2015 8:42:24 AM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "text": "%sql \nselect * from myMap\nwhere Altitude \u003e ${Altitude\u003d300}", + "config": { + "colWidth": 6.0, + "graph": { + "mode": "mapChart", + "height": 300.0, + "optionOpen": false, + "keys": [ + { + "name": "Country", + "index": 0.0, + "aggr": "sum" + } + ], + "values": [ + { + "name": "Name", + "index": 1.0, + "aggr": "sum" + } + ], + "groups": [], + "scatter": { + "xAxis": { + "name": "Country", + "index": 0.0, + "aggr": "sum" + }, + "yAxis": { + "name": "Name", + "index": 1.0, + "aggr": "sum" + } + } + }, + "editorHide": true + }, + "settings": { + "params": { + "Altitude": "400" + }, + "forms": { + "Altitude": { + "name": "Altitude", + "defaultValue": "300", + "hidden": false + } + } + }, + "jobName": "paragraph_1437317266677_-261952669", + "id": "20150719-201746_23407076", + "result": { + "code": "SUCCESS", + "type": "TABLE", + "msg": "Country\tName\tlat\tlan\tAltitude\nUnited States\tEl Paso\t31.75872\t-106.48693\t1147.0\nUnited States\tDenver\t39.739155\t-104.9847\t1598.0\nUnited States\tTucson\t32.221745\t-110.926476\t751.0\nUnited States\tAlbuquerque\t35.08449\t-106.65114\t1510.0\nUnited States\tLas Vegas\t36.17497\t-115.13722\t609.0\nUnited States\tColorado Springs\t38.83388\t-104.821365\t1829.0\nUnited States\tWichita\t37.692238\t-97.33755\t402.0\nUnited States\tAurora\t39.72943\t-104.83192\t1647.0\nUnited States\tHenderson\t36.0397\t-114.98193\t580.0\nUnited States\tParadise\t36.097195\t-115.14667\t626.0\nUnited States\tLubbock\t33.57786\t-101.85516\t976.0\n" + }, + "dateCreated": "Jul 19, 2015 8:17:46 PM", + "dateStarted": "Jul 25, 2015 8:42:24 AM", + "dateFinished": "Jul 25, 2015 8:42:24 AM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "text": "", + "config": { + "colWidth": 12.0, + "graph": { + "mode": "table", + "height": 300.0, + "optionOpen": false, + "keys": [], + "values": [], + "groups": [], + "scatter": {} + } + }, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1437793749347_527943396", + "id": "20150725-083909_25279730", + "result": { + "code": "SUCCESS", + "type": "TEXT" + }, + "dateCreated": "Jul 25, 2015 8:39:09 AM", + "dateStarted": "Jul 25, 2015 8:42:24 AM", + "dateFinished": "Jul 25, 2015 8:42:24 AM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + } + ], + "name": "Map Visualization Tutorial", + "id": "2AU6K8KS2", + "angularObjects": { + "2AVFWDXQ8": [], + "2AW52KKF2": [], + "2AWBECUSM": [], + "2ATG5P9DG": [], + "2AUPDKZH1": [], + "2AVUJ5W2S": [], + "2AUSHYMSD": [], + "2ATHTSAJV": [], + "2AUZPG9UC": [] + }, + "config": { + "looknfeel": "default" + }, + "info": {} +} \ No newline at end of file diff --git a/zeppelin-web/bower.json b/zeppelin-web/bower.json index 04bdbf86b70..2a5f986fbe5 100644 --- a/zeppelin-web/bower.json +++ b/zeppelin-web/bower.json @@ -26,7 +26,9 @@ "highlightjs": "~8.4.0", "lodash": "~3.9.3", "angular-filter": "~0.5.4", - "ngtoast": "~1.5.5" + "ngtoast": "~1.5.5", + "leaflet": "~0.7.3", + "angular-leaflet-directive": "~0.8.5" }, "devDependencies": { "angular-mocks": "1.3.8" diff --git a/zeppelin-web/src/app/app.js b/zeppelin-web/src/app/app.js index b4a769bab91..9a255c1abf8 100644 --- a/zeppelin-web/src/app/app.js +++ b/zeppelin-web/src/app/app.js @@ -31,7 +31,8 @@ angular.module('zeppelinWebApp', [ 'monospaced.elastic', 'puElasticInput', 'xeditable', - 'ngToast' + 'ngToast', + 'leaflet-directive' ]) .filter('breakFilter', function() { return function (text) { diff --git a/zeppelin-web/src/app/notebook/notebook.css b/zeppelin-web/src/app/notebook/notebook.css index 0d3de89b64d..00bf86757e4 100644 --- a/zeppelin-web/src/app/notebook/notebook.css +++ b/zeppelin-web/src/app/notebook/notebook.css @@ -456,6 +456,15 @@ margin-bottom: 5px !important; } +.angular-leaflet-map { + height: 300px; + width: 100%; +} + +.graphContainer .mapChart { + overflow: hidden; +} + .allFields { margin-bottom: 10px; } diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index 08eb657b9c8..2a5dbc0c0c0 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -17,7 +17,7 @@ angular.module('zeppelinWebApp') .controller('ParagraphCtrl', function($scope,$rootScope, $route, $window, $element, $routeParams, $location, - $timeout, $compile, websocketMsgSrv) { + $timeout, $compile, websocketMsgSrv, leafletBoundsHelpers, dataValidatorSrv) { $scope.paragraph = null; $scope.editor = null; @@ -730,6 +730,10 @@ angular.module('zeppelinWebApp') } }; + $scope.defaults= { + scrollWheelZoom: false + }; + $scope.setGraphMode = function(type, emit, refresh) { if (emit) { setNewMode(type); @@ -742,6 +746,9 @@ angular.module('zeppelinWebApp') if (!type || type === 'table') { setTable($scope.paragraph.result, refresh); } + if (!type || type === 'mapChart') { + setMapChart(type, $scope.paragraph.result, refresh); + } else { setD3Chart(type, $scope.paragraph.result, refresh); } @@ -846,6 +853,56 @@ angular.module('zeppelinWebApp') }; + var setMapChart = function(type, data, refresh) { + var latArr = [], + lngArr = [], + newmarkers = {}; + if (!$scope.chart[type]) { + + var mapChartModel = function(d) { + var key = d[1].replace('-', '_'); + var obj = {}; + latArr.push(Math.round(parseFloat(d[2]))); + lngArr.push(Math.round(parseFloat(d[3]))); + obj[key] = { + lat: parseFloat(d[2]), + lng: parseFloat(d[3]), + message: d[1], + focus: true, + draggable: false + }; + return obj; + }; + + for (var i = 0; i < data.rows.length; i++) { + var row = data.rows[i]; + var rowMarker = mapChartModel(row); + newmarkers = $.extend(newmarkers, rowMarker); + } + } + //data model validator + var msg = dataValidatorSrv.validateMapData(data); + //TODO- warning need to be show in here. currently it is only printing. + //need to know what is the standard way of warning in zepplin. + if(msg.error){ + console.log(msg.msg); + }else{ + //drawing map deatils if only data set is validated. + $scope.markers = newmarkers; + var bounds = leafletBoundsHelpers.createBoundsFromArray([ + [Math.max.apply(Math, latArr), Math.max.apply(Math, lngArr)], + [Math.min.apply(Math, latArr), Math.min.apply(Math, lngArr)] + ]); + $scope.bounds = bounds; + + + // set map chart height + var height = $scope.paragraph.config.graph.height; + $('#p'+$scope.paragraph.id+'_mapChart').height(height); + } + $scope.center = {}; + }; + var setD3Chart = function(type, data, refresh) { if (!$scope.chart[type]) { var chart = nv.models[type](); @@ -1251,6 +1308,7 @@ angular.module('zeppelinWebApp') var schema = data.schema; var rows = data.rows; + //check for d3s var values = $scope.paragraph.config.graph.values; var concat = function(o, n) { @@ -1348,6 +1406,12 @@ angular.module('zeppelinWebApp') }); } + var msg = dataValidatorSrv.validateChartData(data); + //Only console print error found + if(msg.error){ + console.log(msg.msg); + } + // clear aggregation name, if possible var namesWithoutAggr = {}; var colName; @@ -1393,7 +1457,6 @@ angular.module('zeppelinWebApp') } } - return { xLabels : rowIndexValue, d3g : d3g @@ -1483,8 +1546,15 @@ angular.module('zeppelinWebApp') }; } + var msg = dataValidatorSrv.validateScatterData(data); + //TODO- warning need to error model or services will needed + if(msg.error){ + console.log(msg.msg); + } + for (var i = 0; i < data.rows.length; i++) { row = data.rows[i]; + if (xAxis) { xValue = row[xAxis.index]; xValues[i] = xValue; diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.html b/zeppelin-web/src/app/notebook/paragraph/paragraph.html index 4d0f4510fc7..7478e870aa3 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.html +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.html @@ -129,8 +129,12 @@ ng-class="{'active': isGraphMode('scatterChart')}" ng-click="setGraphMode('scatterChart', true)"> + - @@ -333,6 +337,11 @@ id="p{{paragraph.id}}_scatterChart"> + +
+
+ + @@ -115,6 +117,9 @@ + + + @@ -137,6 +142,12 @@ + + + + + + diff --git a/zeppelin-web/test/karma.conf.js b/zeppelin-web/test/karma.conf.js index d76f72cb661..b0cb2e61b5a 100644 --- a/zeppelin-web/test/karma.conf.js +++ b/zeppelin-web/test/karma.conf.js @@ -54,10 +54,14 @@ module.exports = function(config) { 'bower_components/lodash/lodash.js', 'bower_components/angular-filter/dist/angular-filter.min.js', 'bower_components/ngtoast/dist/ngToast.js', + 'bower_components/leaflet/dist/leaflet.js', + 'bower_components/leaflet/dist/leaflet-src.js', + 'bower_components/angular-leaflet-directive/dist/angular-leaflet-directive.js', 'bower_components/angular-mocks/angular-mocks.js', // endbower 'src/app/app.js', 'src/app/app.controller.js', + 'src/components/data-validator/*.js', 'src/app/**/*.js', 'test/spec/**/*.js' ], diff --git a/zeppelin-web/test/spec/components/data-validator/chart-data-validator-test.js b/zeppelin-web/test/spec/components/data-validator/chart-data-validator-test.js new file mode 100644 index 00000000000..fa3f080ecba --- /dev/null +++ b/zeppelin-web/test/spec/components/data-validator/chart-data-validator-test.js @@ -0,0 +1,67 @@ +'use strict'; + +describe('DataValidatorSrv ', function() { + beforeEach(module('zeppelinWebApp')); + + var chartDataValidatorSrv; + beforeEach(inject(function(dataValidatorSrv) { + chartDataValidatorSrv = dataValidatorSrv; + })); + + describe('validateChartData function', function() { + + var mockDataOne = { + 'schema': Object, + 'rows': Object + }; + it('testing with empty data', function() { + expect(chartDataValidatorSrv.validateChartData({}).error).toBe( + true); + expect(chartDataValidatorSrv.validateChartData({}).msg).toBe( + 'data rows does not exisiting | '); + }); + it('testing with data contain empty rows objects', function() { + expect(chartDataValidatorSrv.validateChartData({}).error).toBe( + true); + expect(chartDataValidatorSrv.validateChartData({}).msg).toBe( + 'data rows does not exisiting | '); + }); + //mock correct data set model + var mockRecord = { + 'value(sum)': { + 'count': 1, + 'value': '4' + } + }; + var mockRow = { + '19': mockRecord + }; + mockDataOne.rows = mockRow; + it('testing with validated data', function() { + expect(chartDataValidatorSrv.validateChartData(mockDataOne).error) + .toBe(false); + expect(chartDataValidatorSrv.validateChartData(mockDataOne).msg) + .toBe(''); + }); + //mock incorrect data set model + var incorrectMockRecord = { + 'value(sum)': { + 'count': 1, + 'value': 'wrong' + } + }; + var incorrectMockRow = { + '23': incorrectMockRecord + }; + var mockDataTwo = { + 'schema': Object, + 'rows': incorrectMockRow + }; + it('testing with invalidated data', function() { + expect(chartDataValidatorSrv.validateChartData(mockDataTwo).error) + .toBe(true); + expect(chartDataValidatorSrv.validateChartData(mockDataTwo).msg) + .toBe('data record wrong is not matching for schema | '); + }); + }); +}); \ No newline at end of file diff --git a/zeppelin-web/test/spec/components/data-validator/data-validator-service.js b/zeppelin-web/test/spec/components/data-validator/data-validator-service.js new file mode 100644 index 00000000000..b2a8ab5bd73 --- /dev/null +++ b/zeppelin-web/test/spec/components/data-validator/data-validator-service.js @@ -0,0 +1,35 @@ +'use strict'; + +describe('Service : DataValidatorSrv', function() { + beforeEach(module('zeppelinWebApp')); + + var chartDataValidatorSrv; + beforeEach(inject(function(dataValidatorSrv) { + chartDataValidatorSrv = dataValidatorSrv; + })); + + describe('Testing API', function() { + + it('to be define', function() { + expect(chartDataValidatorSrv).toBeDefined(); + }); + + it('Services to be define', function() { + expect(chartDataValidatorSrv.validateMapData).toBeDefined(); + expect(chartDataValidatorSrv.validateScatterData).toBeDefined(); + expect(chartDataValidatorSrv.validateChartData).toBeDefined(); + }); + //mock data for testing + var mockData = { + 'schema': Object, + 'rows': Object + }; + it('testing return message format', function() { + expect(chartDataValidatorSrv.validateChartData(mockData).msg) + .toBeDefined(); + expect(chartDataValidatorSrv.validateChartData(mockData).error) + .toBeDefined(); + }); + + }); +}); \ No newline at end of file diff --git a/zeppelin-web/test/spec/components/data-validator/map-data-validator-test.js b/zeppelin-web/test/spec/components/data-validator/map-data-validator-test.js new file mode 100644 index 00000000000..62659214160 --- /dev/null +++ b/zeppelin-web/test/spec/components/data-validator/map-data-validator-test.js @@ -0,0 +1,47 @@ +'use strict'; + +describe('DataValidatorSrv ', function() { + beforeEach(module('zeppelinWebApp')); + + var chartDataValidatorSrv; + beforeEach(inject(function(dataValidatorSrv) { + chartDataValidatorSrv = dataValidatorSrv; + })); + + describe('validateMapData function', function() { + + var mockDataOne = { + 'msg': 'mock data', + 'code': 'SUCCESS', + 'rows': [ + ['us', 'El paso', '31.758', '-106.4869', '1147'] + ] + }; + //test use case + //testing with correct validated data set then change data and test again + it('testing with validate GIS data and range check', function() { + expect(chartDataValidatorSrv.validateMapData(mockDataOne).error) + .toBe( + false); + expect(chartDataValidatorSrv.validateMapData(mockDataOne).msg) + .toBe( + 'data is exisiting | latitudes are ok | longitude are ok | '); + //change number to string and test + mockDataOne.rows[0][3] = 'text'; + expect(chartDataValidatorSrv.validateMapData(mockDataOne).error) + .toBe( + true); + expect(chartDataValidatorSrv.validateMapData(mockDataOne).msg) + .toContain('data record text is not matching for schema'); + //testing for Longitude range + mockDataOne.rows[0][3] = 250; + expect(chartDataValidatorSrv.validateMapData(mockDataOne).error) + .toBe( + true); + expect(chartDataValidatorSrv.validateMapData(mockDataOne).msg) + .toBe('data is exisiting | latitudes are ok | Longitude250 is not in range | '); + }); + + }); + +}); \ No newline at end of file diff --git a/zeppelin-web/test/spec/components/data-validator/scatter-data-validator-test.js b/zeppelin-web/test/spec/components/data-validator/scatter-data-validator-test.js new file mode 100644 index 00000000000..c8bf2d9acb3 --- /dev/null +++ b/zeppelin-web/test/spec/components/data-validator/scatter-data-validator-test.js @@ -0,0 +1,63 @@ +'use strict'; + +describe('DataValidatorSrv ', function() { + beforeEach(module('zeppelinWebApp')); + + var validateScatterDataSrv; + beforeEach(inject(function(dataValidatorSrv) { + validateScatterDataSrv = dataValidatorSrv; + })); + + describe('validateScatterData function', function() { + + var mockDataOne = { + 'code': 'SUCCESS', + 'rows': Object + }; + it('testing with empty data', function() { + expect(validateScatterDataSrv.validateScatterData({}).error).toBe( + true); + expect(validateScatterDataSrv.validateScatterData({}).msg).toBe( + 'data rows does not exisiting | data does not exisiting | ' + ); + }); + it('testing with data contain empty rows objects', function() { + //mockDataOne.rows = [[]]; + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .error).toBe( + true); + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .msg).toContain( + 'data is exisiting | '); + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .msg).toContain( + 'data record does not exisiting | '); + }); + + it('testing with valid data ', function() { + mockDataOne.rows = [ + [12, 34] + ]; + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .error).toBe( + false); + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .msg).toBe( + 'data is exisiting | '); + }); + + it('testing with string data model', function() { + mockDataOne.rows = [ + ['test', '34'] + ]; + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .error).toBe( + true); + expect(validateScatterDataSrv.validateScatterData(mockDataOne) + .msg).toBe( + 'data record test is not matching for schema | data record does not mapping to data schema| data is exisiting | ' + ); + }); + + }); +}); \ No newline at end of file