Adding test infrastructure and check for update end to end tests.

This commit is contained in:
Daniel Lebu 2015-09-30 09:20:53 -07:00
Родитель 9a14feaa92
Коммит a0e4809e64
26 изменённых файлов: 2496 добавлений и 38 удалений

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/
@ -13,8 +13,7 @@
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Package = require("./package");
var NativeAppInfo = require("./nativeAppInfo");

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/

Просмотреть файл

@ -4,7 +4,7 @@
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING.
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE.
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD.
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md.
*********************************************************************************************/
@ -14,8 +14,7 @@
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var LocalPackage = require("./localPackage");
var Package = require("./package");

Просмотреть файл

@ -1,7 +1,10 @@
var gulp = require("gulp");
var path = require("path");
var sourcePath = "./www";
var testPath = "./test";
var binPath = "./bin";
var tsFiles = "/**/*.ts";
/* This message is appended to the compiled JS files to avoid contributions to the compiled sources.*/
var compiledSourceWarningMessage = "\n \
@ -10,26 +13,43 @@ var compiledSourceWarningMessage = "\n \
PLEASE DO NOT MODIFY THIS FILE AS YOU WILL LOSE YOUR CHANGES WHEN RECOMPILING. \n \
ALSO, PLEASE DO NOT SUBMIT PULL REQUESTS WITH CHANGES TO THIS FILE. \n \
INSTEAD, EDIT THE TYPESCRIPT SOURCES UNDER THE WWW FOLDER. \n \
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.MD. \n \
FOR MORE INFORMATION, PLEASE SEE CONTRIBUTING.md. \n \
*********************************************************************************************/ \n\n\n";
gulp.task("compile", function () {
/* TypeScript compilation parameters */
var tsCompileOptions = {
"noImplicitAny": true,
"noEmitOnError": true,
"target": "ES5",
"module": "commonjs",
"sourceMap": false,
"sortOutput": true,
"removeComments": true
};
gulp.task("compile", function (callback) {
var runSequence = require("run-sequence");
runSequence("compile-src", "compile-test", callback);
});
gulp.task("compile-test", function () {
var ts = require("gulp-typescript");
var insert = require("gulp-insert");
var tsCompileOptions = {
"noImplicitAny": true,
"noEmitOnError": true,
"target": "ES5",
"module": "commonjs",
"sourceMap": false,
"sortOutput": true,
"removeComments": true
};
return gulp.src([sourcePath + "/**/*.ts"])
return gulp.src([testPath + tsFiles])
.pipe(ts(tsCompileOptions))
.pipe(insert.prepend(compiledSourceWarningMessage))
.pipe(gulp.dest(binPath));
.pipe(gulp.dest(path.join(binPath, testPath)));
});
gulp.task("compile-src", function () {
var ts = require("gulp-typescript");
var insert = require("gulp-insert");
return gulp.src([sourcePath + tsFiles])
.pipe(ts(tsCompileOptions))
.pipe(insert.prepend(compiledSourceWarningMessage))
.pipe(gulp.dest(path.join(binPath, sourcePath)));
});
gulp.task("tslint", function () {
@ -73,17 +93,17 @@ gulp.task("tslint", function () {
}
}
return gulp.src(sourcePath + "/**/*.ts")
return gulp.src([sourcePath + tsFiles, testPath + tsFiles])
.pipe(tslint({ configuration: config }))
.pipe(tslint.report("verbose"));
});
gulp.task("clean", function (callback) {
gulp.task("clean", function () {
var del = require("del");
del([binPath + "/**"], { force: true }, callback);
return del([binPath + "/**"], { force: true });
});
gulp.task("default", function (callback) {
var runSequence = require("run-sequence");
runSequence("clean", "compile", "tslint");
runSequence("clean", "compile", "tslint", callback);
});

Просмотреть файл

@ -24,6 +24,11 @@
"gulp-insert": "latest",
"gulp-tslint": "latest",
"del": "latest",
"run-sequence": "latest"
"run-sequence": "latest",
"q": "latest",
"replace": "latest",
"mkdirp": "latest",
"express": "latest",
"body-parser": "latest"
}
}

Просмотреть файл

@ -10,35 +10,35 @@
<dependency id="cordova-plugin-file" version=">=2.0.0" />
<dependency id="cordova-plugin-zip" version=">=3.0.0" />
<js-module src="bin/codePush.js" name="codePush">
<js-module src="bin/www/codePush.js" name="codePush">
<clobbers target="codePush" />
</js-module>
<js-module src="bin/localPackage.js" name="localPackage">
<js-module src="bin/www/localPackage.js" name="localPackage">
<clobbers target="LocalPackage" />
</js-module>
<js-module src="bin/remotePackage.js" name="remotePackage">
<js-module src="bin/www/remotePackage.js" name="remotePackage">
<clobbers target="RemotePackage" />
</js-module>
<js-module src="bin/codePushUtil.js" name="codePushUtil">
<js-module src="bin/www/codePushUtil.js" name="codePushUtil">
<runs/>
</js-module>
<js-module src="bin/fileUtil.js" name="fileUtil">
<js-module src="bin/www/fileUtil.js" name="fileUtil">
<runs/>
</js-module>
<js-module src="bin/httpRequester.js" name="httpRequester">
<js-module src="bin/www/httpRequester.js" name="httpRequester">
<runs/>
</js-module>
<js-module src="bin/nativeAppInfo.js" name="nativeAppInfo">
<js-module src="bin/www/nativeAppInfo.js" name="nativeAppInfo">
<runs/>
</js-module>
<js-module src="bin/package.js" name="package">
<js-module src="bin/www/package.js" name="package">
<runs/>
</js-module>

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="cordova-plugin-code-push-acquisition" version="0.0.1-dev">
<name>CodePushAcquisition</name>
<description>Code Push Acquisition Plugin for Apache Cordova</description>
<license>Apache 2.0</license>
<keywords>cordova,code,push,acquisition</keywords>
<repo>https://github.com/Microsoft/hybrid-mobile-deploy.git</repo>
<js-module src="script/acquisition-sdk.js" name="AcquisitionManager">
<merges target="window" />
</js-module>
</plugin>

Просмотреть файл

@ -0,0 +1,86 @@
/// <reference path="../definitions/harness.d.ts" />
var AcquisitionManager = (function () {
function AcquisitionManager(httpRequester, configuration) {
this._httpRequester = httpRequester;
this._serverUrl = configuration.serverUrl;
if (this._serverUrl.slice(-1) !== "/") {
this._serverUrl += "/";
}
this._deploymentKey = configuration.deploymentKey;
this._ignoreAppVersion = configuration.ignoreAppVersion;
}
AcquisitionManager.prototype.queryUpdateWithCurrentPackage = function (currentPackage, callback) {
var _this = this;
if (!currentPackage || !currentPackage.appVersion) {
throw new Error("Calling common acquisition SDK with incorrect package"); // Unexpected; indicates error in our implementation
}
var updateRequest = {
deploymentKey: this._deploymentKey,
appVersion: currentPackage.appVersion,
packageHash: currentPackage.packageHash,
isCompanion: this._ignoreAppVersion
};
var requestUrl = this._serverUrl + "updateCheck?" + queryStringify(updateRequest);
this._httpRequester.request(0 /* GET */, requestUrl, function (error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode !== 200) {
callback(new Error(response.statusCode + ": " + response.body), null);
return;
}
try {
var responseObject = JSON.parse(response.body);
var updateInfo = responseObject.updateInfo;
}
catch (error) {
callback(error, null);
return;
}
if (!updateInfo) {
callback(error, null);
return;
}
else if (updateInfo.updateAppVersion) {
callback(null, { updateAppVersion: true, appVersion: updateInfo.appVersion });
return;
}
else if (!updateInfo.isAvailable) {
callback(null, null);
return;
}
var remotePackage = {
deploymentKey: _this._deploymentKey,
description: updateInfo.description,
label: updateInfo.label,
appVersion: updateInfo.appVersion,
isMandatory: updateInfo.isMandatory,
packageHash: updateInfo.packageHash,
packageSize: updateInfo.packageSize,
downloadUrl: updateInfo.downloadURL
};
callback(null, remotePackage);
});
};
return AcquisitionManager;
})();
exports.AcquisitionManager = AcquisitionManager;
function queryStringify(object) {
var queryString = "";
var isFirst = true;
for (var property in object) {
if (object.hasOwnProperty(property)) {
var value = object[property];
if (!isFirst) {
queryString += "&";
}
queryString += encodeURIComponent(property) + "=";
if (value !== null && typeof value !== "undefined") {
queryString += encodeURIComponent(value);
}
isFirst = false;
}
}
return queryString;
}

106
test/projectManager.ts Normal file
Просмотреть файл

@ -0,0 +1,106 @@
/// <reference path="../typings/codePush.d.ts" />
/// <reference path="../typings/q.d.ts" />
/// <reference path="../typings/node.d.ts" />
/// <reference path="../typings/replace.d.ts" />
/// <reference path="../typings/mkdirp.d.ts" />
"use strict";
import child_process = require("child_process");
import replace = require("replace");
import path = require("path");
import Q = require("q");
import fs = require("fs");
import mkdirp = require("mkdirp");
var del = require("del");
/**
* In charge of Cordova project related operations.
*/
export class ProjectManager {
public static ANDROID_KEY_PLACEHOLDER: string = "CODE_PUSH_ANDROID_DEPOYMENT_KEY";
public static IOS_KEY_PLACEHOLDER: string = "CODE_PUSH_IOS_DEPLOYMENT_KEY";
public static SERVER_URL_PLACEHOLDER: string = "CODE_PUSH_SERVER_URL";
/**
* Creates a new cordova test application at the specified path, and configures it
* with the given server URL, android and ios deployment keys.
*/
public static setupTemplate(destinationPath: string, templatePath: string, serverURL: string, androidKey: string, iosKey: string, appName: string, appNamespace: string): Q.Promise<void> {
var configXmlPath = path.join(destinationPath, "config.xml");
var indexHtmlPath = path.join(destinationPath, "www/index.html");
var indexJsPath = path.join(destinationPath, "www/js/index.js");
if (fs.existsSync(destinationPath)) {
del.sync([destinationPath], { force: true });
}
mkdirp.sync(destinationPath);
return ProjectManager.execAndLogChildProcess("cordova create " + destinationPath + " " + appNamespace + " " + appName + " --copy-from " + templatePath)
.then<void>(ProjectManager.replaceString.bind(undefined, configXmlPath, ProjectManager.ANDROID_KEY_PLACEHOLDER, androidKey))
.then<void>(ProjectManager.replaceString.bind(undefined, configXmlPath, ProjectManager.IOS_KEY_PLACEHOLDER, iosKey))
.then<void>(ProjectManager.replaceString.bind(undefined, configXmlPath, ProjectManager.SERVER_URL_PLACEHOLDER, serverURL))
.then<void>(ProjectManager.replaceString.bind(undefined, indexHtmlPath, ProjectManager.SERVER_URL_PLACEHOLDER, serverURL))
.then<void>(ProjectManager.replaceString.bind(undefined, indexJsPath, ProjectManager.SERVER_URL_PLACEHOLDER, serverURL));
}
/**
* Adds a plugin to a Cordova project.
*/
public static addPlugin(projectFolder: string, plugin: string): Q.Promise<void> {
return ProjectManager.execAndLogChildProcess("cordova plugin add " + plugin, { cwd: projectFolder });
}
/**
* Adds a platform to a Cordova project.
*/
public static buildPlatform(projectFolder: string, platformName: string): Q.Promise<void> {
return ProjectManager.execAndLogChildProcess("cordova build " + platformName, { cwd: projectFolder });
}
/**
* Runs a project to a given target / platform.
*/
public static runPlatform(projectFolder: string, platformName: string, skipBuild: boolean = false, target?: string): Q.Promise<void> {
var runTarget = target ? " --target " + target : "";
var nobuild = skipBuild ? " --nobuild" : "";
return ProjectManager.execAndLogChildProcess("cordova run " + platformName + runTarget + nobuild, { cwd: projectFolder });
}
/**
* Adds a platform to a Cordova project.
*/
public static addPlatform(projectFolder: string, platformName: string): Q.Promise<void> {
return ProjectManager.execAndLogChildProcess("cordova platform add " + platformName, { cwd: projectFolder });
}
/**
* Replaces a regex in a file with a given string.
*/
public static replaceString(filePath: string, regex: string, replacement: string): void {
replace({ regex: regex, replacement: replacement, recursive: false, silent: false, paths: [filePath] });
}
/**
* Executes a child process and logs its output to the console.
*/
private static execAndLogChildProcess(command: string, options?: child_process.IExecOptions): Q.Promise<void> {
var deferred = Q.defer<void>();
child_process.exec(command, options, (error: Error, stdout: Buffer, stderr: Buffer) => {
stdout && console.log(stdout);
stderr && console.error(stderr);
if (error) {
console.error(error);
deferred.reject(error);
} else {
deferred.resolve(undefined);
}
});
return deferred.promise;
}
}

22
test/serverUtil.ts Normal file
Просмотреть файл

@ -0,0 +1,22 @@
"use strict";
/**
* Class used to mock the codePush.checkForUpdate() response from the server.
*/
export class CheckForUpdateResponseMock {
downloadURL: string;
isAvailable: boolean;
packageSize: number;
updateAppVersion: boolean;
appVersion: string;
description: string;
label: string;
packageHash: string;
isMandatory: boolean;
}
export class TestMessage {
public static CHECK_UP_TO_DATE = "CHECK_UP_TO_DATE";
public static CHECK_UPDATE_AVAILABLE = "CHECK_UPDATE_AVAILABLE";
public static CHECK_ERROR = "CHECK_ERROR";
}

42
test/template/config.xml Normal file
Просмотреть файл

@ -0,0 +1,42 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.test.codepush" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>CodePushTest</name>
<description>
A sample Apache Cordova application that is used for testing the Code Push plugin.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<!-- The contents of the main page can change between Code-Push updates, but not the name. -->
<content src="index.html" />
<plugin name="cordova-plugin-whitelist" version="1" />
<!-- This sample application can communicate with any external domain.
If you want to restrict this, don't forget to enable communication with the Code-Push server URL as well. -->
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
<!-- Code Push deployment key for the Android platform. -->
<preference name="CodePushDeploymentKey" value="CODE_PUSH_ANDROID_DEPOYMENT_KEY" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<!-- Code Push deployment key for the iOS platform. -->
<preference name="CodePushDeploymentKey" value="CODE_PUSH_IOS_DEPLOYMENT_KEY" />
</platform>
<!-- Code Push server URL. -->
<preference name="CodePushServerURL" value="CODE_PUSH_SERVER_URL" />
</widget>

Просмотреть файл

@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<!--
Customize this policy to fit your own app's needs. For more guidance, see:
https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
Some notes:
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
* Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
* Enable inline JS: add 'unsafe-inline' to default-src
* Code Push users, you need to add the Code Push server URL to the CSP's default-src
-->
<meta http-equiv="Content-Security-Policy" content="default-src CODE_PUSH_SERVER_URL 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<title>Hello World</title>
</head>
<body>
<div>
<h1>Hello, CodePush (Store Version)</h1>
<p id="deviceready">Waiting for device...</p>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var app = {
// Application Constructor
initialize: function () {
this.bindEvents();
},
bindEvents: function () {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function () {
app.receivedDeviceReady();
app.checkForUpdates();
},
// Update DOM on a Received Event
receivedDeviceReady: function () {
document.getElementById("deviceready").innerText = "Device is ready";
console.log('Received Event: deviceready');
},
checkForUpdates: function () {
console.log("Checking for updates...");
window.codePush.checkForUpdate(app.checkSuccess, app.checkError);
},
checkSuccess: function (remotePackage) {
if (!remotePackage) {
// A null remotePackage means that the server successfully responded, but there is no update available.
console.log("The application is up to date.");
app.sendTestMessage("CHECK_UP_TO_DATE");
}
else {
console.log("There is an update available. Remote package:" + JSON.stringify(remotePackage));
app.sendTestMessage("CHECK_UPDATE_AVAILABLE", [remotePackage]);
}
},
checkError: function (error) {
console.log("An error ocurred while checking for errors.");
app.sendTestMessage("CHECK_ERROR");
},
sendTestMessage: function (message, args) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "CODE_PUSH_SERVER_URL/reportTestMessage", false);
var body = JSON.stringify({ message: message, args: args });
console.log("Sending test message body: " + body);
xhr.setRequestHeader("Content-type", "application/json");
xhr.send(body);
}
};
app.initialize();

131
test/test.ts Normal file
Просмотреть файл

@ -0,0 +1,131 @@
/// <reference path="../typings/mocha.d.ts" />
/// <reference path="../typings/node.d.ts" />
/// <reference path="../typings/assert.d.ts" />
"use strict";
import tm = require("./projectManager");
import tu = require("./testUtil");
import su = require("./serverUtil");
import path = require("path");
import os = require("os");
import assert = require("assert");
var express = require("express");
var bodyparser = require("body-parser");
var templateManager = tm.ProjectManager;
var testUtil = tu.TestUtil;
var templatePath = path.join(__dirname, "../../test/template");
var acquisitionPluginPath = path.join(__dirname, "../../test/cordova-plugin-code-push-acquisition");
var thisPluginPath = path.join(__dirname, "../..");
var testRunDirectory = path.join(os.tmpdir(), "cordova-plugin-code-push", "test-run");
var serverUrl = testUtil.readMockServerName();
var targetPlatform = testUtil.readTargetPlatform();
const AndroidKey = "mock-android-deployment-key";
const IOSKey = "mock-ios-deployment-key";
const TestAppName = "TestCodePush";
const TestNamespace = "com.microsoft.codepush.test";
describe("window.codePush", function() {
this.timeout(100 * 60 * 1000);
before(() => {
console.log("\nMock server url: " + serverUrl);
console.log("Target platform: " + targetPlatform);
return templateManager.setupTemplate(testRunDirectory, templatePath, serverUrl, AndroidKey, IOSKey, TestAppName, TestNamespace)
.then<void>(templateManager.addPlatform.bind(undefined, testRunDirectory, targetPlatform))
.then<void>(templateManager.addPlugin.bind(undefined, testRunDirectory, acquisitionPluginPath))
.then<void>(templateManager.addPlugin.bind(undefined, testRunDirectory, thisPluginPath))
.then<void>(templateManager.buildPlatform.bind(undefined, testRunDirectory, targetPlatform));
});
describe("#queryUpdate", function() {
this.timeout(100 * 60 * 1000);
var app = express();
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: true }));
var mockResponse: any;
var testMessageCallback: (requestBody: any) => void;
/* clean up */
afterEach(() => {
mockResponse = undefined;
testMessageCallback = undefined;
});
app.get("/updateCheck", function(req: any, res: any) {
res.send(mockResponse);
console.log("Update check called from the app.");
});
app.post("/reportTestMessage", function(req: any, res: any) {
console.log("Application reported a test message.");
console.log("Body: " + JSON.stringify(req.body));
res.sendStatus(200);
testMessageCallback(req.body);
});
app.listen(3000);
it("should handle no update scenario", function(done) {
setTimeout(done, 100 * 60 * 1000);
var noUpdateReponse = new su.CheckForUpdateResponseMock();
noUpdateReponse.isAvailable = false;
mockResponse = { updateInfo: noUpdateReponse };
testMessageCallback = (requestBody: any) => {
assert.equal(su.TestMessage.CHECK_UP_TO_DATE, requestBody.message);
done();
};
console.log("Running project...");
templateManager.runPlatform(testRunDirectory, targetPlatform, true);
});
it("should handle update scenario", function(done) {
setTimeout(done, 100 * 60 * 1000);
var updateReponse = new su.CheckForUpdateResponseMock();
updateReponse.isAvailable = true;
updateReponse.appVersion = "1.0.0";
updateReponse.downloadURL = "http://mock.url";
updateReponse.isMandatory = true;
updateReponse.label = "update1";
updateReponse.packageHash = "12345-67890";
updateReponse.packageSize = 12345;
updateReponse.updateAppVersion = false;
mockResponse = { updateInfo: updateReponse };
testMessageCallback = (requestBody: any) => {
assert.equal(su.TestMessage.CHECK_UPDATE_AVAILABLE, requestBody.message);
done();
};
console.log("Running project...");
templateManager.runPlatform(testRunDirectory, targetPlatform, true);
});
it("should handle error during check for update scenario", function(done) {
setTimeout(done, 100 * 60 * 1000);
mockResponse = "invalid {{ json";
testMessageCallback = (requestBody: any) => {
assert.equal(su.TestMessage.CHECK_ERROR, requestBody.message);
done();
};
console.log("Running project...");
templateManager.runPlatform(testRunDirectory, targetPlatform, true);
});
});
});

43
test/testUtil.ts Normal file
Просмотреть файл

@ -0,0 +1,43 @@
/// <reference path="../typings/mocha.d.ts" />
/// <reference path="../typings/node.d.ts" />
"use strict";
export class TestUtil {
public static MOCK_SERVER_OPTION_NAME: string = "--mockserver";
public static PLATFORM_OPTION_NAME: string = "--platform";
/**
* Reads the mock Code Push server URL parameter passed to mocha.
* The mock server runs on the local machine during tests.
*/
public static readMockServerName(): string {
return TestUtil.readMochaCommandLineOption(TestUtil.MOCK_SERVER_OPTION_NAME);
}
/**
* Reads the test target platform.
*/
public static readTargetPlatform(): string {
return TestUtil.readMochaCommandLineOption(TestUtil.PLATFORM_OPTION_NAME);
}
/**
* Reads command line options passed to mocha.
*/
private static readMochaCommandLineOption(optionName: string): string {
var optionValue: string = undefined;
for (var i = 0; i < process.argv.length; i++) {
if (process.argv[i].indexOf(optionName) === 0) {
if (i + 1 < process.argv.length) {
optionValue = process.argv[i + 1];
}
break;
}
}
return optionValue;
}
}

63
typings/assert.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
// Type definitions for assert and power-assert
// Project: https://github.com/Jxck/assert
// Project: https://github.com/twada/power-assert
// Definitions by: vvakame <https://github.com/vvakame>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
// copy from assert external module in node.d.ts
declare function assert(value:any, message?:string):void;
declare module assert {
export class AssertionError implements Error {
name:string;
message:string;
actual:any;
expected:any;
operator:string;
generatedMessage:boolean;
constructor(options?:{message?: string; actual?: any; expected?: any; operator?: string; stackStartFunction?: Function});
}
export function fail(actual?:any, expected?:any, message?:string, operator?:string):void;
export function ok(value:any, message?:string):void;
export function equal(actual:any, expected:any, message?:string):void;
export function notEqual(actual:any, expected:any, message?:string):void;
export function deepEqual(actual:any, expected:any, message?:string):void;
export function notDeepEqual(acutal:any, expected:any, message?:string):void;
export function strictEqual(actual:any, expected:any, message?:string):void;
export function notStrictEqual(actual:any, expected:any, message?:string):void;
export var throws:{
(block:Function, message?:string): void;
(block:Function, error:Function, message?:string): void;
(block:Function, error:RegExp, message?:string): void;
(block:Function, error:(err:any) => boolean, message?:string): void;
};
export var doesNotThrow:{
(block:Function, message?:string): void;
(block:Function, error:Function, message?:string): void;
(block:Function, error:RegExp, message?:string): void;
(block:Function, error:(err:any) => boolean, message?:string): void;
};
export function ifError(value:any):void;
}
// duplicate to node.d.ts
// declare module "assert" {
// export = assert;
// }
// move to power-assert.d.ts. do not use this definition file.
declare module "power-assert" {
export = assert;
}

15
typings/mkdirp.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
// Type definitions for mkdirp 0.3.0
// Project: http://github.com/substack/node-mkdirp
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module 'mkdirp' {
function mkdirp(dir: string, cb: (err: any, made: string) => void): void;
function mkdirp(dir: string, flags: any, cb: (err: any, made: string) => void): void;
module mkdirp {
function sync(dir: string, flags?: any): string;
}
export = mkdirp;
}

114
typings/mocha.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,114 @@
// Type definitions for mocha 1.17.1
// Project: http://visionmedia.github.io/mocha/
// Definitions by: Kazi Manzur Rashid <https://github.com/kazimanzurrashid/>, otiai10 <https://github.com/otiai10>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
interface Mocha {
// Setup mocha with the given setting options.
setup(options: MochaSetupOptions): Mocha;
//Run tests and invoke `fn()` when complete.
run(callback?: () => void): void;
// Set reporter as function
reporter(reporter: () => void): Mocha;
// Set reporter, defaults to "dot"
reporter(reporter: string): Mocha;
// Enable growl support.
growl(): Mocha
}
interface MochaSetupOptions {
//milliseconds to wait before considering a test slow
slow?: number;
// timeout in milliseconds
timeout?: number;
// ui name "bdd", "tdd", "exports" etc
ui?: string;
//array of accepted globals
globals?: any[];
// reporter instance (function or string), defaults to `mocha.reporters.Dot`
reporter?: any;
// bail on the first test failure
bail?: Boolean;
// ignore global leaks
ignoreLeaks?: Boolean;
// grep string or regexp to filter tests with
grep?: any;
}
interface MochaDone {
(error?: Error): void;
}
declare var mocha: Mocha;
declare var describe: {
(description: string, spec: () => void): void;
only(description: string, spec: () => void): void;
skip(description: string, spec: () => void): void;
timeout(ms: number): void;
}
// alias for `describe`
declare var context: {
(contextTitle: string, spec: () => void): void;
only(contextTitle: string, spec: () => void): void;
skip(contextTitle: string, spec: () => void): void;
timeout(ms: number): void;
}
declare var it: {
(expectation: string, assertion?: () => void): void;
(expectation: string, assertion?: (done: MochaDone) => void): void;
only(expectation: string, assertion?: () => void): void;
only(expectation: string, assertion?: (done: MochaDone) => void): void;
skip(expectation: string, assertion?: () => void): void;
skip(expectation: string, assertion?: (done: MochaDone) => void): void;
timeout(ms: number): void;
};
declare function before(action: () => void): void;
declare function before(action: (done: MochaDone) => void): void;
declare function setup(action: () => void): void;
declare function setup(action: (done: MochaDone) => void): void;
declare function after(action: () => void): void;
declare function after(action: (done: MochaDone) => void): void;
declare function teardown(action: () => void): void;
declare function teardown(action: (done: MochaDone) => void): void;
declare function beforeEach(action: () => void): void;
declare function beforeEach(action: (done: MochaDone) => void): void;
declare function suiteSetup(action: () => void): void;
declare function suiteSetup(action: (done: MochaDone) => void): void;
declare function afterEach(action: () => void): void;
declare function afterEach(action: (done: MochaDone) => void): void;
declare function suiteTeardown(action: () => void): void;
declare function suiteTeardown(action: (done: MochaDone) => void): void;
declare module "mocha" {
export = undefined;
}

1343
typings/node.d.ts поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

330
typings/q.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,330 @@
// Type definitions for Q
// Project: https://github.com/kriskowal/q
// Definitions by: Barrie Nemetchek <https://github.com/bnemetchek>, Andrew Gaspar <https://github.com/AndrewGaspar/>, John Reilly <https://github.com/johnnyreilly>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/**
* If value is a Q promise, returns the promise.
* If value is a promise from another library it is coerced into a Q promise (where possible).
*/
declare function Q<T>(promise: Q.IPromise<T>): Q.Promise<T>;
/**
* If value is not a promise, returns a promise that is fulfilled with value.
*/
declare function Q<T>(value: T): Q.Promise<T>;
declare module Q {
interface IPromise<T> {
then<U>(onFulfill?: (value: T) => U | IPromise<U>, onReject?: (error: any) => U | IPromise<U>): IPromise<U>;
}
interface Deferred<T> {
promise: Promise<T>;
resolve(value: T): void;
reject(reason: any): void;
notify(value: any): void;
makeNodeResolver(): (reason: any, value: T) => void;
}
interface Promise<T> {
/**
* Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object.
* finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished.
*/
fin(finallyCallback: () => any): Promise<T>;
/**
* Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object.
* finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished.
*/
finally(finallyCallback: () => any): Promise<T>;
/**
* The then method from the Promises/A+ specification, with an additional progress handler.
*/
then<U>(onFulfill?: (value: T) => U | IPromise<U>, onReject?: (error: any) => U | IPromise<U>, onProgress?: Function): Promise<U>;
/**
* Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason.
*
* This is especially useful in conjunction with all
*/
spread<U>(onFulfill: (...args: any[]) => IPromise<U> | U, onReject?: (reason: any) => IPromise<U> | U): Promise<U>;
fail<U>(onRejected: (reason: any) => U | IPromise<U>): Promise<U>;
/**
* A sugar method, equivalent to promise.then(undefined, onRejected).
*/
catch<U>(onRejected: (reason: any) => U | IPromise<U>): Promise<U>;
/**
* A sugar method, equivalent to promise.then(undefined, undefined, onProgress).
*/
progress(onProgress: (progress: any) => any): Promise<T>;
/**
* Much like then, but with different behavior around unhandled rejection. If there is an unhandled rejection, either because promise is rejected and no onRejected callback was provided, or because onFulfilled or onRejected threw an error or returned a rejected promise, the resulting rejection reason is thrown as an exception in a future turn of the event loop.
*
* This method should be used to terminate chains of promises that will not be passed elsewhere. Since exceptions thrown in then callbacks are consumed and transformed into rejections, exceptions at the end of the chain are easy to accidentally, silently ignore. By arranging for the exception to be thrown in a future turn of the event loop, so that it won't be caught, it causes an onerror event on the browser window, or an uncaughtException event on Node.js's process object.
*
* Exceptions thrown by done will have long stack traces, if Q.longStackSupport is set to true. If Q.onerror is set, exceptions will be delivered there instead of thrown in a future turn.
*
* The Golden Rule of done vs. then usage is: either return your promise to someone else, or if the chain ends with you, call done to terminate it.
*/
done(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any, onProgress?: (progress: any) => any): void;
/**
* If callback is a function, assumes it's a Node.js-style callback, and calls it as either callback(rejectionReason) when/if promise becomes rejected, or as callback(null, fulfillmentValue) when/if promise becomes fulfilled. If callback is not a function, simply returns promise.
*/
nodeify(callback: (reason: any, value: any) => void): Promise<T>;
/**
* Returns a promise to get the named property of an object. Essentially equivalent to
*
* promise.then(function (o) {
* return o[propertyName];
* });
*/
get<U>(propertyName: String): Promise<U>;
set<U>(propertyName: String, value: any): Promise<U>;
delete<U>(propertyName: String): Promise<U>;
/**
* Returns a promise for the result of calling the named method of an object with the given array of arguments. The object itself is this in the function, just like a synchronous method call. Essentially equivalent to
*
* promise.then(function (o) {
* return o[methodName].apply(o, args);
* });
*/
post<U>(methodName: String, args: any[]): Promise<U>;
/**
* Returns a promise for the result of calling the named method of an object with the given variadic arguments. The object itself is this in the function, just like a synchronous method call.
*/
invoke<U>(methodName: String, ...args: any[]): Promise<U>;
fapply<U>(args: any[]): Promise<U>;
fcall<U>(...args: any[]): Promise<U>;
/**
* Returns a promise for an array of the property names of an object. Essentially equivalent to
*
* promise.then(function (o) {
* return Object.keys(o);
* });
*/
keys(): Promise<string[]>;
/**
* A sugar method, equivalent to promise.then(function () { return value; }).
*/
thenResolve<U>(value: U): Promise<U>;
/**
* A sugar method, equivalent to promise.then(function () { throw reason; }).
*/
thenReject(reason: any): Promise<T>;
/**
* Attaches a handler that will observe the value of the promise when it becomes fulfilled, returning a promise for that same value, perhaps deferred but not replaced by the promise returned by the onFulfilled handler.
*/
tap(onFulfilled: (value: T) => any): Promise<T>;
timeout(ms: number, message?: string): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
delay(ms: number): Promise<T>;
/**
* Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true.
*/
isFulfilled(): boolean;
/**
* Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false.
*/
isRejected(): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
isPending(): boolean;
valueOf(): any;
/**
* Returns a "state snapshot" object, which will be in one of three forms:
*
* - { state: "pending" }
* - { state: "fulfilled", value: <fulfllment value> }
* - { state: "rejected", reason: <rejection reason> }
*/
inspect(): PromiseState<T>;
}
interface PromiseState<T> {
/**
* "fulfilled", "rejected", "pending"
*/
state: string;
value?: T;
reason?: any;
}
// If no value provided, returned promise will be of void type
export function when(): Promise<void>;
// if no fulfill, reject, or progress provided, returned promise will be of same type
export function when<T>(value: T | IPromise<T>): Promise<T>;
// If a non-promise value is provided, it will not reject or progress
export function when<T, U>(value: T | IPromise<T>, onFulfilled: (val: T) => U | IPromise<U>, onRejected?: (reason: any) => U | IPromise<U>, onProgress?: (progress: any) => any): Promise<U>;
/**
* Currently "impossible" (and I use the term loosely) to implement due to TypeScript limitations as it is now.
* See: https://github.com/Microsoft/TypeScript/issues/1784 for discussion on it.
*/
// export function try(method: Function, ...args: any[]): Promise<any>;
export function fbind<T>(method: (...args: any[]) => T | IPromise<T>, ...args: any[]): (...args: any[]) => Promise<T>;
export function fcall<T>(method: (...args: any[]) => T, ...args: any[]): Promise<T>;
export function send<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function invoke<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function mcall<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function denodeify<T>(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise<T>;
export function nbind<T>(nodeFunction: Function, thisArg: any, ...args: any[]): (...args: any[]) => Promise<T>;
export function nfbind<T>(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise<T>;
export function nfcall<T>(nodeFunction: Function, ...args: any[]): Promise<T>;
export function nfapply<T>(nodeFunction: Function, args: any[]): Promise<T>;
export function ninvoke<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
export function npost<T>(nodeModule: any, functionName: string, args: any[]): Promise<T>;
export function nsend<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
export function nmcall<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<T>(promises: IPromise<T>[]): Promise<T[]>;
/**
* Returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected.
*/
export function allSettled<T>(promises: IPromise<T>[]): Promise<PromiseState<T>[]>;
export function allResolved<T>(promises: IPromise<T>[]): Promise<Promise<T>[]>;
/**
* Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason.
* This is especially useful in conjunction with all.
*/
export function spread<T, U>(promises: IPromise<T>[], onFulfilled: (...args: T[]) => U | IPromise<U>, onRejected?: (reason: any) => U | IPromise<U>): Promise<U>;
/**
* Returns a promise that will have the same result as promise, except that if promise is not fulfilled or rejected before ms milliseconds, the returned promise will be rejected with an Error with the given message. If message is not supplied, the message will be "Timed out after " + ms + " ms".
*/
export function timeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
export function delay<T>(promise: Promise<T>, ms: number): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
export function delay<T>(value: T, ms: number): Promise<T>;
/**
* Returns a promise that will be fulfilled with undefined after at least ms milliseconds have passed.
*/
export function delay(ms: number): Promise <void>;
/**
* Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true.
*/
export function isFulfilled(promise: Promise<any>): boolean;
/**
* Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false.
*/
export function isRejected(promise: Promise<any>): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
export function isPending(promise: Promise<any>): boolean;
/**
* Returns a "deferred" object with a:
* promise property
* resolve(value) method
* reject(reason) method
* notify(value) method
* makeNodeResolver() method
*/
export function defer<T>(): Deferred<T>;
/**
* Returns a promise that is rejected with reason.
*/
export function reject<T>(reason?: any): Promise<T>;
export function Promise<T>(resolver: (resolve: (val: T | IPromise<T>) => void , reject: (reason: any) => void , notify: (progress: any) => void ) => void ): Promise<T>;
/**
* Creates a new version of func that accepts any combination of promise and non-promise values, converting them to their fulfillment values before calling the original func. The returned version also always returns a promise: if func does a return or throw, then Q.promised(func) will return fulfilled or rejected promise, respectively.
*
* This can be useful for creating functions that accept either promises or non-promise values, and for ensuring that the function always returns a promise even in the face of unintentional thrown exceptions.
*/
export function promised<T>(callback: (...args: any[]) => T): (...args: any[]) => Promise<T>;
/**
* Returns whether the given value is a Q promise.
*/
export function isPromise(object: any): boolean;
/**
* Returns whether the given value is a promise (i.e. it's an object with a then function).
*/
export function isPromiseAlike(object: any): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
export function isPending(object: any): boolean;
/**
* This is an experimental tool for converting a generator function into a deferred function. This has the potential of reducing nested callbacks in engines that support yield.
*/
export function async<T>(generatorFunction: any): (...args: any[]) => Promise<T>;
export function nextTick(callback: Function): void;
/**
* A settable property that will intercept any uncaught errors that would otherwise be thrown in the next tick of the event loop, usually as a result of done. Can be useful for getting the full stack trace of an error in browsers, which is not usually possible with window.onerror.
*/
export var onerror: (reason: any) => void;
/**
* A settable property that lets you turn on long stack trace support. If turned on, "stack jumps" will be tracked across asynchronous promise operations, so that if an uncaught error is thrown by done or a rejection reason's stack property is inspected in a rejection callback, a long stack trace is produced.
*/
export var longStackSupport: boolean;
/**
* Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does).
* Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason.
* Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value.
* Calling resolve with a non-promise value causes promise to be fulfilled with that value.
*/
export function resolve<T>(object: IPromise<T>): Promise<T>;
/**
* Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does).
* Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason.
* Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value.
* Calling resolve with a non-promise value causes promise to be fulfilled with that value.
*/
export function resolve<T>(object: T): Promise<T>;
/**
* Resets the global "Q" variable to the value it has before Q was loaded.
* This will either be undefined if there was no version or the version of Q which was already loaded before.
* @returns { The last version of Q. }
*/
export function noConflict(): typeof Q;
}
declare module "q" {
export = Q;
}

13
typings/replace.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
interface ReplaceOptions {
regex: string;
replacement: string;
paths: Array<string>;
recursive: boolean;
silent: boolean;
}
declare module "replace" {
function replace(options: ReplaceOptions): void;
export = replace;
}