mirror of https://gitee.com/bigwinds/arangodb
Added an upgrade foxx dialog to the WebInterface
This commit is contained in:
parent
0d09cf0759
commit
eca23b3814
|
@ -2459,7 +2459,6 @@ window.StatisticsCollection = Backbone.Collection.extend({
|
|||
}());
|
||||
|
||||
/*jshint browser: true */
|
||||
/*jshint unused: false */
|
||||
/*global Backbone, $, window, setTimeout, Joi, _ */
|
||||
/*global templateEngine*/
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,13 +45,42 @@
|
|||
var fs = require("fs");
|
||||
var defaultThumb = require("/lib/defaultThumbnail").defaultThumb;
|
||||
|
||||
controller.extend({
|
||||
installer: function() {
|
||||
this.queryParam("mount", mountPoint);
|
||||
this.queryParam("upgrade", {type: joi.boolean().optional().description(
|
||||
"Trigger to upgrade the app installed at the mountpoint. Triggers setup."
|
||||
)});
|
||||
this.queryParam("replace", {type: joi.boolean().optional().description(
|
||||
"Trigger to replace the app installed at the mountpoint. Triggers teardown and setup."
|
||||
)});
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SECTION install
|
||||
// ------------------------------------------------------------
|
||||
|
||||
var installApp = function(res, appInfo, mount, options) {
|
||||
var validateMount = function(req) {
|
||||
var mount = req.params("mount");
|
||||
// Validation
|
||||
mount = decodeURIComponent(mount);
|
||||
return mount;
|
||||
};
|
||||
|
||||
var installApp = function(req, res, appInfo, options) {
|
||||
var mount = validateMount(req);
|
||||
var upgrade = req.params("upgrade") || false;
|
||||
var replace = req.params("replace") || false;
|
||||
try {
|
||||
var app = FoxxManager.install(appInfo, mount, options);
|
||||
var app;
|
||||
if (upgrade) {
|
||||
app = FoxxManager.upgrade(appInfo, mount, options);
|
||||
} else if (replace) {
|
||||
app = FoxxManager.replace(appInfo, mount, options);
|
||||
} else {
|
||||
app = FoxxManager.install(appInfo, mount, options);
|
||||
}
|
||||
var config = FoxxManager.configuration(mount);
|
||||
res.json({
|
||||
error: false,
|
||||
|
@ -65,12 +94,6 @@
|
|||
}
|
||||
};
|
||||
|
||||
var validateMount = function(req) {
|
||||
var mount = req.params("mount");
|
||||
// Validation
|
||||
mount = decodeURIComponent(mount);
|
||||
return mount;
|
||||
};
|
||||
/** Install a Foxx from the store
|
||||
*
|
||||
* Downloads a Foxx from the store and installs it at the given mount
|
||||
|
@ -78,10 +101,9 @@
|
|||
controller.put("/store", function(req, res) {
|
||||
var content = JSON.parse(req.requestBody),
|
||||
name = content.name,
|
||||
version = content.version,
|
||||
mount = validateMount(req);
|
||||
installApp(res, name + ":" + version, mount);
|
||||
}).queryParam("mount", mountPoint);
|
||||
version = content.version;
|
||||
installApp(req, res, name + ":" + version);
|
||||
}).installer();
|
||||
|
||||
/** Install a Foxx from Github
|
||||
*
|
||||
|
@ -90,20 +112,18 @@
|
|||
controller.put("/git", function (req, res) {
|
||||
var content = JSON.parse(req.requestBody),
|
||||
url = content.url,
|
||||
version = content.version,
|
||||
mount = validateMount(req);
|
||||
installApp(res, "git:" + url + ":" + (version || "master"), mount);
|
||||
}).queryParam("mount", mountPoint);
|
||||
version = content.version;
|
||||
installApp(req, res, "git:" + url + ":" + (version || "master"));
|
||||
}).installer();
|
||||
|
||||
/** Generate a new foxx
|
||||
*
|
||||
* Generate a new empty foxx on the given mount point
|
||||
*/
|
||||
controller.put("/generate", function (req, res) {
|
||||
var info = JSON.parse(req.requestBody),
|
||||
mount = validateMount(req);
|
||||
installApp(res, "EMPTY", mount, info);
|
||||
}).queryParam("mount", mountPoint);
|
||||
var info = JSON.parse(req.requestBody);
|
||||
installApp(req, res, "EMPTY", info);
|
||||
}).installer();
|
||||
|
||||
/** Install a Foxx from temporary zip file
|
||||
*
|
||||
|
@ -113,10 +133,10 @@
|
|||
controller.put("/zip", function (req, res) {
|
||||
var content = JSON.parse(req.requestBody),
|
||||
file = content.zipFile,
|
||||
mount = validateMount(req),
|
||||
path = fs.join(fs.getTempPath(), file);
|
||||
installApp(res, path, mount);
|
||||
}).queryParam("mount", mountPoint);
|
||||
installApp(req, res, path);
|
||||
}).installer();
|
||||
|
||||
|
||||
/** Uninstall a Foxx
|
||||
*
|
||||
|
|
|
@ -30,11 +30,19 @@
|
|||
|
||||
// Install Foxx from github repo
|
||||
// info is expected to contain: "url" and "version"
|
||||
installFromGithub: function (info, mount, callback) {
|
||||
installFromGithub: function (info, mount, callback, flag) {
|
||||
var url = "/_admin/aardvark/foxxes/git?mount=" + encodeURIComponent(mount);
|
||||
if (flag !== undefined) {
|
||||
if (flag) {
|
||||
url += "&replace=true";
|
||||
} else {
|
||||
url += "&upgrade=true";
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "PUT",
|
||||
url: "/_admin/aardvark/foxxes/git?mount=" + encodeURIComponent(mount),
|
||||
url: url,
|
||||
data: JSON.stringify(info),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
|
@ -49,11 +57,19 @@
|
|||
|
||||
// Install Foxx from arango store
|
||||
// info is expected to contain: "name" and "version"
|
||||
installFromStore: function (info, mount, callback) {
|
||||
installFromStore: function (info, mount, callback, flag) {
|
||||
var url = "/_admin/aardvark/foxxes/store?mount=" + encodeURIComponent(mount);
|
||||
if (flag !== undefined) {
|
||||
if (flag) {
|
||||
url += "&replace=true";
|
||||
} else {
|
||||
url += "&upgrade=true";
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "PUT",
|
||||
url: "/_admin/aardvark/foxxes/store?mount=" + encodeURIComponent(mount),
|
||||
url: url,
|
||||
data: JSON.stringify(info),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
|
@ -66,11 +82,19 @@
|
|||
});
|
||||
},
|
||||
|
||||
installFromZip: function(fileName, mount, callback) {
|
||||
installFromZip: function(fileName, mount, callback, flag) {
|
||||
var url = "/_admin/aardvark/foxxes/zip?mount=" + encodeURIComponent(mount);
|
||||
if (flag !== undefined) {
|
||||
if (flag) {
|
||||
url += "&replace=true";
|
||||
} else {
|
||||
url += "&upgrade=true";
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "PUT",
|
||||
url: "/_admin/aardvark/foxxes/zip?mount=" + encodeURIComponent(mount),
|
||||
url: url,
|
||||
data: JSON.stringify({zipFile: fileName}),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
|
@ -83,11 +107,19 @@
|
|||
});
|
||||
},
|
||||
|
||||
generate: function (info, mount, callback) {
|
||||
generate: function (info, mount, callback, flag) {
|
||||
var url = "/_admin/aardvark/foxxes/generate?mount=" + encodeURIComponent(mount);
|
||||
if (flag !== undefined) {
|
||||
if (flag) {
|
||||
url += "&replace=true";
|
||||
} else {
|
||||
url += "&upgrade=true";
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "PUT",
|
||||
url: "/_admin/aardvark/foxxes/generate?mount=" + encodeURIComponent(mount),
|
||||
url: url,
|
||||
data: JSON.stringify(info),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
|
|
|
@ -59,6 +59,11 @@
|
|||
initialize: function () {
|
||||
// This should be the only global object
|
||||
window.modalView = new window.ModalView();
|
||||
|
||||
this.foxxList = new window.FoxxCollection();
|
||||
window.foxxInstallView = new window.FoxxInstallView({
|
||||
collection: this.foxxList
|
||||
});
|
||||
window.progressView = new window.ProgressView();
|
||||
var self = this;
|
||||
|
||||
|
@ -78,7 +83,6 @@
|
|||
arangoHelper.setDocumentStore(this.arangoDocumentStore);
|
||||
|
||||
this.arangoCollectionsStore.fetch({async: false});
|
||||
this.foxxList = new window.FoxxCollection();
|
||||
|
||||
this.footerView = new window.FooterView();
|
||||
this.notificationList = new window.NotificationCollection();
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
</div>
|
||||
<div class="header_left">
|
||||
<input type="button" class="open button-success" disabled="true" value="Open" />
|
||||
<input id="app-upgrade" type="button" class="upgrade button-warning" value="Upgrade" <%=app.isSystem()?"disabled":"" %>/>
|
||||
<input id="app-switch-mode" type="button" class="switch-mode button-warning" value="<%=app.get('development')?'Set Pro':'Set Dev'%>" />
|
||||
<input type="button" class="delete button-danger" value="Delete" <%=app.isSystem()?"disabled":""%> />
|
||||
</div>
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
<script id="modalApplicationMount.ejs" type="text/template">
|
||||
<table>
|
||||
<tr class="tableRow">
|
||||
<th class="collectionInfoTh">
|
||||
Mount*:
|
||||
</th>
|
||||
<th class="collectionInfoTh">
|
||||
<input type="text" id="new-app-mount" value="" placeholder="/my/foxx"></input>
|
||||
</th>
|
||||
<th>
|
||||
<a class="modalTooltips" title="The path the app will be mounted. Has to start with /. Is not allowed to start with /_">
|
||||
<span class="arangoicon icon_arangodb_info"></span>
|
||||
</a>
|
||||
</th>
|
||||
<% if (content === true) { %>
|
||||
<th class="collectionInfoTh">
|
||||
Run teardown:
|
||||
</th>
|
||||
<th class="collectionInfoTh">
|
||||
<input type="checkbox" id="new-app-teardown"></input>
|
||||
</th>
|
||||
<% } else { %>
|
||||
<th class="collectionInfoTh">
|
||||
Mount*:
|
||||
</th>
|
||||
<th class="collectionInfoTh">
|
||||
<input type="text" id="new-app-mount" value="" placeholder="/my/foxx"></input>
|
||||
</th>
|
||||
<th>
|
||||
<a class="modalTooltips" title="The path the app will be mounted. Has to start with /. Is not allowed to start with /_">
|
||||
<span class="arangoicon icon_arangodb_info"></span>
|
||||
</a>
|
||||
</th>
|
||||
<% } %>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@ -70,7 +79,7 @@
|
|||
-->
|
||||
<tr class="tableRow">
|
||||
<th class="collectionInfoTh">
|
||||
Collections*:
|
||||
Collections:
|
||||
</th>
|
||||
<th class="collectionInfoTh">
|
||||
<input type="hidden" id="new-app-collections" value="" placeholder="Collections"></input>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*jshint browser: true */
|
||||
/*jshint strict: false, unused: false */
|
||||
/*global Backbone, $, window, arangoHelper, templateEngine, Joi, _, modalDialogHelper, alert*/
|
||||
/*global Backbone, $, window, arangoHelper, templateEngine, Joi, _*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
window.ApplicationDetailView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
|
@ -16,6 +16,14 @@
|
|||
'click #app-setup': 'setup',
|
||||
'click #app-teardown': 'teardown',
|
||||
"click #app-scripts": "toggleScripts",
|
||||
"click #app-upgrade": "upgradeApp"
|
||||
},
|
||||
|
||||
upgradeApp: function() {
|
||||
var mount = this.model.get("mount");
|
||||
window.foxxInstallView.upgrade(mount, function() {
|
||||
window.App.applicationDetail(encodeURIComponent(mount));
|
||||
});
|
||||
},
|
||||
|
||||
toggleScripts: function() {
|
||||
|
@ -48,13 +56,13 @@
|
|||
},
|
||||
|
||||
setup: function() {
|
||||
this.model.setup(function(data) {
|
||||
this.model.setup(function() {
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
this.model.teardown(function(data) {
|
||||
this.model.teardown(function() {
|
||||
|
||||
});
|
||||
},
|
||||
|
@ -67,7 +75,7 @@
|
|||
|
||||
$.get(this.appUrl()).success(function () {
|
||||
$('.open', this.el).prop('disabled', false);
|
||||
}, this);
|
||||
}.bind(this));
|
||||
|
||||
this.updateConfig();
|
||||
|
||||
|
@ -129,7 +137,7 @@
|
|||
return;
|
||||
}
|
||||
});
|
||||
this.model.setConfiguration(cfg, function(data) {
|
||||
this.model.setConfiguration(cfg, function() {
|
||||
window.modalView.hide();
|
||||
this.updateConfig();
|
||||
}.bind(this));
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
/*jshint browser: true */
|
||||
/*global require, Backbone, $, window, arangoHelper, templateEngine, Joi, alert, _*/
|
||||
/*global Backbone, $, window, arangoHelper, templateEngine, _*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var errors = require("internal").errors;
|
||||
|
||||
window.ApplicationsView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
|
||||
template: templateEngine.createTemplate("applicationsView.ejs"),
|
||||
appStoreTemplate: templateEngine.createTemplate("applicationListView.ejs"),
|
||||
|
||||
events: {
|
||||
"click #addApp" : "createInstallModal",
|
||||
|
@ -104,282 +101,9 @@
|
|||
$('#foxxDropdownOut').slideToggle(200);
|
||||
},
|
||||
|
||||
installFoxxFromStore: function(e) {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
var toInstall = $(e.currentTarget).attr("appId");
|
||||
var version = $(e.currentTarget).attr("appVersion");
|
||||
this.collection.installFromStore({name: toInstall, version: version}, mount, this.installCallback.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
installFoxxFromZip: function(files, data) {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
this.collection.installFromZip(data.filename, mount, this.installCallback.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
installCallback: function(result) {
|
||||
if (result.error === false) {
|
||||
window.modalView.hide();
|
||||
this.reload();
|
||||
} else {
|
||||
// TODO Error handling properly!
|
||||
switch(result.errorNum) {
|
||||
case errors.ERROR_APPLICATION_DOWNLOAD_FAILED.code:
|
||||
alert("Unable to download application from the given repository.");
|
||||
break;
|
||||
default:
|
||||
alert("Error: " + result.errorNum + ". " + result.errorMessage);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
installFoxxFromGithub: function() {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var url, version, mount;
|
||||
|
||||
//fetch needed information, need client side verification
|
||||
//remove name handling on server side because not needed
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
url = window.arangoHelper.escapeHtml($('#repository').val());
|
||||
version = window.arangoHelper.escapeHtml($('#tag').val());
|
||||
|
||||
if (version === '') {
|
||||
version = "master";
|
||||
}
|
||||
var info = {
|
||||
url: window.arangoHelper.escapeHtml($('#repository').val()),
|
||||
version: window.arangoHelper.escapeHtml($('#tag').val())
|
||||
};
|
||||
|
||||
try {
|
||||
Joi.assert(url, Joi.string().regex(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+$/));
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
//send server req through collection
|
||||
this.collection.installFromGithub(info, mount, this.installCallback.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
/* potential error handling
|
||||
if (info.responseText.indexOf("already used by") > -1) {
|
||||
alert("Mount path already in use.");
|
||||
} else if (info.responseText.indexOf("app is not defined") > -1) {
|
||||
//temp ignore this message, fix needs to be server-side
|
||||
window.modalView.hide();
|
||||
self.reload();
|
||||
} else {
|
||||
alert(info.statusText);
|
||||
}
|
||||
*/
|
||||
|
||||
generateNewFoxxApp: function() {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount;
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
var info = {
|
||||
name: window.arangoHelper.escapeHtml($("#new-app-name").val()),
|
||||
collectionNames: _.map($('#new-app-collections').select2("data"), function(d) {
|
||||
return window.arangoHelper.escapeHtml(d.text);
|
||||
}),
|
||||
// authenticated: window.arangoHelper.escapeHtml($("#new-app-name").val()),
|
||||
author: window.arangoHelper.escapeHtml($("#new-app-author").val()),
|
||||
license: window.arangoHelper.escapeHtml($("#new-app-license").val()),
|
||||
description: window.arangoHelper.escapeHtml($("#new-app-description").val())
|
||||
};
|
||||
this.collection.generate(info, mount, this.installCallback.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
addAppAction: function() {
|
||||
var openTab = $(".modal-body .tab-pane.active").attr("id");
|
||||
switch (openTab) {
|
||||
case "newApp":
|
||||
this.generateNewFoxxApp();
|
||||
break;
|
||||
case "github":
|
||||
this.installFoxxFromGithub();
|
||||
break;
|
||||
case "zip":
|
||||
// this.installFoxxFromZip();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
},
|
||||
|
||||
setMountpointValidators: function() {
|
||||
window.modalView.clearValidators();
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-mount",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().regex(/^(\/(APP[^\/]+|(?!APP)[a-zA-Z0-9_\-%]+))+$/i),
|
||||
msg: "May not contain /APP"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^(\/[a-zA-Z0-9_\-%]+)+$/),
|
||||
msg: "Can only contain [a-zA-Z0-9_-%]"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^\/[^_]/),
|
||||
msg: "Mountpoints with _ are reserved for internal use"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/[^\/]$/),
|
||||
msg: "May not end with /"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^\//),
|
||||
msg: "Has to start with /"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().required().min(2),
|
||||
msg: "Has to be non-empty"
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setGithubValidators: function() {
|
||||
window.modalView.modalBindValidation({
|
||||
id: "repository",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+$/),
|
||||
msg: "No valid github account and repository."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setNewAppValidators: function() {
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-author",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().min(1),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-name",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z\-_][a-zA-Z0-9\-_]*$/),
|
||||
msg: "Can only contain a to z, A to Z, 0-9, '-' and '_'."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-description",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().min(1),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-license",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z0-9 \.,;\-]+$/),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
window.modalView.modalTestAll();
|
||||
},
|
||||
|
||||
switchModalButton: function(event) {
|
||||
window.modalView.clearValidators();
|
||||
var openTab = $(event.currentTarget).attr("href").substr(1);
|
||||
var button = $("#modalButton1");
|
||||
this.setMountpointValidators();
|
||||
switch (openTab) {
|
||||
case "newApp":
|
||||
button.html("Generate");
|
||||
button.prop("disabled", false);
|
||||
this.setNewAppValidators();
|
||||
break;
|
||||
case "appstore":
|
||||
button.html("Install");
|
||||
button.prop("disabled", true);
|
||||
break;
|
||||
case "github":
|
||||
this.setGithubValidators();
|
||||
button.html("Install");
|
||||
button.prop("disabled", false);
|
||||
break;
|
||||
case "zip":
|
||||
button.html("Install");
|
||||
button.prop("disabled", false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
},
|
||||
|
||||
createInstallModal: function(event) {
|
||||
event.preventDefault();
|
||||
var buttons = [];
|
||||
var modalEvents = {
|
||||
"click #infoTab a" : this.switchModalButton.bind(this),
|
||||
"click .install-app" : this.installFoxxFromStore.bind(this)
|
||||
};
|
||||
buttons.push(
|
||||
window.modalView.createSuccessButton("Generate", this.addAppAction.bind(this))
|
||||
);
|
||||
window.modalView.show(
|
||||
"modalApplicationMount.ejs",
|
||||
"Install application",
|
||||
buttons,
|
||||
undefined,
|
||||
undefined,
|
||||
modalEvents
|
||||
);
|
||||
$("#new-app-collections").select2({
|
||||
tags: [],
|
||||
showSearchBox: false,
|
||||
minimumResultsForSearch: -1,
|
||||
width: "336px"
|
||||
});
|
||||
$("#upload-foxx-zip").uploadFile({
|
||||
url: "/_api/upload?multipart=true",
|
||||
allowedTypes: "zip",
|
||||
onSuccess: this.installFoxxFromZip.bind(this)
|
||||
});
|
||||
var listTempl = this.appStoreTemplate;
|
||||
$.get("foxxes/fishbowl", function(list) {
|
||||
var table = $("#appstore-content");
|
||||
_.each(_.sortBy(list, "name"), function(app) {
|
||||
table.append(listTempl.render(app));
|
||||
});
|
||||
}).fail(function() {
|
||||
var table = $("#appstore-content");
|
||||
table.append("<tr><td>Store is not available. ArangoDB is not able to connect to github.com</td></tr>");
|
||||
});
|
||||
this.setMountpointValidators();
|
||||
this.setNewAppValidators();
|
||||
window.foxxInstallView.install(this.reload.bind(this));
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
/*jshint browser: true */
|
||||
/*global require, $, Joi, _, alert, templateEngine*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var errors = require("internal").errors;
|
||||
var appStoreTemplate = templateEngine.createTemplate("applicationListView.ejs");
|
||||
|
||||
var FoxxInstallView = function(opts) {
|
||||
this.collection = opts.collection;
|
||||
};
|
||||
|
||||
var installCallback = function(result) {
|
||||
if (result.error === false) {
|
||||
this.collection.fetch({ async: false });
|
||||
window.modalView.hide();
|
||||
this.reload();
|
||||
} else {
|
||||
// TODO Error handling properly!
|
||||
switch(result.errorNum) {
|
||||
case errors.ERROR_APPLICATION_DOWNLOAD_FAILED.code:
|
||||
alert("Unable to download application from the given repository.");
|
||||
break;
|
||||
default:
|
||||
alert("Error: " + result.errorNum + ". " + result.errorMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setMountpointValidators = function() {
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-mount",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().regex(/^(\/(APP[^\/]+|(?!APP)[a-zA-Z0-9_\-%]+))+$/i),
|
||||
msg: "May not contain /APP"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^(\/[a-zA-Z0-9_\-%]+)+$/),
|
||||
msg: "Can only contain [a-zA-Z0-9_-%]"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^\/[^_]/),
|
||||
msg: "Mountpoints with _ are reserved for internal use"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/[^\/]$/),
|
||||
msg: "May not end with /"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().regex(/^\//),
|
||||
msg: "Has to start with /"
|
||||
},
|
||||
{
|
||||
rule: Joi.string().required().min(2),
|
||||
msg: "Has to be non-empty"
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var setGithubValidators = function() {
|
||||
window.modalView.modalBindValidation({
|
||||
id: "repository",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+$/),
|
||||
msg: "No valid github account and repository."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var setNewAppValidators = function() {
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-author",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().min(1),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-name",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z\-_][a-zA-Z0-9\-_]*$/),
|
||||
msg: "Can only contain a to z, A to Z, 0-9, '-' and '_'."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-description",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().min(1),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
window.modalView.modalBindValidation({
|
||||
id: "new-app-license",
|
||||
validateInput: function() {
|
||||
return [
|
||||
{
|
||||
rule: Joi.string().required().regex(/^[a-zA-Z0-9 \.,;\-]+$/),
|
||||
msg: "Has to be non empty."
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
window.modalView.modalTestAll();
|
||||
};
|
||||
|
||||
var switchModalButton = function(event) {
|
||||
window.modalView.clearValidators();
|
||||
var openTab = $(event.currentTarget).attr("href").substr(1);
|
||||
var button = $("#modalButton1");
|
||||
if (!this._upgrade) {
|
||||
setMountpointValidators();
|
||||
}
|
||||
switch (openTab) {
|
||||
case "newApp":
|
||||
button.html("Generate");
|
||||
button.prop("disabled", false);
|
||||
setNewAppValidators();
|
||||
break;
|
||||
case "appstore":
|
||||
button.html("Install");
|
||||
button.prop("disabled", true);
|
||||
break;
|
||||
case "github":
|
||||
setGithubValidators();
|
||||
button.html("Install");
|
||||
button.prop("disabled", false);
|
||||
break;
|
||||
case "zip":
|
||||
button.html("Install");
|
||||
button.prop("disabled", false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
var installFoxxFromStore = function(e) {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount, flag;
|
||||
if (this._upgrade) {
|
||||
mount = this.mount;
|
||||
flag = $('#new-app-teardown').prop("checked");
|
||||
} else {
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
}
|
||||
var toInstall = $(e.currentTarget).attr("appId");
|
||||
var version = $(e.currentTarget).attr("appVersion");
|
||||
if (flag !== undefined) {
|
||||
this.collection.installFromStore({name: toInstall, version: version}, mount, installCallback.bind(this), flag);
|
||||
} else {
|
||||
this.collection.installFromStore({name: toInstall, version: version}, mount, installCallback.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var installFoxxFromZip = function(files, data) {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount, flag;
|
||||
if (this._upgrade) {
|
||||
mount = this.mount;
|
||||
flag = $('#new-app-teardown').prop("checked");
|
||||
} else {
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
}
|
||||
if (flag !== undefined) {
|
||||
this.collection.installFromZip(data.filename, mount, installCallback.bind(this), flag);
|
||||
} else {
|
||||
this.collection.installFromZip(data.filename, mount, installCallback.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var installFoxxFromGithub = function() {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var url, version, mount, flag;
|
||||
if (this._upgrade) {
|
||||
mount = this.mount;
|
||||
flag = $('#new-app-teardown').prop("checked");
|
||||
} else {
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
}
|
||||
url = window.arangoHelper.escapeHtml($('#repository').val());
|
||||
version = window.arangoHelper.escapeHtml($('#tag').val());
|
||||
|
||||
if (version === '') {
|
||||
version = "master";
|
||||
}
|
||||
var info = {
|
||||
url: window.arangoHelper.escapeHtml($('#repository').val()),
|
||||
version: window.arangoHelper.escapeHtml($('#tag').val())
|
||||
};
|
||||
|
||||
try {
|
||||
Joi.assert(url, Joi.string().regex(/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+$/));
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
//send server req through collection
|
||||
if (flag !== undefined) {
|
||||
this.collection.installFromGithub(info, mount, installCallback.bind(this), flag);
|
||||
} else {
|
||||
this.collection.installFromGithub(info, mount, installCallback.bind(this));
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var generateNewFoxxApp = function() {
|
||||
if (window.modalView.modalTestAll()) {
|
||||
var mount, flag;
|
||||
if (this._upgrade) {
|
||||
mount = this.mount;
|
||||
flag = $('#new-app-teardown').prop("checked");
|
||||
} else {
|
||||
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
|
||||
}
|
||||
var info = {
|
||||
name: window.arangoHelper.escapeHtml($("#new-app-name").val()),
|
||||
collectionNames: _.map($('#new-app-collections').select2("data"), function(d) {
|
||||
return window.arangoHelper.escapeHtml(d.text);
|
||||
}),
|
||||
// authenticated: window.arangoHelper.escapeHtml($("#new-app-name").val()),
|
||||
author: window.arangoHelper.escapeHtml($("#new-app-author").val()),
|
||||
license: window.arangoHelper.escapeHtml($("#new-app-license").val()),
|
||||
description: window.arangoHelper.escapeHtml($("#new-app-description").val())
|
||||
};
|
||||
if (flag !== undefined) {
|
||||
this.collection.generate(info, mount, installCallback.bind(this), flag);
|
||||
} else {
|
||||
this.collection.generate(info, mount, installCallback.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var addAppAction = function() {
|
||||
var openTab = $(".modal-body .tab-pane.active").attr("id");
|
||||
switch (openTab) {
|
||||
case "newApp":
|
||||
generateNewFoxxApp.apply(this);
|
||||
break;
|
||||
case "github":
|
||||
installFoxxFromGithub.apply(this);
|
||||
break;
|
||||
case "zip":
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
var render = function(scope, upgrade) {
|
||||
var buttons = [];
|
||||
var modalEvents = {
|
||||
"click #infoTab a" : switchModalButton.bind(scope),
|
||||
"click .install-app" : installFoxxFromStore.bind(scope)
|
||||
};
|
||||
buttons.push(
|
||||
window.modalView.createSuccessButton("Generate", addAppAction.bind(scope))
|
||||
);
|
||||
window.modalView.show(
|
||||
"modalApplicationMount.ejs",
|
||||
"Install application",
|
||||
buttons,
|
||||
upgrade,
|
||||
undefined,
|
||||
modalEvents
|
||||
);
|
||||
$("#new-app-collections").select2({
|
||||
tags: [],
|
||||
showSearchBox: false,
|
||||
minimumResultsForSearch: -1,
|
||||
width: "336px"
|
||||
});
|
||||
$("#upload-foxx-zip").uploadFile({
|
||||
url: "/_api/upload?multipart=true",
|
||||
allowedTypes: "zip",
|
||||
onSuccess: installFoxxFromZip.bind(scope)
|
||||
});
|
||||
$.get("foxxes/fishbowl", function(list) {
|
||||
var table = $("#appstore-content");
|
||||
_.each(_.sortBy(list, "name"), function(app) {
|
||||
table.append(appStoreTemplate.render(app));
|
||||
});
|
||||
}).fail(function() {
|
||||
var table = $("#appstore-content");
|
||||
table.append("<tr><td>Store is not available. ArangoDB is not able to connect to github.com</td></tr>");
|
||||
});
|
||||
};
|
||||
|
||||
FoxxInstallView.prototype.install = function(callback) {
|
||||
this.reload = callback;
|
||||
this._upgrade = false;
|
||||
delete this.mount;
|
||||
render(this, false);
|
||||
window.modalView.clearValidators();
|
||||
setMountpointValidators();
|
||||
setNewAppValidators();
|
||||
|
||||
};
|
||||
|
||||
FoxxInstallView.prototype.upgrade = function(mount, callback) {
|
||||
this.reload = callback;
|
||||
this._upgrade = true;
|
||||
this.mount = mount;
|
||||
render(this, true);
|
||||
window.modalView.clearValidators();
|
||||
setNewAppValidators();
|
||||
};
|
||||
|
||||
window.FoxxInstallView = FoxxInstallView;
|
||||
}());
|
|
@ -1,5 +1,4 @@
|
|||
/*jshint browser: true */
|
||||
/*jshint unused: false */
|
||||
/*global Backbone, $, window, setTimeout, Joi, _ */
|
||||
/*global templateEngine*/
|
||||
|
||||
|
|
|
@ -30,12 +30,10 @@
|
|||
position: absolute;
|
||||
width: 120px;
|
||||
|
||||
input.delete {
|
||||
margin-top: (160px - 3 * 30px) / 2;
|
||||
}
|
||||
|
||||
input.delete,
|
||||
input.upgrade,
|
||||
input.switch-mode {
|
||||
margin-top: (160px - 3 * 30px) / 2;
|
||||
margin-top: (160px - 4 * 30px) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
"test/specs/views/applicationsViewSpec.js",
|
||||
"test/specs/views/applicationDetailViewSpec.js",
|
||||
"test/specs/views/modalViewSpec.js",
|
||||
"test/specs/views/installFoxxViewSpec.js",
|
||||
"test/specs/views/editListEntryViewSpec.js",
|
||||
"test/specs/views/collectionsViewSpec.js",
|
||||
"test/specs/views/collectionsItemViewSpec.js",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
"test/specs/views/apiViewSpec.js",
|
||||
"test/specs/views/modalViewSpec.js",
|
||||
"test/specs/views/foxxInstallViewSpec.js",
|
||||
"test/specs/views/editListEntryViewSpec.js",
|
||||
"test/specs/views/collectionsViewSpec.js",
|
||||
"test/specs/views/collectionsItemViewSpec.js",
|
||||
|
|
|
@ -179,6 +179,248 @@
|
|||
});
|
||||
});
|
||||
|
||||
describe("upgrading apps", function() {
|
||||
|
||||
it("should generate an app", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
name: "My App",
|
||||
author: "ArangoDB",
|
||||
description: "Description of the App",
|
||||
license: "Apache 2",
|
||||
collectionNames: ["first", "second"]
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.generate(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, false);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/generate?mount=" + encodeURIComponent(mount) + "&upgrade=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from github", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
url: "arangodb/itzpapalotl",
|
||||
version: "1.2.0"
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromGithub(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, false);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/git?mount=" + encodeURIComponent(mount) + "&upgrade=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from store", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
name: "itzpapalotl",
|
||||
version: "1.2.0"
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromStore(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, false);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/store?mount=" + encodeURIComponent(mount) + "&upgrade=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
});
|
||||
|
||||
it("should install an app from an uploaded zip", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
var fileName = "uploads/tmp-123.zip";
|
||||
calledBack = false;
|
||||
info = {
|
||||
zipFile: fileName,
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromZip(fileName, mount, function() {
|
||||
calledBack = true;
|
||||
}, false);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/zip?mount=" + encodeURIComponent(mount) + "&upgrade=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe("replacing apps", function() {
|
||||
|
||||
it("should generate an app", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
name: "My App",
|
||||
author: "ArangoDB",
|
||||
description: "Description of the App",
|
||||
license: "Apache 2",
|
||||
collectionNames: ["first", "second"]
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.generate(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, true);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/generate?mount=" + encodeURIComponent(mount) + "&replace=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from github", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
url: "arangodb/itzpapalotl",
|
||||
version: "1.2.0"
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromGithub(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, true);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/git?mount=" + encodeURIComponent(mount) + "&replace=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from store", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
calledBack = false;
|
||||
info = {
|
||||
name: "itzpapalotl",
|
||||
version: "1.2.0"
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromStore(info, mount, function() {
|
||||
calledBack = true;
|
||||
}, true);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/store?mount=" + encodeURIComponent(mount) + "&replace=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
});
|
||||
|
||||
it("should install an app from an uploaded zip", function() {
|
||||
var calledBack, info, mount;
|
||||
|
||||
runs(function() {
|
||||
var fileName = "uploads/tmp-123.zip";
|
||||
calledBack = false;
|
||||
info = {
|
||||
zipFile: fileName,
|
||||
};
|
||||
mount = "/my/app";
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
col.installFromZip(fileName, mount, function() {
|
||||
calledBack = true;
|
||||
}, true);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return calledBack;
|
||||
}, 750);
|
||||
|
||||
runs(function() {
|
||||
var url = "/_admin/aardvark/foxxes/zip?mount=" + encodeURIComponent(mount) + "&replace=true";
|
||||
validateRequest(url, "PUT", JSON.stringify(info));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
// Spy on all views that are initialized by startup
|
||||
beforeEach(function () {
|
||||
window.CreateDummyForObject(window, "FoxxInstallView");
|
||||
naviDummy = {
|
||||
id: "navi",
|
||||
render: function () {
|
||||
|
@ -253,6 +254,7 @@
|
|||
afterEach(function() {
|
||||
// Remove all global values the router has created.
|
||||
delete window.modalView;
|
||||
delete window.foxxInstallView;
|
||||
delete window.progressView;
|
||||
});
|
||||
|
||||
|
@ -265,6 +267,13 @@
|
|||
r = new window.Router();
|
||||
});
|
||||
|
||||
it("should create the foxx installer", function() {
|
||||
expect(window.FoxxInstallView).toHaveBeenCalledWith({
|
||||
collection: foxxDummy
|
||||
});
|
||||
expect(window.foxxInstallView).toBeDefined();
|
||||
});
|
||||
|
||||
it("should trigger the version check", function() {
|
||||
expect(window.checkVersion).toHaveBeenCalled();
|
||||
expect(window.checkVersion.callCount).toEqual(1);
|
||||
|
|
|
@ -53,7 +53,9 @@
|
|||
deleteButton = $("input.delete");
|
||||
openButton = $("input.open");
|
||||
window.CreateDummyForObject(window, "Router");
|
||||
window.CreateDummyForObject(window, "FoxxInstallView");
|
||||
window.App = new window.Router();
|
||||
window.foxxInstallView = new window.FoxxInstallView();
|
||||
spyOn(window.App, "navigate");
|
||||
});
|
||||
|
||||
|
@ -394,6 +396,21 @@
|
|||
$(button).click();
|
||||
expect(appDummy.teardown).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("should offer upgrading the app", function() {
|
||||
spyOn(window.foxxInstallView, "upgrade").andCallFake(function(mount, cb) {
|
||||
expect(mount).toEqual(appDummy.get("mount"));
|
||||
expect(cb).toEqual(jasmine.any(Function));
|
||||
cb();
|
||||
});
|
||||
spyOn(window.App, "applicationDetail");
|
||||
$("#app-upgrade").click();
|
||||
expect(window.foxxInstallView.upgrade).toHaveBeenCalled();
|
||||
expect(window.App.applicationDetail).toHaveBeenCalledWith(
|
||||
encodeURIComponent(view.model.get('mount'))
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
describe("edit a foxx", function() {
|
||||
|
||||
|
|
|
@ -21,11 +21,15 @@
|
|||
document.body.appendChild(div);
|
||||
window.CreateDummyForObject(window, "FoxxCollection");
|
||||
listDummy = new window.FoxxCollection();
|
||||
window.foxxInstallView = new window.FoxxInstallView({
|
||||
collection: listDummy
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
document.body.removeChild(div);
|
||||
delete window.modalView;
|
||||
delete window.foxxInstallView;
|
||||
document.body.removeChild(modalDiv);
|
||||
});
|
||||
|
||||
|
@ -68,6 +72,7 @@
|
|||
view = new window.ApplicationsView({
|
||||
collection: listDummy
|
||||
});
|
||||
spyOn(view, "reload");
|
||||
|
||||
runs(function () {
|
||||
$("#addApp").click();
|
||||
|
@ -123,7 +128,6 @@
|
|||
$("#new-app-license").val(license);
|
||||
$("#new-app-mount").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
spyOn(view, "reload");
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
|
@ -157,7 +161,6 @@
|
|||
expect($("#appstore-content").children().length).toEqual(2);
|
||||
button = $("#appstore-content .install-app[appId='" + storeApp + "']");
|
||||
expect(button.length).toEqual(1);
|
||||
spyOn(view, "reload");
|
||||
button.click();
|
||||
});
|
||||
|
||||
|
@ -195,7 +198,6 @@
|
|||
$("#tag").val(version);
|
||||
$("#new-app-mount").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
spyOn(view, "reload");
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
|
@ -224,7 +226,6 @@
|
|||
});
|
||||
});
|
||||
$("#new-app-mount").val(mount);
|
||||
spyOn(view, "reload");
|
||||
uploadCallback(["app.zip"], {filename: fileName});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,618 @@
|
|||
/*jshint browser: true */
|
||||
/*global describe, beforeEach, afterEach, it, spyOn, expect*/
|
||||
/*global runs, waitsFor, jasmine*/
|
||||
/*global $*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
describe("Foxx Install View", function() {
|
||||
var view, listDummy, closeButton, generateButton, modalDiv,
|
||||
uploadCallback, storeApp, storeAppVersion;
|
||||
|
||||
beforeEach(function() {
|
||||
modalDiv = document.createElement("div");
|
||||
modalDiv.id = "modalPlaceholder";
|
||||
document.body.appendChild(modalDiv);
|
||||
window.modalView = new window.ModalView();
|
||||
closeButton = "#modalButton0";
|
||||
generateButton = "#modalButton1";
|
||||
window.CreateDummyForObject(window, "FoxxCollection");
|
||||
listDummy = new window.FoxxCollection();
|
||||
view = new window.FoxxInstallView({
|
||||
collection: listDummy
|
||||
});
|
||||
storeApp = "Online App";
|
||||
storeAppVersion = "2.1.1";
|
||||
spyOn(listDummy, "fetch").andCallFake(function(opts) {
|
||||
opts.success();
|
||||
});
|
||||
spyOn(listDummy, "each");
|
||||
spyOn(listDummy, "sort");
|
||||
spyOn($.fn, "uploadFile").andCallFake(function(opts) {
|
||||
expect(opts.url).toEqual("/_api/upload?multipart=true");
|
||||
expect(opts.allowedTypes).toEqual("zip");
|
||||
expect(opts.onSuccess).toEqual(jasmine.any(Function));
|
||||
uploadCallback = opts.onSuccess;
|
||||
});
|
||||
spyOn($, "get").andCallFake(function(url, callback) {
|
||||
expect(url).toEqual("foxxes/fishbowl");
|
||||
callback([
|
||||
{
|
||||
name: "MyApp",
|
||||
author: "ArangoDB",
|
||||
description: "Description of the app",
|
||||
latestVersion: "1.1.0"
|
||||
},{
|
||||
name: storeApp,
|
||||
author: "ArangoDB",
|
||||
description: "Description of the other app",
|
||||
latestVersion: storeAppVersion
|
||||
}
|
||||
]);
|
||||
return {
|
||||
fail: function() {}
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
delete window.modalView;
|
||||
document.body.removeChild(modalDiv);
|
||||
});
|
||||
|
||||
describe("Adding a new App", function() {
|
||||
var spyFunc;
|
||||
|
||||
beforeEach(function() {
|
||||
runs(function () {
|
||||
spyFunc = jasmine.createSpy("reload");
|
||||
view.install(spyFunc);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "block";
|
||||
}, "The Add App dialog should be shown", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should open and close the install dialog", function() {
|
||||
|
||||
runs(function() {
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should offer the mountpoint input but not the run teardown", function() {
|
||||
|
||||
runs(function() {
|
||||
expect($("#new-app-mount").length).toEqual(1);
|
||||
expect($("#new-app-teardown").length).toEqual(0);
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should generate an empty app", function() {
|
||||
var mount, author, name, desc, license, expectedInfo;
|
||||
|
||||
runs(function() {
|
||||
$("#tab-new").click();
|
||||
spyOn(listDummy, "generate").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
mount = "/my/application";
|
||||
author = "ArangoDB";
|
||||
name = "MyApp";
|
||||
desc = "My new app";
|
||||
license = "Apache 2";
|
||||
expectedInfo = {
|
||||
author: author,
|
||||
name: name,
|
||||
description: desc,
|
||||
license: license,
|
||||
collectionNames: []
|
||||
};
|
||||
|
||||
expect($(generateButton).prop("disabled")).toBeTruthy();
|
||||
|
||||
$("#new-app-mount").val(mount);
|
||||
$("#new-app-author").val(author);
|
||||
$("#new-app-name").val(name);
|
||||
$("#new-app-description").val(desc);
|
||||
$("#new-app-license").val(license);
|
||||
$("#new-app-mount").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.generate).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from the store", function() {
|
||||
var mount;
|
||||
|
||||
runs(function() {
|
||||
var button;
|
||||
mount = "/my/application";
|
||||
$("#tab-store").click();
|
||||
$("#new-app-mount").val(mount);
|
||||
$("#new-app-mount").keyup();
|
||||
spyOn(listDummy, "installFromStore").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
expect($("#appstore-content").children().length).toEqual(2);
|
||||
button = $("#appstore-content .install-app[appId='" + storeApp + "']");
|
||||
expect(button.length).toEqual(1);
|
||||
button.click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromStore).toHaveBeenCalledWith(
|
||||
{name: storeApp, version: storeAppVersion}, mount, jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from github", function() {
|
||||
var repository, version, mount, expectedInfo;
|
||||
runs(function() {
|
||||
$("#tab-git").click();
|
||||
spyOn(listDummy, "installFromGithub").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
repository = "arangodb/itzpapalotl";
|
||||
version = "1.2.0";
|
||||
mount = "/my/application";
|
||||
expectedInfo = {
|
||||
url: repository,
|
||||
version: version
|
||||
};
|
||||
$("#new-app-mount").val(mount);
|
||||
$("#repository").val(repository);
|
||||
$("#tag").val(version);
|
||||
$("#new-app-mount").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromGithub).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should install an app from zip file", function() {
|
||||
var fileName = "/tmp/upload-12345.zip";
|
||||
var mount = "/my/application";
|
||||
|
||||
runs(function() {
|
||||
$("#tab-zip").click();
|
||||
spyOn(listDummy, "installFromZip").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
$("#new-app-mount").val(mount);
|
||||
uploadCallback(["app.zip"], {filename: fileName});
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromZip).toHaveBeenCalledWith(
|
||||
fileName, mount, jasmine.any(Function)
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("Upgradeing App", function() {
|
||||
var spyFunc, mount;
|
||||
|
||||
beforeEach(function() {
|
||||
runs(function () {
|
||||
mount = "/my/application";
|
||||
spyFunc = jasmine.createSpy("reload");
|
||||
view.upgrade(mount, spyFunc);
|
||||
$("#new-app-teardown").prop("checked", false);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "block";
|
||||
}, "The Add App dialog should be shown", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should open and close the dialog", function() {
|
||||
|
||||
runs(function() {
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should not offer the mountpoint input but the run teardown", function() {
|
||||
|
||||
runs(function() {
|
||||
expect($("#new-app-mount").length).toEqual(0);
|
||||
expect($("#new-app-teardown").length).toEqual(1);
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it("generate an empty app", function() {
|
||||
var author, name, desc, license, expectedInfo;
|
||||
|
||||
runs(function() {
|
||||
$("#tab-new").click();
|
||||
spyOn(listDummy, "generate").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
author = "ArangoDB";
|
||||
name = "MyApp";
|
||||
desc = "My new app";
|
||||
license = "Apache 2";
|
||||
expectedInfo = {
|
||||
author: author,
|
||||
name: name,
|
||||
description: desc,
|
||||
license: license,
|
||||
collectionNames: []
|
||||
};
|
||||
|
||||
expect($(generateButton).prop("disabled")).toBeTruthy();
|
||||
|
||||
$("#new-app-author").val(author);
|
||||
$("#new-app-name").val(name);
|
||||
$("#new-app-description").val(desc);
|
||||
$("#new-app-license").val(license);
|
||||
$("#new-app-license").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.generate).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function), false
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from the store", function() {
|
||||
|
||||
runs(function() {
|
||||
var button;
|
||||
$("#tab-store").click();
|
||||
spyOn(listDummy, "installFromStore").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
expect($("#appstore-content").children().length).toEqual(2);
|
||||
button = $("#appstore-content .install-app[appId='" + storeApp + "']");
|
||||
expect(button.length).toEqual(1);
|
||||
button.click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromStore).toHaveBeenCalledWith(
|
||||
{name: storeApp, version: storeAppVersion}, mount, jasmine.any(Function), false
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from github", function() {
|
||||
var repository, version, expectedInfo;
|
||||
|
||||
runs(function() {
|
||||
$("#tab-git").click();
|
||||
spyOn(listDummy, "installFromGithub").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
repository = "arangodb/itzpapalotl";
|
||||
version = "1.2.0";
|
||||
expectedInfo = {
|
||||
url: repository,
|
||||
version: version
|
||||
};
|
||||
$("#repository").val(repository);
|
||||
$("#tag").val(version).keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromGithub).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function), false
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from zip file", function() {
|
||||
var fileName = "/tmp/upload-12345.zip";
|
||||
|
||||
runs(function() {
|
||||
$("#tab-zip").click();
|
||||
spyOn(listDummy, "installFromZip").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
uploadCallback(["app.zip"], {filename: fileName});
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromZip).toHaveBeenCalledWith(
|
||||
fileName, mount, jasmine.any(Function), false
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Replacing App", function() {
|
||||
var spyFunc, mount;
|
||||
|
||||
beforeEach(function() {
|
||||
runs(function () {
|
||||
mount = "/my/application";
|
||||
spyFunc = jasmine.createSpy("reload");
|
||||
view.upgrade(mount, spyFunc);
|
||||
$("#new-app-teardown").prop("checked", true);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "block";
|
||||
}, "The Add App dialog should be shown", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should open and close the dialog", function() {
|
||||
|
||||
runs(function() {
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
it("should not offer the mountpoint input but the run teardown", function() {
|
||||
|
||||
runs(function() {
|
||||
expect($("#new-app-mount").length).toEqual(0);
|
||||
expect($("#new-app-teardown").length).toEqual(1);
|
||||
$(closeButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it("generate an empty app", function() {
|
||||
var author, name, desc, license, expectedInfo;
|
||||
|
||||
runs(function() {
|
||||
$("#tab-new").click();
|
||||
spyOn(listDummy, "generate").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
author = "ArangoDB";
|
||||
name = "MyApp";
|
||||
desc = "My new app";
|
||||
license = "Apache 2";
|
||||
expectedInfo = {
|
||||
author: author,
|
||||
name: name,
|
||||
description: desc,
|
||||
license: license,
|
||||
collectionNames: []
|
||||
};
|
||||
|
||||
expect($(generateButton).prop("disabled")).toBeTruthy();
|
||||
|
||||
$("#new-app-author").val(author);
|
||||
$("#new-app-name").val(name);
|
||||
$("#new-app-description").val(desc);
|
||||
$("#new-app-license").val(license);
|
||||
$("#new-app-license").keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.generate).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function), true
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from the store", function() {
|
||||
|
||||
runs(function() {
|
||||
var button;
|
||||
$("#tab-store").click();
|
||||
spyOn(listDummy, "installFromStore").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
expect($("#appstore-content").children().length).toEqual(2);
|
||||
button = $("#appstore-content .install-app[appId='" + storeApp + "']");
|
||||
expect(button.length).toEqual(1);
|
||||
button.click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromStore).toHaveBeenCalledWith(
|
||||
{name: storeApp, version: storeAppVersion}, mount, jasmine.any(Function), true
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from github", function() {
|
||||
var repository, version, expectedInfo;
|
||||
|
||||
runs(function() {
|
||||
$("#tab-git").click();
|
||||
spyOn(listDummy, "installFromGithub").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
repository = "arangodb/itzpapalotl";
|
||||
version = "1.2.0";
|
||||
expectedInfo = {
|
||||
url: repository,
|
||||
version: version
|
||||
};
|
||||
$("#repository").val(repository);
|
||||
$("#tag").val(version).keyup();
|
||||
expect($(generateButton).prop("disabled")).toBeFalsy();
|
||||
$(generateButton).click();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromGithub).toHaveBeenCalledWith(
|
||||
expectedInfo, mount, jasmine.any(Function), true
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("an app from zip file", function() {
|
||||
var fileName = "/tmp/upload-12345.zip";
|
||||
|
||||
runs(function() {
|
||||
$("#tab-zip").click();
|
||||
spyOn(listDummy, "installFromZip").andCallFake(function(i, m, callback) {
|
||||
callback({
|
||||
error: false
|
||||
});
|
||||
});
|
||||
uploadCallback(["app.zip"], {filename: fileName});
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return $("#modal-dialog").css("display") === "none";
|
||||
}, "The Add App dialog should be hidden.", 750);
|
||||
|
||||
runs(function() {
|
||||
expect(spyFunc).toHaveBeenCalled();
|
||||
expect(listDummy.installFromZip).toHaveBeenCalledWith(
|
||||
fileName, mount, jasmine.any(Function), true
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
||||
|
Loading…
Reference in New Issue