Best JavaScript code snippet using appium-android-driver
Gruntfile.js
Source:Gruntfile.js
1'use strict';2var LIVERELOAD_PORT = 35729;3var SERVER_PORT = 8000;4var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});5var mountFolder = function (connect, dir) {6 return connect.static(7 require('path').resolve(dir),8 {9 // We need to specify a file that will be displayed in place of10 // index.html. _.html is used because it is unlikely to exist.11 index: '_.html'12 }13 );14};15var mountDirectory = function(connect, dir) {16 return connect.directory(17 require('path').resolve(dir),18 {19 icons: true,20 }21 );22};23var postHandler = function(req, res, next) {24 if (req.method === 'POST') {25 //debugger;26 console.log('received a POST request');27 var mkdirp = require('mkdirp');28 var fs = require('fs');29 // We don't want the leading /, or else the file system will think30 // we're writing to root, which we don't have permission to. Should31 // really be dealing with the path more gracefully.32 var path = req.url.substring(1);33 34 // First make sure the directory exists, or else the following call to35 // createWriteStream fails. We don't want to include the file name as36 // part of the directory, or else our post will be trying to change the37 // directory to become a file with content, which will fail.38 var lastDelimiter = path.lastIndexOf('/');39 if (lastDelimiter >= 0) {40 var directories = path.substring(0, lastDelimiter);41 mkdirp.sync(directories);42 }43 var file = fs.createWriteStream(path);44 req.pipe(file);45 file.on('error', function(err) {46 res.write('error uploading the file');47 res.write(JSON.stringify(err));48 res.statusCode = 500;49 });50 req.on('end', function() {51 res.write('uploaded file!');52 res.end();53 });54 } else {55 // We only want to hand this off to the other middleware if this56 // is not a POST, as we're expecting to be the only ones to57 // handle POSTs.58 return next();59 }60};61// # Globbing62// for performance reasons we're only matching one level down:63// 'test/spec/{,*/}*.js'64// use this if you want to match all subfolders:65// 'test/spec/**/*.js'66// templateFramework: 'lodash'67module.exports = function (grunt) {68 // show elapsed time at the end69 require('time-grunt')(grunt);70 // load all grunt tasks71 require('load-grunt-tasks')(grunt);72 // We do not want the default behavior of serving only the app folder.73 // Instead we want to serve the base repo directory, as this will give us74 // access to the test dir as well. Further, if you don't have a homescreen75 // defined, it doesn't really make sense to have a single index.html.76 var baseDirForServer = '';77 var tablesConfig = {78 // The base app directory. Note that if you modify this you should79 // also modify the other properties in this object that refer to 80 // app81 appDir: 'app',82 appName: 'tables',83 // The mount point of the device. Should allow adb push/pull.84 deviceMount: '/sdcard/opendatakit',85 // The mount point of the device for odk collect forms.86 formMount: '/sdcard/odk/forms',87 // The directory where the 'tables' directory containing the tableId88 // directories lives.89 tablesDir: 'app/config/tables',90 // Where the templates for a new tableId folder lives. i.e. if you want91 // to add a table, the contents of this directory would be copied to92 // tablesDir/tableId.93 tableTemplateDir: 'grunttemplates/table/default',94 // tableIdStr will be what we replace in the table template with the95 // provided tableId. E.g. '../%TABLE_ID%_list.html' will become96 // '../myTableId_list.html'97 tableIdStr: '%TABLE_ID%',98 // The string we need to replace with the app name.99 appStr: '%APP%',100 // The output directory101 outputDbDir: 'output/db',102 // The directory where csvs are output.103 outputCsvDir: 'output/csv',104 // The directory where the debug objects are output.105 outputDebugDir: 'output/debug',106 // The db path on the phone. %APP% should be replaced by app name107 deviceDbPath: '/sdcard/opendatakit/%APP%/data/webDb/sqlite.db',108 xlsxDir: 'xlsxconverter'109 110 };111 var surveyConfig = {112 // The base app directory. Note that if you modify this you should113 // also modify the other properties in this object that refer to 114 // app115 appDir: 'app',116 appName: 'survey',117 // The mount point of the device. Should allow adb push/pull.118 deviceMount: '/sdcard/opendatakit',119 xlsxDir: 'xlsxconverter'120 121 };122 grunt.initConfig({123 // Here we have to set the objects for the exec task. We are using124 // grunt-exec to execute the adb push and adb pull commands.125 // cmd is the command that is run when calling this task with the126 // target and must return a string.127 exec: {128 adbpush: {129 cmd: function(src, dest) {130 return 'adb push ' + src + ' ' + dest;131 }132 },133 adbpull: {134 cmd: function(src, dest) {135 return 'adb pull ' + src + ' ' + dest;136 }137 },138 adbshell: {139 cmd: function(str) {140 return 'adb shell ' + str;141 }142 }143 },144 tables: tablesConfig,145 watch: {146 options: {147 nospawn: true,148 livereload: true149 },150 livereload: {151 options: {152 livereload: LIVERELOAD_PORT153 },154 files: [155 '<%= tables.appDir %>/*.html',156 'test/tables/**/*.js',157 '<%= tables.appDir %>/system/**',158 '<%= tables.appDir %>/config/**',159 '<%= tables.appDir %>/themeGenerator/*'160 ]161 },162 test: {163 files: ['test/spec/**/*.js'],164 tasks: ['test']165 }166 },167 connect: {168 options: {169 port: SERVER_PORT,170 // change this to '0.0.0.0' to access the server from outside171 hostname: '0.0.0.0'172 },173 livereload: {174 options: {175 middleware: function (connect) {176 return [177 postHandler,178 lrSnippet,179 mountFolder(connect, baseDirForServer),180 mountDirectory(connect, baseDirForServer)181 ];182 }183 }184 },185 test: {186 options: {187 port: 8001,188 middleware: function (connect) {189 return [190 postHandler,191 lrSnippet,192 mountFolder(connect, 'test'),193 mountFolder(connect, baseDirForServer),194 mountDirectory(connect, baseDirForServer)195 ];196 }197 }198 }199 },200 open: {201 server: {202 path: 'http://localhost:<%= connect.options.port %>/index.html',203 app: (function() {204 var platform = require('os').platform();205 // windows: *win*206 // mac: darwin207 if (platform.search('win') >= 0 &&208 platform.search('darwin') < 0) {209 // Windows expects chrome.210 grunt.log.writeln('detected Windows environment');211 return 'chrome';212 } else {213 // Mac (and maybe others--add as discovered), expects214 // Google Chrome215 grunt.log.writeln('detected non-Windows environment');216 return 'Google Chrome';217 }218 })()219 }220 },221 });222 // We need grunt-exec to run adb commands from within grunt. 223 grunt.loadNpmTasks('grunt-exec');224 // Just an alias task--shorthand for doing all the pullings225 grunt.registerTask(226 'adbpull',227 'Perform all the adbpull tasks',228 ['adbpull-debug', 'adbpull-db', 'adbpull-csv']);229 // Just an alias task--shorthand for doing all the pushings230 grunt.registerTask(231 'adbpush',232 'Perform all the adbpush tasks',233 ['adbpush-collect', 'adbpush-tables-app']);234 grunt.registerTask(235 'adbpull-debug',236 'Pull the debug output objects from the device',237 function() {238 var src = tablesConfig.deviceMount + '/' + tablesConfig.appName +239 '/' + tablesConfig.outputDebugDir;240 var dest = tablesConfig.appDir + '/' + tablesConfig.outputDebugDir;241 grunt.log.writeln('adb pull ' + src + ' ' + dest);242 grunt.task.run('exec:adbpull:' + src + ':' + dest);243 });244 grunt.registerTask(245 'adbpull-db',246 'Pull the db from the device',247 function() {248 var dbPath = tablesConfig.deviceDbPath;249 dbPath = dbPath.replace(tablesConfig.appStr, tablesConfig.appName);250 var src = dbPath;251 var dest = tablesConfig.appDir + '/' + tablesConfig.outputDbDir;252 grunt.log.writeln('adb pull ' + src + ' ' + dest);253 grunt.task.run('exec:adbpull:' + src + ':' + dest);254 });255 grunt.registerTask(256 'adbpull-csv',257 'Pull any exported csv files from the device',258 function() {259 var src = tablesConfig.deviceMount + '/' + tablesConfig.appName +260 '/' + tablesConfig.outputCsvDir;261 var dest = tablesConfig.appDir + '/' + tablesConfig.outputCsvDir;262 grunt.log.writeln('adb pull ' + src + ' ' + dest);263 grunt.task.run('exec:adbpull:' + src + ':' + dest);264 });265 grunt.registerTask(266 'adbpush-tables-app',267 'Push everything in the app directory (except system) to the device',268 function() {269 // Do not push any system, data or output files.270 // The first parameter is an options object where we specify that271 // we only want files--this is important because otherwise when272 // we get directory names adb will push everything in the directory273 // name, effectively pushing everything twice. We also specify that we 274 // want everything returned to be relative to 'app' by using 'cwd'. 275 var dirs = grunt.file.expand(276 {filter: 'isFile',277 cwd: 'app' },278 '**',279 '!system/**',280 '!data/**',281 '!output/**');282 // Now push these files to the phone.283 dirs.forEach(function(fileName) {284 // Have to add app back into the file name for the adb push285 var src = tablesConfig.appDir + '/' + fileName;286 var dest =287 tablesConfig.deviceMount +288 '/' +289 tablesConfig.appName +290 '/' +291 fileName;292 grunt.log.writeln('adb push ' + src + ' ' + dest);293 grunt.task.run('exec:adbpush:' + src + ':' + dest);294 });295 });296 grunt.registerTask(297 'adbpush-tables',298 'Push everything for tables only to the device',299 function() {300 // We do not need any system, data or output files. 301 // The first parameter is an options object where we specify that302 // we only want files--this is important because otherwise when303 // we get directory names adb will push everything in the directory304 // name, effectively pushing everything twice. We also specify that we 305 // want everything returned to be relative to 'app' by using 'cwd'. 306 var dirs = grunt.file.expand(307 {filter: 'isFile',308 cwd: 'app' },309 '**',310 '!system/**',311 '!data/**',312 '!output/**');313 // Now push these files to the phone.314 dirs.forEach(function(fileName) {315 // Have to add app back into the file name for the adb push316 var src = tablesConfig.appDir + '/' + fileName;317 var dest =318 tablesConfig.deviceMount +319 '/' +320 tablesConfig.appName +321 '/' +322 fileName;323 grunt.log.writeln('adb push ' + src + ' ' + dest);324 grunt.task.run('exec:adbpush:' + src + ':' + dest);325 });326 // And then we want to put the collect forms in the right place.327 // This will push the collect forms for ALL the tables, but since328 // only the files used in the Tables demo follows the convention329 // required by the adbpush-collect task, that is ok.330 grunt.task.run('adbpush-collect');331 });332 grunt.registerTask(333 'adbpush-tables-demo-alpha2',334 'Push everything for tables demo to the device',335 function() {336 // In the alpha demo we want Tables and Survey. For the alpha2,337 // it had needed a push of the system files, but we won't do that338 // here. We only want a subset of the app/tables files,339 // however. So, we are going to get everything except that340 // directory and then add back in the ones that we want.341 // The first parameter is an options object where we specify that342 // we only want files--this is important because otherwise when343 // we get directory names adb will push everything in the directory344 // name, effectively pushing everything twice. We also specify that we 345 // want everything returned to be relative to 'app' by using 'cwd'. 346 var dirs = grunt.file.expand(347 {filter: 'isFile',348 cwd: 'app' },349 '**',350 '!system/**',351 '!data/**',352 '!output/**',353 '!config/tables/**',354 'config/tables/geotagger/**',355 'config/tables/Tea_houses/**',356 'config/tables/Tea_types/**',357 'config/tables/Tea_inventory/**',358 'config/tables/Tea_houses_editable/**',359 'config/tables/household/**',360 'config/tables/household_member/**');361 // Now push these files to the phone.362 dirs.forEach(function(fileName) {363 // Have to add app back into the file name for the adb push364 var src = tablesConfig.appDir + '/' + fileName;365 var dest =366 tablesConfig.deviceMount +367 '/' +368 tablesConfig.appName +369 '/' +370 fileName;371 grunt.log.writeln('adb push ' + src + ' ' + dest);372 grunt.task.run('exec:adbpush:' + src + ':' + dest);373 });374 // And then we want to put the collect forms in the right place.375 // This will push the collect forms for ALL the tables, but since376 // only the files used in the Tables demo follows the convention377 // required by the adbpush-collect task, that is ok.378 grunt.task.run('adbpush-collect');379 });380 grunt.registerTask(381 'adbpush-tables-demo-JGI',382 'Push everything for tables JGI demo to the device',383 function() {384 // In the alpha demo we want Tables and Survey. For this demo,385 // it had needed a push of the system files, but we won't do that386 // here. We only want a subset of the app/tables files,387 // however. So, we are going to get everything except that388 // directory and then add back in the ones that we want.389 // The first parameter is an options object where we specify that390 // we only want files--this is important because otherwise when391 // we get directory names adb will push everything in the directory392 // name, effectively pushing everything twice. We also specify that we 393 // want everything returned to be relative to 'app' by using 'cwd'. 394 var dirs = grunt.file.expand(395 {filter: 'isFile',396 cwd: 'app' },397 '**',398 '!system/**',399 '!data/**',400 '!output/**',401 '!config/tables/**',402 'config/tables/follow/**',403 'config/tables/follow_arrival/**',404 'config/tables/follow_map_position/**',405 'config/tables/follow_map_time/**',406 'config/tables/food_bout/**',407 'config/tables/groom_bout/**',408 'config/tables/mating_event/**',409 'config/tables/other_species/**');410 // Now push these files to the phone.411 dirs.forEach(function(fileName) {412 // Have to add app back into the file name for the adb push413 var src = tablesConfig.appDir + '/' + fileName;414 var dest =415 tablesConfig.deviceMount +416 '/' +417 tablesConfig.appName +418 '/' +419 fileName;420 grunt.log.writeln('adb push ' + src + ' ' + dest);421 grunt.task.run('exec:adbpush:' + src + ':' + dest);422 });423 });424 grunt.registerTask(425 'adbpush-survey',426 'Push everything for survey to the device',427 function() {428 // We do not need any system or output files. 429 // The first parameter is an options object where we specify that430 // we only want files--this is important because otherwise when431 // we get directory names adb will push everything in the directory432 // name, effectively pushing everything twice. We also specify that we 433 // want everything returned to be relative to 'app' by using 'cwd'. 434 var dirs = grunt.file.expand(435 {filter: 'isFile',436 cwd: 'app' },437 '**',438 '!system/**',439 '!data/**',440 '!output/**');441 // Now push these files to the phone.442 dirs.forEach(function(fileName) {443 // Have to add app back into the file name for the adb push444 var src = surveyConfig.appDir + '/' + fileName;445 var dest =446 surveyConfig.deviceMount +447 '/' +448 surveyConfig.appName +449 '/' +450 fileName;451 grunt.log.writeln('adb push ' + src + ' ' + dest);452 grunt.task.run('exec:adbpush:' + src + ':' + dest);453 });454 });455 grunt.registerTask(456 'adbpush-scan',457 'Push only scan demo',458 function() {459 // In the beta demo we only want Survey. It had needed the system460 // files, but we won't push them here. We only want a subset of the461 // app/config/tables files. So, we are going to get everything except462 // that directory and then add back in the ones that we want.463 // The first parameter is an options object where we specify that464 // we only want files--this is important because otherwise when465 // we get directory names adb will push everything in the directory466 // name, effectively pushing everything twice. We also specify that we 467 // want everything returned to be relative to 'app' by using 'cwd'. 468 var dirs = grunt.file.expand(469 {filter: 'isFile',470 cwd: 'app' },471 '**',472 'config/assets/**',473 '!system/**',474 '!data/**',475 '!output/**',476 '!config/tables/**',477 'config/tables/scan_childvacc_822_pg1/**',478 'config/tables/scan_childvacc_822a_pg2/**',479 'config/tables/scan_childvacc_825_pg3/**',480 'config/tables/scan_childvacc_825_pg4/**',481 'config/tables/scan_example/**',482 'config/tables/scan_HIV_Patient_Record/**',483 'config/tables/scan_HIV_Visit_Record/**');484 // Now push these files to the phone.485 dirs.forEach(function(fileName) {486 // Have to add app back into the file name for the adb push487 var src = tablesConfig.appDir + '/' + fileName;488 var dest =489 tablesConfig.deviceMount +490 '/' +491 tablesConfig.appName +492 '/' +493 fileName;494 grunt.log.writeln('adb push ' + src + ' ' + dest);495 grunt.task.run('exec:adbpush:' + src + ':' + dest);496 });497 // Change the tables.init to be applicable for scan498 var srcTablesInit = 'app/config/assets/tables.init.scan';499 var srcTablesIndex = 'app/config/assets/index_Scan.html';500 var dest =501 tablesConfig.deviceMount +502 '/' +503 tablesConfig.appName +504 '/assets/';505 grunt.log.writeln('adb push ' + srcTablesInit + ' ' + dest + 'tables.init');506 grunt.task.run('exec:adbpush:' + srcTablesInit + ':' + dest + 'tables.init');507 // Change the index.html to be applicable for scan508 grunt.log.writeln('adb push ' + srcTablesIndex + ' ' + dest + 'index.html');509 grunt.task.run('exec:adbpush:' + srcTablesIndex + ':' + dest + 'index.html');510 });511 grunt.registerTask(512 'adbpush-survey-demo-beta2',513 'Push everything for survey to the device',514 function() {515 // In the beta demo we only want Survey; do not push any516 // system or output files. We only want a subset of the 517 // app/config/tables files. So, we are going to get everything except518 // that directory and then add back in the ones that we want.519 // The first parameter is an options object where we specify that520 // we only want files--this is important because otherwise when521 // we get directory names adb will push everything in the directory522 // name, effectively pushing everything twice. We also specify that we 523 // want everything returned to be relative to 'app' by using 'cwd'. 524 var dirs = grunt.file.expand(525 {filter: 'isFile',526 cwd: 'app' },527 '**',528 '!system/**',529 '!data/**',530 '!output/**',531 '!config/tables/**',532 'config/tables/exampleForm/**',533 'config/tables/household/**',534 'config/tables/household_member/**',535 'config/tables/selects/**',536 'config/tables/gridScreen/**');537 // Now push these files to the phone.538 dirs.forEach(function(fileName) {539 // Have to add app back into the file name for the adb push540 var src = surveyConfig.appDir + '/' + fileName;541 var dest =542 surveyConfig.deviceMount +543 '/' +544 surveyConfig.appName +545 '/' +546 fileName;547 grunt.log.writeln('adb push ' + src + ' ' + dest);548 grunt.task.run('exec:adbpush:' + src + ':' + dest);549 });550 });551 grunt.registerTask(552 'adbpush-survey-demo-bmg05152014',553 'Push everything for survey demo to the device',554 function() {555 // In the demo we only want Survey. Do not push the system or 556 // output files. We only want a subset of the app/config/tables files,557 // however. So, we are going to get everything except that558 // directory and then add back in the ones that we want.559 // The first parameter is an options object where we specify that560 // we only want files--this is important because otherwise when561 // we get directory names adb will push everything in the directory562 // name, effectively pushing everything twice. We also specify that we 563 // want everything returned to be relative to 'app' by using 'cwd'. 564 var dirs = grunt.file.expand(565 {filter: 'isFile',566 cwd: 'app' },567 '**',568 '!system/**',569 '!data/**',570 '!output/**',571 '!config/tables/**',572 'config/tables/household/**',573 'config/tables/household_member/**',574 'config/tables/selects/**',575 'config/tables/gridScreen/**');576 // Now push these files to the phone.577 dirs.forEach(function(fileName) {578 // Have to add app back into the file name for the adb push579 var src = surveyConfig.appDir + '/' + fileName;580 var dest =581 surveyConfig.deviceMount +582 '/' +583 surveyConfig.appName +584 '/' +585 fileName;586 grunt.log.writeln('adb push ' + src + ' ' + dest);587 grunt.task.run('exec:adbpush:' + src + ':' + dest);588 });589 });590 grunt.registerTask(591 'adbpush-survey-demo-bmg10092014',592 'Push everything for survey demo to the device',593 function() {594 // In the demo we only want Survey. Do not push the system or 595 // output files. We only want a subset of the app/config/tables files,596 // however. So, we are going to get everything except that597 // directory and then add back in the ones that we want.598 // The first parameter is an options object where we specify that599 // we only want files--this is important because otherwise when600 // we get directory names adb will push everything in the directory601 // name, effectively pushing everything twice. We also specify that we 602 // want everything returned to be relative to 'app' by using 'cwd'. 603 //604 // For this demo selects had to be modified due to select_one_with_other605 // and the media player not working for video606 var dirs = grunt.file.expand(607 {filter: 'isFile',608 cwd: 'app' },609 '**',610 '!system/**',611 '!data/**',612 '!output/**',613 '!config/assets/**',614 'config/assets/csv/**',615 'config/assets/tables.init',616 '!config/tables/**',617 'config/tables/plot/**',618 'config/tables/visit/**',619 'config/tables/selects_demo/**',620 'config/tables/geotagger/**',621 'config/tables/agriculture/**');622 // Now push these files to the phone.623 dirs.forEach(function(fileName) {624 // Have to add app back into the file name for the adb push625 var src = tablesConfig.appDir + '/' + fileName;626 var dest =627 tablesConfig.deviceMount +628 '/' +629 tablesConfig.appName +630 '/' +631 fileName;632 grunt.log.writeln('adb push ' + src + ' ' + dest);633 grunt.task.run('exec:adbpush:' + src + ':' + dest);634 });635 });636 grunt.registerTask(637 'adbpush-survey-demo-techCon2014',638 'Push everything for survey demo to the device',639 function() {640 // In the demo we only want Survey. Do not push the system or 641 // output files. We only want a subset of the app/config/tables files,642 // however. So, we are going to get everything except that643 // directory and then add back in the ones that we want.644 // The first parameter is an options object where we specify that645 // we only want files--this is important because otherwise when646 // we get directory names adb will push everything in the directory647 // name, effectively pushing everything twice. We also specify that we 648 // want everything returned to be relative to 'app' by using 'cwd'. 649 //650 // For this demo selects had to be modified due to select_one_with_other651 // and the media player not working for video652 var dirs = grunt.file.expand(653 {filter: 'isFile',654 cwd: 'app' },655 '**',656 '!system/**',657 '!data/**',658 '!output/**',659 '!config/assets/**',660 'config/assets/csv/**',661 'config/assets/tables.init',662 '!config/tables/**',663 'config/tables/plot/**',664 'config/tables/visit/**',665 'config/tables/selects_demo/**',666 'config/tables/geotagger/**',667 'config/tables/agriculture/**',668 'config/tables/temperatureSensor/**');669 // Now push these files to the phone.670 dirs.forEach(function(fileName) {671 // Have to add app back into the file name for the adb push672 var src = tablesConfig.appDir + '/' + fileName;673 var dest =674 tablesConfig.deviceMount +675 '/' +676 tablesConfig.appName +677 '/' +678 fileName;679 grunt.log.writeln('adb push ' + src + ' ' + dest);680 grunt.task.run('exec:adbpush:' + src + ':' + dest);681 });682 });683 grunt.registerTask(684 'adbpush-survey-demo-beta3',685 'Push everything for survey to the device',686 function() {687 // In the beta demo we only want Survey. Do not push the system 688 // or output files. We only want a subset of the app/config/tables files,689 // however. So, we are going to get everything except that690 // directory and then add back in the ones that we want.691 // The first parameter is an options object where we specify that692 // we only want files--this is important because otherwise when693 // we get directory names adb will push everything in the directory694 // name, effectively pushing everything twice. We also specify that we 695 // want everything returned to be relative to 'app' by using 'cwd'. 696 var dirs = grunt.file.expand(697 {filter: 'isFile',698 cwd: 'app' },699 '**',700 '!system/**',701 '!data/**',702 '!output/**',703 '!config/assets/**',704 '!config/tables/**',705 'config/tables/exampleForm/**',706 'config/tables/household/**',707 'config/tables/household_member/**',708 'config/tables/selects/**',709 'config/tables/gridScreen/**');710 // Now push these files to the phone.711 dirs.forEach(function(fileName) {712 // Have to add app back into the file name for the adb push713 var src = surveyConfig.appDir + '/' + fileName;714 var dest =715 surveyConfig.deviceMount +716 '/' +717 surveyConfig.appName +718 '/' +719 fileName;720 grunt.log.writeln('adb push ' + src + ' ' + dest);721 grunt.task.run('exec:adbpush:' + src + ':' + dest);722 });723 });724 grunt.registerTask(725 'adbpush-survey-beta3-opendatakit-surveydemo',726 'Push everything for the opendatakit-surveydemo.appspot.com site to the device',727 function() {728 // These are the files that are uploaded to the opendatakit-surveydemo729 // appspot instance. We only want a subset of the app/tables files,730 // however. So, we are going to get everything except that731 // directory and then add back in the ones that we want.732 // The first parameter is an options object where we specify that733 // we only want files--this is important because otherwise when734 // we get directory names adb will push everything in the directory735 // name, effectively pushing everything twice. We also specify that we 736 // want everything returned to be relative to 'app' by using 'cwd'. 737 var dirs = grunt.file.expand(738 {filter: 'isFile',739 cwd: 'app' },740 '**',741 '!config/assets/**',742 '!system/**',743 '!data/**',744 '!output/**',745 '!config/tables/**',746 'config/tables/geoweather/**');747 // Now push these files to the phone.748 dirs.forEach(function(fileName) {749 // Have to add app back into the file name for the adb push750 var src = surveyConfig.appDir + '/' + fileName;751 var dest =752 surveyConfig.deviceMount +753 '/' +754 surveyConfig.appName +755 '/' +756 fileName;757 grunt.log.writeln('adb push ' + src + ' ' + dest);758 grunt.task.run('exec:adbpush:' + src + ':' + dest);759 });760 });761 grunt.registerTask(762 'adbpush-collect',763 'Push any collect form to the device',764 function() {765 // The full paths to all the table id directories.766 var tableIdDirs = grunt.file.expand(tablesConfig.tablesDir + '/*');767 // Now we want just the table ids.768 var tableIds = [];769 tableIdDirs.forEach(function(element) {770 tableIds.push(element.substr(element.lastIndexOf('/') + 1));771 });772 grunt.log.writeln(this.name + ', found tableIds: ' + tableIds);773 // Now that we have the table ids, we need to push any form in the774 // collect-forms directory. There should be only one, but we aren't775 // picky.776 tableIds.forEach(function(tableId) {777 var files = grunt.file.expand(778 tablesConfig.tablesDir + '/' + tableId +779 '/collect-forms/*');780 files.forEach(function(file) {781 var src = file;782 // We basically want to push all the contents under 783 // /sdcard/opendatakit/APP/tables/tableId/collect-forms784 // to /sdcard/odk/forms785 // I.e., this folder should contain things like:786 // .../formid.xml787 // .../formid-media/form_logo.jpg788 // .../formid-media/...789 // .../formid2.xml790 //791 // The names of the files will stay the same 792 // when we push them793 var dest = tablesConfig.formMount;794 grunt.log.writeln(795 'adb push ' + src + ' ' + dest);796 grunt.task.run('exec:adbpush: ' + src + ':' + dest);797 });798 });799 });800 // This task adds a table. This includes making a folder in the app/tables801 // directory and instantiating the directory structure that is expected.802 // It also creates templates for the js and html files based on the given803 // tableId.804 grunt.registerTask(805 'addtable',806 'Adds a table directory structure',807 function(tableId) {808 if (arguments.length !== 1) {809 grunt.fail.fatal(this.name +810 ' requires one tableId. Call using "' +811 this.name + ':tableId"');812 } else {813 /**814 * Reads the file in srcPath, replaces all instances of815 * tablesConfig.tableIdStr with tableId, and writes it to816 * destPath.817 */818 var replaceIdAndWrite = function(srcPath, destPath, tableId) {819 var contents = grunt.file.read(srcPath);820 // Now modify it.821 // We need to do a global replace.822 var regex = new RegExp(tablesConfig.tableIdStr, 'g');823 contents =824 contents.replace(regex, tableId);825 grunt.file.write(destPath, contents);826 };827 grunt.log.writeln(828 this.name + ' making table with id ' + tableId);829 var tableDir = tablesConfig.tablesDir + '/' + tableId;830 // First we need to make the directory in the tables dir.831 grunt.file.mkdir(tableDir);832 // Now we copy the files from the grunttemplates directory into833 // the new directory. We're going to do the files that depend834 // on the tableId independntly, doing a string replace on our835 // flag for the marker.836 // These will be the files in the tableTemplateDir we want to837 // copy directly. You must terminate with / if it is a dir.838 var toCopy = [839 'forms/',840 'collect-forms/',841 'instances/'842 ];843 grunt.log.writeln(this.name + ', copying files: ' + toCopy);844 toCopy.forEach(function(path) {845 var srcPath = tablesConfig.tableTemplateDir + '/' + path;846 var destPath = tableDir + '/' + path;847 // We have to do a special case on if it's a directory.848 if (grunt.util._.endsWith(srcPath, '/')) {849 grunt.file.mkdir(destPath);850 } else {851 grunt.file.copy(srcPath, destPath);852 }853 });854 // Now we will copy the files to which we need to add the 855 // table id.856 var detailHtml = {857 srcPath: tablesConfig.tableTemplateDir +858 '/html/detail.html',859 destPath: tableDir + '/html/' + tableId + '_detail.html'860 };861 var detailJs = {862 srcPath: tablesConfig.tableTemplateDir + '/js/detail.js',863 destPath: tableDir + '/js/' + tableId + '_detail.js'864 };865 var listHtml = {866 srcPath: tablesConfig.tableTemplateDir + '/html/list.html',867 destPath: tableDir + '/html/' + tableId + '_list.html'868 };869 var listJs = {870 srcPath: tablesConfig.tableTemplateDir + '/js/list.js',871 destPath: tableDir + '/js/' + tableId + '_list.js'872 };873 var filesToReplace = [874 detailHtml,875 detailJs,876 listHtml,877 listJs878 ];879 grunt.log.writeln(this.name + ', writing dynamic table files');880 filesToReplace.forEach(function(element) {881 replaceIdAndWrite(882 element.srcPath,883 element.destPath,884 tableId);885 });886 }887 });888 grunt.registerTask('server', function (target) {889 if (target === 'test') {890 return grunt.task.run([891 'connect:test',892 'watch:livereload'893 ]);894 }895 grunt.task.run([896 'connect:livereload',897 'open',898 'watch'899 ]);900 });901 grunt.registerTask('default', [902 'server'903 ]);904 905 grunt.registerTask(906 'adbpush-system',907 'Push the system directory to the survey appName on the device',908 function() {909 // Useful for testing working system code before constructing910 // the framework zip file and adding it to the APK res/raw911 // folder. 912 // The first parameter is an options object where we specify that913 // we only want files--this is important because otherwise when914 // we get directory names adb will push everything in the directory915 // name, effectively pushing everything twice. We also specify that we 916 // want everything returned to be relative to 'app' by using 'cwd'. 917 var dirs = grunt.file.expand(918 {filter: 'isFile',919 cwd: 'app' },920 'system/**');921 // Now push these files to the phone.922 dirs.forEach(function(fileName) {923 // Have to add app back into the file name for the adb push924 var src = surveyConfig.appDir + '/' + fileName;925 var dest =926 surveyConfig.deviceMount +927 '/' +928 surveyConfig.appName +929 '/' +930 fileName;931 grunt.log.writeln('adb push ' + src + ' ' + dest);932 grunt.task.run('exec:adbpush:' + src + ':' + dest);933 });934 });...
push_to_device_test.js
Source:push_to_device_test.js
1'use strict';2var assert = require('chai').assert;3var proxyquire = require('proxyquire');4var mockUtils = require('./mock_utils.js');5suite('push-to-device.js', function() {6 var app;7 setup(function() {8 app = proxyquire.noCallThru().load(9 '../../push-to-device', {10 './utils': mockUtils11 });12 mockUtils.getFileContent = function(file) {13 return file;14 };15 });16 suite('pushToDevice, getPid and installSvoperapps', function() {17 var profileFolder = 'testProfileFolder';18 var remotePath = 'testRemotePath';19 test('pushToDevice without indexedDbFile', function(done) {20 mockUtils.getFile = function() {21 var args = Array.prototype.slice.call(arguments);22 var path = args.join('/');23 var indexDbFileExists = (path === profileFolder + '/indexedDB');24 return {25 exists: function() {26 return !indexDbFileExists;27 },28 isDirectory: function() {29 return !indexDbFileExists;30 },31 path: profileFolder + '/indexedDB'32 };33 };34 var queue = app.pushToDevice(profileFolder, remotePath, 'adb');35 queue.done(function() {36 assert.deepEqual(37 mockUtils.hasRunCommands,38 { sh: [39 '-c adb shell rm -r /' + remotePath + '/webapps',40 '-c adb shell rm //data/local/user.js',41 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +42 '/webapps',43 '-c adb push "' + profileFolder +44 '/user.js" //data/local/user.js']45 }46 );47 done();48 });49 });50 test('pushToDevice with indexedDbFile', function(done) {51 mockUtils.getFile = function() {52 var args = Array.prototype.slice.call(arguments);53 var path = args.join('/');54 var indexDbFileExists = (path === profileFolder + '/indexedDB');55 return {56 exists: function() {57 return indexDbFileExists;58 },59 isDirectory: function() {60 return indexDbFileExists;61 },62 path: profileFolder + '/indexedDB'63 };64 };65 var queue = app.pushToDevice(profileFolder, remotePath, 'adb');66 queue.done(function() {67 assert.deepEqual(68 mockUtils.hasRunCommands,69 { sh: [70 '-c adb shell rm -r /' + remotePath + '/webapps',71 '-c adb shell rm //data/local/user.js',72 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +73 '/webapps',74 '-c adb push "' + profileFolder +75 '/user.js" //data/local/user.js',76 '-c adb push "' + profileFolder +77 '/indexedDB" //data/local/indexedDB']78 }79 );80 done();81 });82 });83 test('installSvoperapps', function(done) {84 var queue = app.installSvoperapps(profileFolder, 'adb');85 queue.done(function() {86 assert.deepEqual(mockUtils.hasRunCommands, {87 sh: [88 '-c adb shell rm -r //data/local/svoperapps',89 '-c adb push "' + profileFolder +90 '/svoperapps" //data/local/svoperapps'91 ]92 });93 done();94 });95 });96 });97 suite('execute', function() {98 var options;99 var appID;100 setup(function() {101 options = {102 ADB: 'adb',103 GAIA_DIR: 'testGaia',104 PROFILE_DIR: 'testProfileFolder',105 GAIA_INSTALL_PARENT: '/system/b2g',106 GAIA_DOMAIN: 'testDomain'107 };108 appID = '999';109 mockUtils.getFile = function() {110 var args = Array.prototype.slice.call(arguments);111 var path = args.join('/');112 var profileExists = (path === options.PROFILE_DIR);113 return {114 exists: function() {115 return profileExists;116 },117 isDirectory: function() {118 return profileExists;119 },120 path: options.PROFILE_DIR121 };122 };123 mockUtils.readZipManifest = function() {124 return {125 name: options.BUILD_APP_NAME126 };127 };128 });129 test('execute, test it without assigning app name', function(done) {130 options.BUILD_APP_NAME = '*';131 var queue = app.execute(options);132 queue.done(function() {133 assert.deepEqual(mockUtils.hasRunCommands, {134 sh: [135 '-c adb start-server',136 '-c adb wait-for-device',137 '-c adb shell stop b2g',138 '-c adb shell rm -r //cache/*',139 '-c adb remount',140 '-c adb shell rm -r /' + options.GAIA_INSTALL_PARENT +141 '/webapps',142 '-c adb shell rm //data/local/user.js',143 '-c adb push "' + options.PROFILE_DIR + '/webapps"' +144 ' //system/b2g/webapps',145 '-c adb push "' + options.PROFILE_DIR + '/user.js"' +146 ' //data/local/user.js',147 '-c adb push "shared/elements/gaia-icons/fonts/gaia-icons.ttf"' +148 ' //system/fonts/hidden/gaia-icons.ttf',149 '-c adb push "shared/style/keyboard_symbols/Keyboard-Symbols.ttf"' +150 ' //system/fonts/hidden/Keyboard-Symbols.ttf',151 '-c adb shell start b2g']});152 done();153 });154 });155 test('execute, test it with testApp as an app name', function(done) {156 options.BUILD_APP_NAME = 'testApp';157 mockUtils.psParser = function() {158 var pidMap = {};159 pidMap[options.BUILD_APP_NAME] = {160 PID: appID161 };162 return pidMap;163 };164 var queue = app.execute(options);165 queue.done(function() {166 assert.deepEqual(mockUtils.hasRunCommands, {167 sh: [168 '-c adb start-server',169 '-c adb wait-for-device',170 '-c adb shell rm -r //cache/*',171 '-c adb remount',172 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +173 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +174 '/manifest.webapp" /' + options.GAIA_INSTALL_PARENT +175 '/webapps/' + options.BUILD_APP_NAME + '.' +176 options.GAIA_DOMAIN + '/manifest.webapp',177 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +178 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +179 '/application.zip" /' + options.GAIA_INSTALL_PARENT +180 '/webapps/' + options.BUILD_APP_NAME + '.' +181 options.GAIA_DOMAIN + '/application.zip',182 '-c adb shell kill testApp']});183 done();184 });185 });186 });187 suite('getRemoteInstallPath', function() {188 test('Return /system/b2g if no profile on device', function() {189 var realGetJSON = mockUtils.getJSON;190 mockUtils.getJSON = function(file) {191 // getJSON should throw in this case because the content of the192 // tempFile will be an adb error message.193 return JSON.parse(194 'remote object \'' + file.path + '\' does not exist');195 };196 var path = app.getRemoteInstallPath('adb');197 assert.equal(path, '/system/b2g');198 mockUtils.getJSON = realGetJSON;199 });200 test('Return /data/local if no app was installed on /system/b2g',201 function() {202 var realGetJSON = mockUtils.getJSON;203 mockUtils.getJSON = function(file) {204 return {205 'app1.gaiamobile.org': {206 'basePath': '/data/local/webapps'207 },208 'app2.gaiamobile.org': {209 'basePath': '/data/local/webapps'210 },211 'app3.gaiamobile.org': {212 'basePath': '/data/local/webapps'213 }214 };215 };216 var path = app.getRemoteInstallPath('adb');217 assert.equal(path, '/data/local');218 mockUtils.getJSON = realGetJSON;219 });220 test('Return /system/b2g if any app was installed there', function() {221 var realGetJSON = mockUtils.getJSON;222 mockUtils.getJSON = function(file) {223 return {224 'app1.gaiamobile.org': {225 'basePath': '/data/local/webapps'226 },227 'app2.gaiamobile.org': {228 'basePath': '/system/b2g/webapps'229 },230 'app3.gaiamobile.org': {231 'basePath': '/system/b2g/webapps'232 }233 };234 };235 var path = app.getRemoteInstallPath('adb');236 assert.equal(path, '/system/b2g');237 mockUtils.getJSON = realGetJSON;238 });239 });...
push-to-device.test.js
Source:push-to-device.test.js
1'use strict';2var assert = require('chai').assert;3var proxyquire = require('proxyquire');4var mockUtils =5 require('./mock_utils.js');6suite('push-to-device.js', function() {7 var app;8 setup(function() {9 app = proxyquire.noCallThru().load(10 '../../push-to-device', {11 './utils': mockUtils12 });13 mockUtils.getFileContent = function(file) {14 return file;15 };16 });17 suite('pushToDevice, getPid and installSvoperapps', function() {18 var profileFolder = 'testProfileFolder';19 var remotePath = 'testRemotePath';20 test('pushToDevice without indexedDbFile', function(done) {21 mockUtils.getFile = function() {22 var args = Array.prototype.slice.call(arguments);23 var path = args.join('/');24 var indexDbFileExists = (path === profileFolder + '/indexedDB');25 return {26 exists: function() {27 return !indexDbFileExists;28 },29 isDirectory: function() {30 return !indexDbFileExists;31 },32 path: profileFolder + '/indexedDB'33 };34 };35 var queue = app.pushToDevice(profileFolder, remotePath, 'adb');36 queue.done(function() {37 assert.deepEqual(38 mockUtils.hasRunCommands,39 { sh: [40 '-c adb shell rm -r /' + remotePath + '/webapps',41 '-c adb shell rm //data/local/user.js',42 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +43 '/webapps',44 '-c adb push "' + profileFolder +45 '/user.js" //data/local/user.js']46 }47 );48 done();49 });50 });51 test('pushToDevice with indexedDbFile', function(done) {52 mockUtils.getFile = function() {53 var args = Array.prototype.slice.call(arguments);54 var path = args.join('/');55 var indexDbFileExists = (path === profileFolder + '/indexedDB');56 return {57 exists: function() {58 return indexDbFileExists;59 },60 isDirectory: function() {61 return indexDbFileExists;62 },63 path: profileFolder + '/indexedDB'64 };65 };66 var queue = app.pushToDevice(profileFolder, remotePath, 'adb');67 queue.done(function() {68 assert.deepEqual(69 mockUtils.hasRunCommands,70 { sh: [71 '-c adb shell rm -r /' + remotePath + '/webapps',72 '-c adb shell rm //data/local/user.js',73 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +74 '/webapps',75 '-c adb push "' + profileFolder +76 '/user.js" //data/local/user.js',77 '-c adb push "' + profileFolder +78 '/indexedDB" //data/local/indexedDB']79 }80 );81 done();82 });83 });84 test('installSvoperapps', function(done) {85 var queue = app.installSvoperapps(profileFolder, 'adb');86 queue.done(function() {87 assert.deepEqual(mockUtils.hasRunCommands, {88 sh: [89 '-c adb shell rm -r //data/local/svoperapps',90 '-c adb push "' + profileFolder +91 '/svoperapps" //data/local/svoperapps'92 ]93 });94 done();95 });96 });97 });98 suite('execute', function() {99 var options;100 var appID;101 setup(function() {102 options = {103 ADB: 'adb',104 GAIA_DIR: 'testGaia',105 PROFILE_DIR: 'testProfileFolder',106 GAIA_INSTALL_PARENT: '/system/b2g',107 GAIA_DOMAIN: 'testDomain'108 };109 appID = '999';110 mockUtils.getFile = function() {111 var args = Array.prototype.slice.call(arguments);112 var path = args.join('/');113 var profileExists = (path === options.PROFILE_DIR);114 return {115 exists: function() {116 return profileExists;117 },118 isDirectory: function() {119 return profileExists;120 },121 path: options.PROFILE_DIR122 };123 };124 mockUtils.readZipManifest = function() {125 return {126 name: options.BUILD_APP_NAME127 };128 };129 });130 test('execute, test it without assigning app name', function(done) {131 options.BUILD_APP_NAME = '*';132 var queue = app.execute(options);133 queue.done(function() {134 assert.deepEqual(mockUtils.hasRunCommands, {135 sh: [136 '-c adb start-server',137 '-c adb wait-for-device',138 '-c adb shell stop b2g',139 '-c adb shell rm -r //cache/*',140 '-c adb remount',141 '-c adb shell rm -r /' + options.GAIA_INSTALL_PARENT +142 '/webapps',143 '-c adb shell rm //data/local/user.js',144 '-c adb push "' + options.PROFILE_DIR + '/webapps"' +145 ' //system/b2g/webapps',146 '-c adb push "' + options.PROFILE_DIR + '/user.js"' +147 ' //data/local/user.js',148 '-c adb shell start b2g']});149 done();150 });151 });152 test('execute, test it with testApp as an app name', function(done) {153 options.BUILD_APP_NAME = 'testApp';154 mockUtils.psParser = function() {155 var pidMap = {};156 pidMap[options.BUILD_APP_NAME] = {157 PID: appID158 };159 return pidMap;160 };161 mockUtils.getPid = function(appName, gaiaDir) {162 return appID;163 };164 var queue = app.execute(options);165 queue.done(function() {166 assert.deepEqual(mockUtils.hasRunCommands, {167 sh: [168 '-c adb start-server',169 '-c adb wait-for-device',170 '-c adb shell rm -r //cache/*',171 '-c adb remount',172 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +173 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +174 '/manifest.webapp" /' + options.GAIA_INSTALL_PARENT +175 '/webapps/' + options.BUILD_APP_NAME + '.' +176 options.GAIA_DOMAIN + '/manifest.webapp',177 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +178 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +179 '/application.zip" /' + options.GAIA_INSTALL_PARENT +180 '/webapps/' + options.BUILD_APP_NAME + '.' +181 options.GAIA_DOMAIN + '/application.zip',182 '-c adb shell kill ' + appID]});183 done();184 });185 });186 });187 suite('getRemoteInstallPath', function() {188 test('Return /system/b2g if no profile on device', function() {189 var realGetJSON = mockUtils.getJSON;190 mockUtils.getJSON = function(file) {191 // getJSON should throw in this case because the content of the192 // tempFile will be an adb error message.193 return JSON.parse(194 'remote object \'' + file.path + '\' does not exist');195 };196 var path = app.getRemoteInstallPath('adb');197 assert.equal(path, '/system/b2g');198 mockUtils.getJSON = realGetJSON;199 });200 test('Return /data/local if no app was installed on /system/b2g',201 function() {202 var realGetJSON = mockUtils.getJSON;203 mockUtils.getJSON = function(file) {204 return {205 'app1.gaiamobile.org': {206 'basePath': '/data/local/webapps'207 },208 'app2.gaiamobile.org': {209 'basePath': '/data/local/webapps'210 },211 'app3.gaiamobile.org': {212 'basePath': '/data/local/webapps'213 }214 };215 };216 var path = app.getRemoteInstallPath('adb');217 assert.equal(path, '/data/local');218 mockUtils.getJSON = realGetJSON;219 });220 test('Return /system/b2g if any app was installed there', function() {221 var realGetJSON = mockUtils.getJSON;222 mockUtils.getJSON = function(file) {223 return {224 'app1.gaiamobile.org': {225 'basePath': '/data/local/webapps'226 },227 'app2.gaiamobile.org': {228 'basePath': '/system/b2g/webapps'229 },230 'app3.gaiamobile.org': {231 'basePath': '/system/b2g/webapps'232 }233 };234 };235 var path = app.getRemoteInstallPath('adb');236 assert.equal(path, '/system/b2g');237 mockUtils.getJSON = realGetJSON;238 });239 });...
push-to-device.js
Source:push-to-device.js
1'use strict';2/* jshint node: true */3var utils = require('./utils');4var sh = new utils.Commander('sh');5var Q = utils.Q;6sh.initPath(utils.getEnvPath());7/**8 * detect if b2g process needs to be restarted9 * @param {string} appName app name10 * @return {bool} true if needed11 */12function needsB2gRestart(appName) {13 // b2g should be restarted if these app name is assigned by APP=appname14 var appList = ['system', 'callscreen'];15 return (appList.indexOf(appName) !== -1);16}17function pushToDevice(profileFolder, remotePath, adb) {18 // MingGW on Windows takes '/remote/src' as 'c:\remote\src' which is19 // not right, so we use two slash before the remote path to prevent it.20 var webapps_path = '/' + remotePath + '/webapps';21 var indexedDbFile;22 var queue = Q.defer();23 queue.resolve();24 return queue.promise.then(function() {25 return sh.run(['-c', adb + ' shell rm -r ' + webapps_path]);26 }).then(function() {27 return sh.run(['-c', adb + ' shell rm //data/local/user.js']);28 }).then(function() {29 // adb push /gaia/profile/webapps /system/b2g/webapps30 return sh.run(['-c', adb + ' push "' + utils.joinPath(profileFolder,31 'webapps') + '" ' + webapps_path]);32 }).then(function() {33 // adb push /gaia/profile/user.js /data/local/user.js34 return sh.run(['-c', adb + ' push "' + utils.joinPath(profileFolder,35 'user.js') + '" //data/local/user.js']);36 }).then(function() {37 indexedDbFile = utils.getFile(profileFolder, 'indexedDB');38 }).then(function() {39 if (indexedDbFile.exists() && indexedDbFile.isDirectory()) {40 // adb push /gaia/profile/indexedDB /data/local/indexedDB41 return sh.run(['-c', adb + ' push "' + indexedDbFile.path +42 '" //data/local/indexedDB']);43 }44 });45}46function installSvoperapps(profileFolder, adb) {47 var svoperappsUrl = '//data/local/svoperapps';48 var queue = Q.defer();49 queue.resolve();50 return queue.promise.then(function() {51 return sh.run(['-c', adb + ' shell rm -r ' + svoperappsUrl]);52 }).then(function() {53 return sh.run(['-c', adb + ' push "' + utils.joinPath(profileFolder,54 'svoperapps') + '" ' + svoperappsUrl]);55 });56}57function installOneApp(targetFolder, buildAppName,58 remotePath, gaiaDomain,59 adb) {60 var queue = Q.defer();61 queue.resolve();62 return queue.promise.then(function() {63 // "adb push /gaia/profile/webapps/SOME_APP.gaiamobile.org/manifest.webapp64 // /system/b2g/webapps/SOME_APP.gaiamobile.org/manifest.webapp"65 return sh.run(['-c',66 adb + ' push "' + utils.joinPath(targetFolder, 'manifest.webapp') +67 '" /' + remotePath + '/webapps/' + buildAppName + '.' +68 gaiaDomain + '/manifest.webapp']);69 }).then(function() {70 // adb push /gaia/profile/webapps/SOME_APP.gaiamobile.org/application.zip71 // /system/b2g/webapps/SOME_APP.gaiamobile.org/application.zip"72 return sh.run(['-c',73 adb + ' push "' + utils.joinPath(targetFolder, 'application.zip') +74 '" /' + remotePath + '/webapps/' + buildAppName + '.' +75 gaiaDomain + '/application.zip']);76 });77}78function getRemoteInstallPath(adb) {79 var tempDirName = 'pushGaia' + Math.random().toString(36).substr(2, 8);80 var tempDir = utils.getTempFolder(tempDirName);81 var tempFile = tempDir.clone();82 tempFile.append('webapps.json');83 // Use |adb shell cat| instead of |adb pull| so we don't run into84 // error and exit when the file does not exist.85 sh.run(['-c', adb + ' shell cat /data/local/webapps/webapps.json > ' +86 tempFile.path]);87 // Read the file as JSON88 // If there were no webapps ever installed on the device (likely purged in89 // the previous step), default to /system/b2g90 var content;91 try {92 content = utils.getJSON(tempFile);93 } catch (e) {94 return '/system/b2g';95 }96 // Remove the entire temp directory97 tempDir.remove(true);98 // If any of the preload Gaia app was installed at /system/b2g,99 // we should overwrite them in /system/b2g100 for (var app in content) {101 if (content[app].basePath === '/system/b2g/webapps') {102 return '/system/b2g';103 }104 }105 return '/data/local';106}107function execute(options) {108 const buildAppName = options.BUILD_APP_NAME;109 const gaiaDir = options.GAIA_DIR;110 const profileFolder = options.PROFILE_DIR;111 const gaiaDomain = options.GAIA_DOMAIN;112 var remotePath = options.GAIA_INSTALL_PARENT;113 var mainQ = Q.defer();114 var targetFolder;115 var adb = options.ADB;116 var restartB2g = needsB2gRestart(buildAppName);117 if (restartB2g) {118 utils.log('push-to-device', 'b2g process will be restarted for ' +119 'installing ' + buildAppName + ' app, see bug 1000049 for ' +120 'more information.');121 }122 mainQ.resolve();123 return mainQ.promise.then(function() {124 var profile = utils.getFile(profileFolder);125 if (!profile.isDirectory()) {126 throw new Error(' -*- build/push-to-device.js: cannot locate' +127 'profile folder in ' + options.PROFILE_DIR);128 }129 }).then(function() {130 return sh.run(['-c', adb + ' start-server']);131 }).then(function() {132 utils.log('push', 'Waiting for device ...');133 return sh.run(['-c', adb + ' wait-for-device']);134 }).then(function() {135 if (buildAppName === '*' || restartB2g) {136 return sh.run(['-c', adb + ' shell stop b2g']);137 }138 }).then(function() {139 return sh.run(['-c', adb + ' shell rm -r //cache/*']);140 }).then(function() {141 if (!remotePath) {142 utils.log('push', 'GAIA_INSTALL_PARENT unset; ' +143 'probing previous installation location...');144 remotePath = getRemoteInstallPath(adb);145 }146 utils.log('push', 'Install webapp(s) to ' + remotePath + '...');147 if (/^\/system\//.test(remotePath)) {148 return sh.run(['-c', adb + ' remount']);149 }150 }).then(function() {151 if (buildAppName === '*') {152 return pushToDevice(profileFolder, remotePath, adb);153 } else {154 targetFolder = utils.joinPath(155 profileFolder, 'webapps',156 buildAppName + '.' + gaiaDomain);157 return installOneApp(targetFolder, buildAppName,158 remotePath, gaiaDomain, adb);159 }160 }).then(function() {161 if (options.VARIANT_PATH) {162 return installSvoperapps(profileFolder, adb);163 }164 }).then(function() {165 if (buildAppName === '*') {166 return sh.run(['-c', adb + ' push ' +167 '"shared/elements/gaia-icons/fonts/gaia-icons.ttf" ' +168 '//system/fonts/hidden/gaia-icons.ttf']);169 }170 }).then(function() {171 if (buildAppName === '*') {172 return sh.run(['-c', adb + ' push ' +173 '"shared/style/keyboard_symbols/Keyboard-Symbols.ttf" ' +174 '//system/fonts/hidden/Keyboard-Symbols.ttf']);175 }176 }).then(function() {177 if (buildAppName === '*' || restartB2g) {178 utils.log('push', 'Restarting B2G...');179 sh.run(['-c', adb + ' shell start b2g']);180 } else {181 var Q3 = Q.defer();182 var manifest;183 Q3.resolve();184 return Q3.promise.then(function() {185 // Some app folder name is different with the process name,186 // ex. sms -> Messages187 manifest = utils.readZipManifest(utils.getFile(188 targetFolder));189 }).then(function() {190 utils.log('push', 'Restarting ' + manifest.name + '...');191 utils.killAppByPid(manifest.name, gaiaDir);192 });193 }194 });195}196exports.execute = execute;197exports.installSvoperapps = installSvoperapps;198exports.getRemoteInstallPath = getRemoteInstallPath;...
install-gaia.test.js
Source:install-gaia.test.js
1'use strict';2var assert = require('chai').assert;3var proxyquire = require('proxyquire');4var mockUtils =5 require('./mock_utils.js');6suite('install-gaia.js', function() {7 var app;8 setup(function() {9 app = proxyquire.noCallThru().load(10 '../../install-gaia', {11 './utils': mockUtils12 });13 mockUtils.getFileContent = function(file) {14 return file;15 };16 });17 suite('installGaia, getPid and installSvoperapps', function() {18 var profileFolder = 'testProfileFolder';19 var remotePath = 'testRemotePath';20 test('installGaia without indexedDbFile', function(done) {21 mockUtils.getFile = function() {22 var args = Array.prototype.slice.call(arguments);23 var path = args.join('/');24 var indexDbFileExists = (path === profileFolder + '/indexedDB');25 return {26 exists: function() {27 return !indexDbFileExists;28 },29 isDirectory: function() {30 return !indexDbFileExists;31 },32 path: profileFolder + '/indexedDB'33 };34 };35 var queue = app.installGaia(profileFolder, remotePath);36 queue.done(function() {37 assert.deepEqual(38 mockUtils.hasRunCommands,39 { sh: [40 '-c adb shell rm -r /' + remotePath + '/webapps',41 '-c adb shell rm //data/local/user.js',42 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +43 '/webapps',44 '-c adb push "' + profileFolder +45 '/user.js" //data/local/user.js']46 }47 );48 done();49 });50 });51 test('installGaia with indexedDbFile', function(done) {52 mockUtils.getFile = function() {53 var args = Array.prototype.slice.call(arguments);54 var path = args.join('/');55 var indexDbFileExists = (path === profileFolder + '/indexedDB');56 return {57 exists: function() {58 return indexDbFileExists;59 },60 isDirectory: function() {61 return indexDbFileExists;62 },63 path: profileFolder + '/indexedDB'64 };65 };66 var queue = app.installGaia(profileFolder, remotePath);67 queue.done(function() {68 assert.deepEqual(69 mockUtils.hasRunCommands,70 { sh: [71 '-c adb shell rm -r /' + remotePath + '/webapps',72 '-c adb shell rm //data/local/user.js',73 '-c adb push "' + profileFolder + '/webapps" /' + remotePath +74 '/webapps',75 '-c adb push "' + profileFolder +76 '/user.js" //data/local/user.js',77 '-c adb push "' + profileFolder +78 '/indexedDB" //data/local/indexedDB']79 }80 );81 done();82 });83 });84 test('installSvoperapps', function(done) {85 var queue = app.installSvoperapps(profileFolder);86 queue.done(function() {87 assert.deepEqual(mockUtils.hasRunCommands, {88 sh: [89 '-c adb shell rm -r //data/local/svoperapps',90 '-c adb push "' + profileFolder +91 '/svoperapps" //data/local/svoperapps'92 ]93 });94 done();95 });96 });97 });98 suite('execute', function() {99 var options;100 var appID;101 setup(function() {102 options = {103 GAIA_DIR: 'testGaia',104 PROFILE_DIR: 'testProfileFolder',105 GAIA_INSTALL_PARENT: '/system/b2g',106 GAIA_DOMAIN: 'testDomain'107 };108 appID = '999';109 mockUtils.getFile = function() {110 var args = Array.prototype.slice.call(arguments);111 var path = args.join('/');112 var profileExists = (path === options.PROFILE_DIR);113 return {114 exists: function() {115 return profileExists;116 },117 isDirectory: function() {118 return profileExists;119 },120 path: options.PROFILE_DIR121 };122 };123 mockUtils.readZipManifest = function() {124 return {125 name: options.BUILD_APP_NAME126 };127 };128 });129 test('execute, test it without assigning app name', function(done) {130 options.BUILD_APP_NAME = '*';131 var queue = app.execute(options);132 queue.done(function() {133 assert.deepEqual(mockUtils.hasRunCommands, {134 sh: [135 '-c adb start-server',136 '-c adb shell stop b2g',137 '-c adb shell rm -r //cache/*',138 '-c adb shell rm -r /' + options.GAIA_INSTALL_PARENT +139 '/webapps',140 '-c adb shell rm //data/local/user.js',141 '-c adb push "' + options.PROFILE_DIR + '/webapps"' +142 ' //system/b2g/webapps',143 '-c adb push "' + options.PROFILE_DIR + '/user.js"' +144 ' //data/local/user.js',145 '-c adb shell start b2g']});146 done();147 });148 });149 test('execute, test it with testApp as an app name', function(done) {150 options.BUILD_APP_NAME = 'testApp';151 mockUtils.psParser = function() {152 var pidMap = {};153 pidMap[options.BUILD_APP_NAME] = {154 PID: appID155 };156 return pidMap;157 };158 var queue = app.execute(options);159 queue.done(function() {160 assert.deepEqual(mockUtils.hasRunCommands, {161 sh: [162 '-c adb start-server',163 '-c adb shell rm -r //cache/*',164 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +165 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +166 '/manifest.webapp" /' + options.GAIA_INSTALL_PARENT +167 '/webapps/' + options.BUILD_APP_NAME + '.' +168 options.GAIA_DOMAIN + '/manifest.webapp',169 '-c adb push "' + options.PROFILE_DIR + '/webapps/' +170 options.BUILD_APP_NAME + '.' + options.GAIA_DOMAIN +171 '/application.zip" /' + options.GAIA_INSTALL_PARENT +172 '/webapps/' + options.BUILD_APP_NAME + '.' +173 options.GAIA_DOMAIN + '/application.zip',174 '-c adb shell kill testApp']});175 done();176 });177 });178 });...
install-gaia.js
Source:install-gaia.js
1'use strict';2var utils = require('./utils');3var sh = new utils.Commander('sh');4var Q = utils.Q;5sh.initPath(utils.getEnvPath());6function installGaia(profileFolder, remotePath) {7 // MingGW on Windows takes '/remote/src' as 'c:\remote\src' which is8 // not right, so we use two slash before the remote path to prevent it.9 var webapps_path = '/' + remotePath + '/webapps';10 var indexedDbFile;11 var queue = Q.defer();12 queue.resolve();13 return queue.promise.then(function() {14 return sh.run(['-c', 'adb shell rm -r ' + webapps_path]);15 }).then(function() {16 return sh.run(['-c', 'adb shell rm //data/local/user.js']);17 }).then(function() {18 // adb push /gaia/profile/webapps /system/b2g/webapps19 return sh.run(['-c', 'adb push "' + utils.joinPath(profileFolder,20 'webapps') + '" ' + webapps_path]);21 }).then(function() {22 // adb push /gaia/profile/user.js /data/local/user.js23 return sh.run(['-c', 'adb push "' + utils.joinPath(profileFolder,24 'user.js') + '" //data/local/user.js']);25 }).then(function() {26 indexedDbFile = utils.getFile(profileFolder, 'indexedDB');27 }).then(function() {28 if (indexedDbFile.exists() && indexedDbFile.isDirectory()) {29 // adb push /gaia/profile/indexedDB /data/local/indexedDB30 return sh.run(['-c', 'adb push "' + indexedDbFile.path +31 '" //data/local/indexedDB']);32 }33 });34}35function installSvoperapps(profileFolder) {36 var svoperappsUrl = '//data/local/svoperapps';37 var queue = Q.defer();38 queue.resolve();39 return queue.promise.then(function() {40 return sh.run(['-c', 'adb shell rm -r ' + svoperappsUrl]);41 }).then(function() {42 return sh.run(['-c', 'adb push "' + utils.joinPath(profileFolder,43 'svoperapps') + '" ' + svoperappsUrl]);44 });45}46function installOneApp(targetFolder, buildAppName, remotePath, gaiaDomain) {47 var queue = Q.defer();48 queue.resolve();49 return queue.promise.then(function() {50 // "adb push /gaia/profile/webapps/SOME_APP.gaiamobile.org/manifest.webapp51 // /system/b2g/webapps/SOME_APP.gaiamobile.org/manifest.webapp"52 return sh.run(['-c',53 'adb push "' + utils.joinPath(targetFolder, 'manifest.webapp') +54 '" /' + remotePath + '/webapps/' + buildAppName + '.' +55 gaiaDomain + '/manifest.webapp']);56 }).then(function() {57 // adb push /gaia/profile/webapps/SOME_APP.gaiamobile.org/application.zip58 // /system/b2g/webapps/SOME_APP.gaiamobile.org/application.zip"59 return sh.run(['-c',60 'adb push "' + utils.joinPath(targetFolder, 'application.zip') +61 '" /' + remotePath + '/webapps/' + buildAppName + '.' +62 gaiaDomain + '/application.zip']);63 });64}65function execute(options) {66 const buildAppName = options.BUILD_APP_NAME;67 const gaiaDir = options.GAIA_DIR;68 const profileFolder = options.PROFILE_DIR;69 const gaiaDomain = options.GAIA_DOMAIN;70 const remotePath = options.GAIA_INSTALL_PARENT || '/system/b2g';71 var mainQ = Q.defer();72 var targetFolder;73 mainQ.resolve();74 return mainQ.promise.then(function() {75 return sh.run(['-c', 'adb start-server']);76 }).then(function() {77 var profile = utils.getFile(profileFolder);78 if (!profile.isDirectory()) {79 throw new Error(' -*- build/install-gaia.js: cannot locate' +80 'profile folder in ' + options.PROFILE_DIR);81 }82 }).then(function() {83 if (buildAppName === '*' || buildAppName === 'system') {84 return sh.run(['-c', 'adb shell stop b2g']);85 }86 }).then(function() {87 return sh.run(['-c', 'adb shell rm -r //cache/*']);88 }).then(function() {89 if (buildAppName === '*') {90 return installGaia(profileFolder, remotePath);91 } else {92 targetFolder = utils.joinPath(93 profileFolder, 'webapps',94 buildAppName + '.' + gaiaDomain);95 return installOneApp(targetFolder, buildAppName, remotePath, gaiaDomain);96 }97 }).then(function() {98 if (options.VARIANT_PATH) {99 return installSvoperapps(profileFolder);100 }101 }).then(function() {102 if (buildAppName === '*' || buildAppName === 'system') {103 sh.run(['-c', 'adb shell start b2g']);104 } else {105 var Q3 = Q.defer();106 var manifest;107 var appPid;108 Q3.resolve();109 return Q3.promise.then(function() {110 // Some app folder name is different with the process name,111 // ex. sms -> Messages112 manifest = utils.readZipManifest(utils.getFile(113 targetFolder));114 }).then(function() {115 utils.killAppByPid(manifest.name, gaiaDir);116 });117 }118 });119}120exports.execute = execute;121exports.installSvoperapps = installSvoperapps;...
Using AI Code Generation
1var adb = require('appium-adb').ADB.createADB();2var path = require('path');3var localPath = path.resolve(__dirname, 'test.txt');4var remotePath = '/data/local/tmp/';5adb.push(localPath, remotePath, function(err, stdout) {6 if (err) {7 console.log(err);8 } else {9 console.log(stdout);10 }11});
Using AI Code Generation
1var webdriver = require('selenium-webdriver');2var driver = new webdriver.Builder().forBrowser('chrome').build();3var adb = require('appium-adb');4var adb = new ADB();5adb.push('C:/Users/username/Downloads/test.txt', '/sdcard/test.txt', function(err) {6 if (err) {7 console.log(err);8 } else {9 console.log("File copied successfully");10 }11});12driver.quit();
Using AI Code Generation
1var adb = require('appium-adb');2var path = require('path');3var fs = require('fs');4var adbPath = '/path/to/adb';5var adbPort = 5037;6var adb = new ADB({adb: adbPath, port: adbPort});7var fileToPush = '/path/to/file/to/push';8var remotePath = '/path/on/device/to/push/file/to';9adb.push(fileToPush, remotePath).then(function(){10 console.log('File pushed');11});12var adb = require('appium-adb');13var path = require('path');14var fs = require('fs');15var adbPath = '/path/to/adb';16var adbPort = 5037;17var adb = new ADB({adb: adbPath, port: adbPort});18var fileToPull = '/path/on/device/to/pull/file/from';19var remotePath = '/path/to/pull/file/to';20adb.pull(fileToPull, remotePath).then(function(){21 console.log('File pulled');22});23var adb = require('appium-adb');24var path = require('path');25var fs = require('fs');26var adbPath = '/path/to/adb';27var adbPort = 5037;28var adb = new ADB({adb: adbPath, port: adbPort});29var command = 'ls -l';30adb.shell(command).then(function(stdout){31 console.log(stdout);32});33var adb = require('appium-adb');34var path = require('path');35var fs = require('fs');36var adbPath = '/path/to/adb';37var adbPort = 5037;38var adb = new ADB({adb: adbPath, port: adbPort});39var systemPort = 4724;40var devicePort = 4724;41adb.forwardPort(systemPort, devicePort).then(function(){42 console.log('Port forwarded');43});
Using AI Code Generation
1var path = require('path');2var adb = require('appium-adb').Adb;3var adb = new Adb();4var file = path.resolve(__dirname, 'test.txt');5var remotePath = '/data/local/tmp/test.txt';6adb.push(file, remotePath, function(err, stdout) {7 if (err) {8 console.log('Error pushing file: ' + err);9 } else {10 console.log('File pushed successfully');11 }12});
Using AI Code Generation
1const ADB = require('appium-adb').ADB;2const adb = new ADB();3const deviceId = '0123456789ABCDEF';4const sourceFile = 'sourceFile.txt';5const destinationFile = '/data/local/tmp/destinationFile.txt';6adb.push(deviceId, sourceFile, destinationFile);7adb.shell(deviceId, 'ls -l ' + destinationFile).then(function(stdout) {8 console.log(stdout);9});10const ADB = require('appium-adb').ADB;11const adb = new ADB();12const deviceId = '0123456789ABCDEF';13const sourceFile = 'sourceFile.txt';14const destinationFile = '/data/local/tmp/destinationFile.txt';15adb.push(deviceId, sourceFile, destinationFile);16adb.shell(deviceId, 'ls -l ' + destinationFile).then(function(stdout) {17 console.log(stdout);18});19executeTest();
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!