UNPKG

playfab-sdk

Version:

Playfab SDK for node.js applications

481 lines (480 loc) 23.6 kB
"use strict"; // 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)); } });