playfab-sdk
Version:
Playfab SDK for node.js applications
481 lines (480 loc) • 23.6 kB
JavaScript
;
// Make typescript aware of nodeunit
Object.defineProperty(exports, "__esModule", { value: true });
var pf = require("../index");
var reporter = require("./reporter");
var nodeunit = require("nodeunit");
var fs = require("fs");
var PlayFab = pf.PlayFab;
var PlayFabAdmin = pf.PlayFabAdmin;
var PlayFabClient = pf.PlayFabClient;
var PlayFabServer = pf.PlayFabServer;
var PlayFabAuthentication = pf.PlayFabAuthentication;
var PlayFabCloudScript = pf.PlayFabCloudScript;
var PlayFabData = pf.PlayFabData;
var PlayFabEconomy = pf.PlayFabEconomy;
var PlayFabEvents = pf.PlayFabEvents;
var PlayFabExperimentation = pf.PlayFabExperimentation;
var PlayFabInsights = pf.PlayFabInsights;
var PlayFabGroups = pf.PlayFabGroups;
var PlayFabProgression = pf.PlayFabProgression;
var PlayFabLocalization = pf.PlayFabLocalization;
var PlayFabMultiplayer = pf.PlayFabMultiplayer;
var PlayFabProfiles = pf.PlayFabProfiles;
var PlayFabAddon = pf.PlayFabAddon;
var titleData = {
// You can set default values for testing here
// Or you can provide the same structure in a json-file and load with LoadTitleData
titleId: "",
developerSecretKey: "",
userEmail: "",
};
var testConstants = {
TEST_KEY: "testCounter",
TEST_STAT_NAME: "str",
};
var testData = {
entityId: "",
entityType: "",
playFabId: "",
testNumber: 0,
};
function TestWrapper(testFunc) {
// The purpose of this TestWrapper is to report tests as failures when they throw exceptions.
// It's pretty disappointing that this isn't part of the testing library
return function (test) {
try {
testFunc(test);
}
catch (e) {
test.ok(false, "Exception thrown during test: " + e.toString() + "\n" + e.stack);
test.done(); // This is required to display the error above, and abort the test
}
};
}
function CallbackWrapper(callbackName, callback, test) {
// Wrap PlayFab result callbacks so that exceptions in callbacks report into the test as failures
// This is is specific to catching exceptions in the PlayFab callbacks, since they're async,
// they don't share the same stacktrace as the function that calls them
return function (error, result) {
try {
callback(error, result);
}
catch (e) {
test.ok(false, "Exception thrown during " + callbackName + " callback: " + e.toString() + "\n" + e.stack);
test.done(); // This is required to display the error above, and abort the test
}
};
}
function SimpleCallbackWrapper(callbackName, callback, test) {
// Wrap no-parameter callbacks so that exceptions in callbacks report into the test as failures
// This is is specific to catching exceptions in the PlayFab callbacks, since they're async,
// they don't share the same stacktrace as the function that calls them
return function () {
try {
callback();
}
catch (e) {
test.ok(false, "Exception thrown during " + callbackName + " callback: " + e.toString() + "\n" + e.stack);
test.done(); // This is required to display the error above, and abort the test
}
};
}
function VerifyNullError(result, error, test, message) {
var success = result !== null && error == null;
if (error != null) {
test.ok(false, "PlayFab error message: " + CompileErrorReport(error));
}
else {
test.ok(success, message);
}
}
function CompileErrorReport(error) {
if (error == null)
return "";
var fullErrors = error.errorMessage;
for (var paramName in error.errorDetails) {
for (var msgIdx in error.errorDetails[paramName]) {
fullErrors += "\n" + paramName + ": " + error.errorDetails[paramName][msgIdx];
}
}
return fullErrors;
}
exports.PlayFabApiTests = {
setUp: function (callback) {
var filename = process.env.PF_TEST_TITLE_DATA_JSON; // Set the PF_TEST_TITLE_DATA_JSON env-var to the path of a testTitleData.json file (described here: https://github.com/PlayFab/SDKGenerator/blob/master/JenkinsConsoleUtility/testTitleData.md)
if (!filename)
throw new Error("testTitleData.json file location not defined.");
var prefix = "testTitleData=";
for (var arg in process.argv) {
if (arg.toLowerCase().indexOf(prefix) === 0) {
filename = arg.substr(prefix.length, arg.length - prefix.length);
}
}
if (filename != null && fs.existsSync(filename)) {
var inputTitleData = require(filename);
// All of these must exist for the titleData load to be successful
var titleDataValid = inputTitleData.hasOwnProperty("titleId") && inputTitleData.hasOwnProperty("developerSecretKey") && inputTitleData.hasOwnProperty("userEmail");
if (titleDataValid) {
titleData = inputTitleData;
}
else {
console.log("testTitleData input file did not parse correctly");
}
}
PlayFab.settings.titleId = titleData.titleId;
PlayFab.settings.developerSecretKey = titleData.developerSecretKey;
callback();
},
tearDown: function (callback) {
callback();
},
/// <summary>
/// CLIENT API
/// Try to deliberately log in with an inappropriate password,
/// and verify that the error displays as expected.
/// </summary>
InvalidLogin: TestWrapper(function (test) {
var invalidRequest = {
Email: titleData.userEmail,
Password: "INVALID",
};
var invalidLoginCallback = function (error, result) {
test.ok(result == null, "Login should have failed");
test.ok(error != null, "Login should have failed");
if (error != null) {
test.ok(error.errorMessage.toLowerCase().indexOf("password") > -1, error.errorMessage);
}
test.done();
};
PlayFabClient.LoginWithEmailAddress(invalidRequest, CallbackWrapper("invalidLoginCallback", invalidLoginCallback, test));
}),
/// <summary>
/// CLIENT API
/// Try to deliberately register a user with an invalid email and password
/// Verify that errorDetails are populated correctly.
/// </summary>
InvalidRegistration: TestWrapper(function (test) {
var invalidRequest = {
Username: "x",
Email: "x",
Password: "x",
};
var registerCallback = function (error, result) {
test.ok(result == null, "InvalidRegistration should have failed");
test.ok(error != null, "InvalidRegistration should have failed");
var expectedEmailMsg = "email address is not valid.";
var expectedPasswordMsg = "password must be between";
var errorReport = CompileErrorReport(error);
test.ok(errorReport.toLowerCase().indexOf(expectedEmailMsg) > -1, "Expect errorMessage about invalid email: " + errorReport);
test.ok(errorReport.toLowerCase().indexOf(expectedPasswordMsg) > -1, "Expect errorMessage about invalid password: " + errorReport);
test.done();
};
PlayFabClient.RegisterPlayFabUser(invalidRequest, CallbackWrapper("registerCallback", registerCallback, test));
}),
/// <summary>
/// CLIENT API
/// Log in or create a user, track their PlayFabId
/// </summary>
LoginOrRegister: TestWrapper(function (test) {
var loginRequest = {
CustomId: PlayFab.buildIdentifier,
CreateAccount: true,
};
var loginCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing Valid login result");
test.ok(PlayFabClient.IsClientLoggedIn(), "Testing Login credentials cache");
testData.playFabId = result.data.PlayFabId; // Save the PlayFabId, it will be used in other tests
test.done();
};
PlayFabClient.LoginWithCustomID(loginRequest, CallbackWrapper("loginCallback", loginCallback, test));
}),
/// <summary>
/// CLIENT API
/// Test a sequence of calls that modifies saved data,
/// and verifies that the next sequential API call contains updated data.
/// Verify that the data is correctly modified on the next call.
/// Parameter types tested: string, Dictionary<string, string>, DateTime
/// </summary>
UserDataApi: TestWrapper(function (test) {
var getDataRequest = {}; // null also works
var getDataCallback2 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetUserData result");
test.ok(result.data.Data != null, "GetUserData failed");
test.ok(result.data.Data.hasOwnProperty(testConstants.TEST_KEY), "GetUserData failed");
var actualtestNumber = parseInt(result.data.Data[testConstants.TEST_KEY].Value, 10);
var actualTimeStamp = new Date(result.data.Data[testConstants.TEST_KEY].LastUpdated).getTime();
test.equal(testData.testNumber, actualtestNumber, "" + testData.testNumber + "!=" + actualtestNumber);
var now = Date.now();
var testMin = now - 1000 * 60 * 5;
var testMax = now + 1000 * 60 * 5;
test.ok(testMin <= actualTimeStamp && actualTimeStamp <= testMax);
test.done();
};
var updateDataCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing UpdateUserData result");
PlayFabClient.GetUserData(getDataRequest, CallbackWrapper("getDataCallback2", getDataCallback2, test));
};
var getDataCallback1 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetUserData result");
test.ok(result.data.Data != null, "GetUserData failed");
var hasData = result.data.Data.hasOwnProperty(testConstants.TEST_KEY);
testData.testNumber = !hasData ? 1 : parseInt(result.data.Data[testConstants.TEST_KEY].Value, 10);
testData.testNumber = (testData.testNumber + 1) % 100; // This test is about the expected value changing - but not testing more complicated issues like bounds
var updateDataRequest = {};
updateDataRequest.Data = {};
updateDataRequest.Data[testConstants.TEST_KEY] = testData.testNumber.toString();
PlayFabClient.UpdateUserData(updateDataRequest, CallbackWrapper("updateDataCallback", updateDataCallback, test));
};
// Kick off this test process
PlayFabClient.GetUserData(getDataRequest, CallbackWrapper("updateDataCallback", getDataCallback1, test));
}),
/// <summary>
/// CLIENT API
/// Test a sequence of calls that modifies saved data,
/// and verifies that the next sequential API call contains updated data.
/// Verify that the data is saved correctly, and that specific types are tested
/// Parameter types tested: Dictionary<string, int>
/// </summary>
PlayerStatisticsApi: TestWrapper(function (test) {
var getStatsRequest = {}; // null also works
var getStatsCallback2 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetPlayerStats result");
test.ok(result.data.Statistics != null, "GetPlayerStats failed");
var actualtestNumber = -1000;
for (var _i = 0, _a = result.data.Statistics; _i < _a.length; _i++) {
var eachStat = _a[_i];
if (eachStat.StatisticName === testConstants.TEST_STAT_NAME) {
actualtestNumber = eachStat.Value;
}
}
test.equal(testData.testNumber, actualtestNumber, "" + testData.testNumber + "!=" + actualtestNumber);
test.done();
};
var updateStatsCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing UpdatePlayerStats result");
PlayFabClient.GetPlayerStatistics(getStatsRequest, CallbackWrapper("getStatsCallback2", getStatsCallback2, test));
};
var getStatsCallback1 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetPlayerStats result");
test.ok(result.data.Statistics != null, "GetPlayerStats failed");
testData.testNumber = 0;
for (var _i = 0, _a = result.data.Statistics; _i < _a.length; _i++) {
var eachStat = _a[_i];
if (eachStat.StatisticName === testConstants.TEST_STAT_NAME) {
testData.testNumber = eachStat.Value;
}
}
testData.testNumber = (testData.testNumber + 1) % 100; // This test is about the expected value changing - but not testing more complicated issues like bounds
var updateStatsRequest = {
Statistics: [
{
StatisticName: testConstants.TEST_STAT_NAME,
Value: testData.testNumber,
},
],
};
PlayFabClient.UpdatePlayerStatistics(updateStatsRequest, CallbackWrapper("updateStatsCallback", updateStatsCallback, test));
};
// Kick off this test process
PlayFabClient.GetPlayerStatistics(getStatsRequest, CallbackWrapper("getStatsCallback1", getStatsCallback1, test));
}),
/// <summary>
/// SERVER API
/// Get or create the given test character for the given user
/// Parameter types tested: Contained-Classes, string
/// </summary>
UserCharacter: TestWrapper(function (test) {
var getCharsCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing GetChars result");
test.done();
};
var getCharsRequest = {};
PlayFabClient.GetAllUsersCharacters(getCharsRequest, CallbackWrapper("getCharsCallback", getCharsCallback, test));
}),
/// <summary>
/// CLIENT AND SERVER API
/// Test that leaderboard results can be requested
/// Parameter types tested: List of contained-classes
/// </summary>
LeaderBoard: TestWrapper(function (test) {
var clientRequest = {
MaxResultsCount: 3,
StartPosition: 0,
StatisticName: testConstants.TEST_STAT_NAME,
};
var serverRequest = {
MaxResultsCount: 3,
StartPosition: 0,
StatisticName: testConstants.TEST_STAT_NAME,
};
var callsCompleted = 0;
var getLeaderboardCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing GetLeaderboard result");
if (result != null) {
test.ok(result.data.Leaderboard != null, "GetLeaderboard failed");
test.ok(result.data.Leaderboard.length > 0, "Leaderboard had insufficient entries");
}
callsCompleted += 1;
if (callsCompleted === 2)
test.done();
};
PlayFabClient.GetLeaderboard(clientRequest, CallbackWrapper("getLeaderboardCallback", getLeaderboardCallback, test));
PlayFabServer.GetLeaderboard(serverRequest, CallbackWrapper("getLeaderboardCallback", getLeaderboardCallback, test));
}),
/// <summary>
/// CLIENT API
/// Test that AccountInfo can be requested
/// Parameter types tested: List of enum-as-strings converted to list of enums
/// </summary>
AccountInfo: TestWrapper(function (test) {
var getAccountInfoCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing GetAccountInfo result");
test.ok(result.data.AccountInfo != null, "GetAccountInfo failed");
test.ok(result.data.AccountInfo.TitleInfo != null, "GetAccountInfo failed");
test.ok(result.data.AccountInfo.TitleInfo.Origination != null, "GetAccountInfo failed");
test.ok(result.data.AccountInfo.TitleInfo.Origination.length > 0, "GetAccountInfo string-Enum failed");
test.done();
};
PlayFabClient.GetAccountInfo({}, CallbackWrapper("getAccountInfoCallback", getAccountInfoCallback, test));
}),
/// <summary>
/// CLIENT API
/// Test that CloudScript can be properly set up and invoked
/// </summary>
CloudScript: TestWrapper(function (test) {
var helloWorldRequest = {
FunctionName: "helloWorld",
};
var helloWorldCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing HelloWorld result");
if (result != null) {
test.ok(result.data.FunctionResult != null, "HelloWorld failed");
test.ok(result.data.FunctionResult.messageValue != null, "HelloWorld failed");
test.equal(result.data.FunctionResult.messageValue, "Hello " + testData.playFabId + "!", "Unexpected HelloWorld cloudscript result: " + result.data.FunctionResult.messageValue);
}
test.done();
};
PlayFabClient.ExecuteCloudScript(helloWorldRequest, CallbackWrapper("helloWorldCallback", helloWorldCallback, test));
}),
/// <summary>
/// CLIENT API
/// Test that CloudScript errors can be deciphered
/// </summary>
CloudScriptError: TestWrapper(function (test) {
var errRequest = {
FunctionName: "throwError",
};
var errCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing Cloud Script Error result");
if (result != null) {
test.ok(result.data.FunctionResult == null, "Cloud Script Error failed");
test.ok(result.data.Error != null, "Cloud Script Error failed");
test.equal(result.data.Error.Error, "JavascriptException", "Cloud Script Error failed");
}
test.done();
};
PlayFabClient.ExecuteCloudScript(errRequest, CallbackWrapper("errCallback", errCallback, test));
}),
/// <summary>
/// CLIENT API
/// Test that the client can publish custom PlayStream events
/// </summary>
WriteEvent: TestWrapper(function (test) {
var writeEventRequest = {
EventName: "ForumPostEvent",
Body: {
Subject: "My First Post",
Body: "This is my awesome post.",
},
};
var writeEventCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing WriteEvent result");
test.done();
};
PlayFabClient.WritePlayerEvent(writeEventRequest, CallbackWrapper("writeEventCallback", writeEventCallback, test));
}),
/// <summary>
/// ENTITY API
/// Verify that a client login can be converted into an entity token
/// </summary>
GetEntityToken: TestWrapper(function (test) {
var getEntityTokenCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing GetEntityToken result");
test.ok(result.data.Entity.Id, "EntityId should be defined");
test.ok(result.data.Entity.Type, "entityType should be defined");
testData.entityId = result.data.Entity.Id; // Save the Entity info, it will be used in other tests
testData.entityType = result.data.Entity.Type; // Save the Entity info, it will be used in other tests
test.done();
};
PlayFabAuthentication.GetEntityToken(null, CallbackWrapper("getEntityTokenCallback", getEntityTokenCallback, test));
}),
/// <summary>
/// ENTITY API
/// Test a sequence of calls that modifies entity objects,
/// and verifies that the next sequential API call contains updated information.
/// Verify that the object is correctly modified on the next call.
/// </summary>
ObjectApi: TestWrapper(function (test) {
var getObjectsRequest = {
Entity: {
Id: testData.entityId,
Type: testData.entityType,
},
EscapeObject: true,
};
var getObjCallback2 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetObjects result");
test.ok(result.data.Objects, "GetObjects failed");
test.ok(result.data.Objects.hasOwnProperty(testConstants.TEST_KEY));
var actualtestNumber = parseInt(result.data.Objects[testConstants.TEST_KEY].EscapedDataObject, 10);
test.equal(testData.testNumber, actualtestNumber, "" + testData.testNumber + " !== " + actualtestNumber);
test.done();
};
var setObjCallback = function (error, result) {
VerifyNullError(result, error, test, "Testing SetObjects result");
PlayFabData.GetObjects(getObjectsRequest, CallbackWrapper("getObjCallback2", getObjCallback2, test));
};
var getObjCallback1 = function (error, result) {
VerifyNullError(result, error, test, "Testing GetObjects result");
testData.testNumber = 0;
if (result.data.Objects && result.data.Objects.hasOwnProperty(testConstants.TEST_KEY)) {
testData.testNumber = parseInt(result.data.Objects[testConstants.TEST_KEY].EscapedDataObject, 10);
}
testData.testNumber = (testData.testNumber + 1) % 100; // This test is about the expected value changing - but not testing more complicated issues like bounds
var setObjRequest = {
Entity: {
Id: testData.entityId,
Type: testData.entityType,
},
Objects: [
{
ObjectName: testConstants.TEST_KEY,
DataObject: testData.testNumber,
},
],
};
PlayFabData.SetObjects(setObjRequest, CallbackWrapper("setObjCallback", setObjCallback, test));
};
// Kick off this test process
PlayFabData.GetObjects(getObjectsRequest, CallbackWrapper("getObjCallback1", getObjCallback1, test));
}),
};
nodeunit.on("complete", function () {
reporter.PfTestReport[0].name = PlayFab.buildIdentifier;
var saveResultsRequest = {
FunctionName: "SaveTestData",
FunctionParameter: {
customId: PlayFab.buildIdentifier,
testReport: reporter.PfTestReport,
},
GeneratePlayStreamEvent: true,
};
if (PlayFabClient.IsClientLoggedIn()) {
PlayFabClient.ExecuteCloudScript(saveResultsRequest, null);
console.log(testData.playFabId, ", Test report saved to CloudScript: ", PlayFab.buildIdentifier); // , "\n", JSON.stringify(reporter.PfTestReport, null, 4));
}
else {
console.log(testData.playFabId, ", Failed to save test report to CloudScript: ", PlayFab.buildIdentifier); // , "\n", JSON.stringify(reporter.PfTestReport, null, 4));
}
});