// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information.
//
//
///
///
//
//
declare var fragmentWithExternalScriptAndStylesLoad;
declare var findmeInternal;
declare var fcc_initialize2;
declare var fcc_fireOnchange;
declare var fcc_getCount;
declare var PageControlsDemo;
module WinJSTests {
"use strict";
function pageNavigated(e) {
// get the element where we want the fragment to load into
var content = WinJS.Utilities.query("#pageContent")[0];
WinJS.Utilities.empty(content);
// Get the fragmentControl constructor by looking up the name of the member passed via the call to navigation().
// For this to work, the control needs to be previously "defined" or loaded via WinJS.UI.Pages.define(). In this case
// it got defined by global JS code when page1.js was included at the top of this test.
var ctor = WinJS.Utilities.getMember(e.detail.location, PageControlsDemo);
// render the control into the destination element. Note the control returned from this
// constructor can also be retrieved later via contentElement.winControl.
new ctor(content);
}
export class FragmentControl {
testFragmentControlBasicRender = function (complete) {
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
WinJS.UI.Pages.render(fragfile, d).then(function () {
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("This is just a test.", rendered.textContent);
}).
then(null, Helper.unhandledTestError).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
}).
then(complete);
};
testFragmentControlBasicRenderHTMLBody = function (complete) {
var fragfile = "$(TESTDATA)/FragmentBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("span");
WinJS.UI.Pages.render(fragfile, d).then(function () {
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("This is just a test.", rendered.textContent);
}).then(null, Helper.unhandledTestError).then(complete);
};
testFragmentControlRemove = function (complete) {
// remove clears the fragment from the cache and deletes item from viewmap
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.get(fragfile);
var instance = new ctor(d);
// fragment file should be present in the cache after calling constructor
LiveUnit.Assert.isTrue(Helper.namedObjectContainsString(WinJS.UI.Fragments._cacheStore, fragfile) >= 0);
instance.elementReady.then(function (element) {
LiveUnit.Assert.isTrue(element === d);
}).
then(function () {
WinJS.UI.Pages._remove(fragfile);
// fragment file should no longer be in the cache after calling remove
LiveUnit.Assert.isFalse(Helper.namedObjectContainsString(WinJS.UI.Fragments._cacheStore, fragfile) >= 0);
}).
then(null, Helper.unhandledTestError).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
}).
then(complete);
};
testFragmentControlBasicGet = function () {
WinJS.UI.Pages._remove("$(TESTDATA)/FragmentControlBasic.html");
LiveUnit.Assert.isTrue(WinJS.UI.Pages.get("FragmentControlBasic.html") !== undefined);
};
testElementReady = function (complete) {
// verify elementReady promise returns rendered element, but processAll() + other has not been called
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.get(fragfile);
var instance = new ctor(d);
instance.elementReady.then(function (element) {
LiveUnit.Assert.isTrue(element === d);
LiveUnit.Assert.isTrue(element === instance.element);
LiveUnit.Assert.areEqual("This is just a test.", element.childNodes[0].textContent);
LiveUnit.Assert.areEqual(1, element.childNodes.length);
}).
then(null, Helper.unhandledTestError).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
}).
then(complete);
};
testFragmentControlBasicInstance = function (complete) {
// verify renderComplete promise returns rendered element
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.get(fragfile);
var instance = new ctor(d);
LiveUnit.Assert.isTrue(instance !== undefined);
LiveUnit.Assert.isTrue(instance.element === d);
LiveUnit.Assert.isTrue(instance.elementReady !== undefined);
LiveUnit.Assert.isTrue(instance.renderComplete !== undefined);
instance.renderComplete.then(function (docfrag) {
LiveUnit.Assert.areEqual(docfrag.element, d, "expected return from renderComplete to be the dest element");
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("This is just a test.", rendered.textContent);
}).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
}).
then(null, Helper.unhandledTestError).
then(complete);
};
testRenderCompleteProcessAll = function (complete) {
// verify renderComplete promise returns rendered element and that processAll() has been called
var fragfile = "$(TESTDATA)/FragmentControlCombo.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
document.body.appendChild(d);
var ctor = WinJS.UI.Pages.get(fragfile);
var instance = new ctor(d);
LiveUnit.Assert.isTrue(instance !== undefined);
LiveUnit.Assert.isTrue(instance.element === d);
LiveUnit.Assert.isTrue(instance.elementReady !== undefined);
LiveUnit.Assert.isTrue(instance.renderComplete !== undefined);
instance.renderComplete.then(function () {
// initialize the loaded fragment contents which looks for fragment elements that were just appended to the document
fcc_initialize2();
LiveUnit.Assert.areEqual(1, fcc_getCount(), "expecting count == 1 after renderComplete()");
// make sure standard control events work
LiveUnit.Assert.isNotNull(document.getElementById('fcc_testSelect'));
fcc_fireOnchange(document.getElementById('fcc_testSelect'));
LiveUnit.Assert.areEqual(2, fcc_getCount(), "expecting count == 2 after firing testSelect onchange");
// make sure WinJS control events work
var datepicker = document.getElementById("datepicker");
LiveUnit.Assert.isNotNull(datepicker.querySelector('.win-datepicker-month'), "unable to query for month element");
fcc_fireOnchange(datepicker.querySelector('.win-datepicker-month'));
LiveUnit.Assert.areEqual(3, fcc_getCount(), "expecting count == 3 after firing onchange for month element");
}).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
WinJS.Utilities.disposeSubTree(d);
document.body.removeChild(d);
}).
then(null, Helper.unhandledTestError).
then(complete);
};
testEmbeddedJSCSS = function (complete) {
// load fragment with embedded JS and CSS, call fragment JS function, validate CSS
var fragfile = "$(TESTDATA)/FragmentFindmeInternal.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
document.body.appendChild(d);
WinJS.UI.Pages.render(fragfile, d).
then(function (docfrag) {
LiveUnit.Assert.isTrue(docfrag !== undefined, "expecting rendered fragment returned from render");
LiveUnit.Assert.isTrue(docfrag.element === d);
// call JS that got loaded up with the fragment
var x = findmeInternal();
LiveUnit.Assert.isTrue(x.id, "findmeInternal");
// make sure CSS was applied
Helper.Assert.areColorsEqual("rgb(255, 0, 0)", getComputedStyle(x).color);
}).
then(null, Helper.unhandledTestError).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
WinJS.Utilities.disposeSubTree(d);
document.body.removeChild(d);
}).
then(complete);
}
testExternalJSCSS = function (complete) {
// load fragment with links to external JS and CSS, call fragment JS function, validate CSS
var fragfile = "$(TESTDATA)/FragmentWithExternalScriptAndStyles.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
document.body.appendChild(d);
WinJS.UI.Pages.render(fragfile, d).
then(function (docfrag) {
LiveUnit.Assert.isTrue(docfrag !== undefined, "expecting rendered fragment returned from render");
LiveUnit.Assert.isTrue(docfrag.element === d);
// call JS that got loaded up with the fragment
fragmentWithExternalScriptAndStylesLoad(docfrag.element);
LiveUnit.Assert.areEqual(1, document.head.querySelectorAll("[data-magic='testFragmentWithExternalScriptAndStyles']").length, "should have cloned the custom attribute on style");
LiveUnit.Assert.areEqual(4, d.children.length, "Missing expected child");
// verify CSS was applied
return WinJS.Promise.timeout(500).then(function () {
Helper.Assert.areColorsEqual("rgb(255, 0, 0)", getComputedStyle(d.children[3]).backgroundColor, "Referenced style should have been applied and colored the generated element");
LiveUnit.Assert.areEqual("hit", d.children[3].textContent, "Loaded script should have run and updated the body for the generated element");
});
}).
then(null, Helper.unhandledTestError).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
WinJS.Utilities.disposeSubTree(d);
document.body.removeChild(d);
}).
then(complete);
}
testEventOrdering = function (complete) {
var fragfile = "foo";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.define(fragfile, {
load: function (uri) {
LiveUnit.Assert.areEqual(0, options.stage);
options.stage++;
return "Some load result";
},
init: function (element, options) {
LiveUnit.Assert.areEqual(1, options.stage);
options.stage++;
},
render: function (element, options, loadResult) {
LiveUnit.Assert.areEqual(2, options.stage);
LiveUnit.Assert.areEqual("Some load result", loadResult);
options.stage++;
var content = document.createElement("div");
content.textContent = "hit";
element.appendChild(content);
return content;
},
processed: function (element, options) {
LiveUnit.Assert.areEqual(3, options.stage);
options.stage++;
},
ready: function (element, options) {
LiveUnit.Assert.areEqual(4, options.stage);
options.stage++;
}
});
var options = { stage: 0 };
var instance = new ctor(d, options);
LiveUnit.Assert.isTrue(instance !== undefined);
LiveUnit.Assert.isTrue(instance.element === d);
LiveUnit.Assert.isTrue(instance.elementReady !== undefined);
LiveUnit.Assert.isTrue(instance.renderComplete !== undefined);
instance.renderComplete.then(function () {
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("hit", rendered.textContent);
LiveUnit.Assert.areEqual(5, options.stage);
}).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
}).
then(null, Helper.unhandledTestError).
then(complete);
};
testErrorOrdering = function (complete) {
var options = { stage: 0 };
var fragfile = "foo";
var stageError = 45;
var err = -1;
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.define(fragfile, {
load: function (uri) {
LiveUnit.Assert.areEqual(0, options.stage);
if (options.stage === stageError) {
throw options.stage;
}
if (options.stage > stageError) {
LiveUnit.Assert.fail("error should have occured earlier and not propogated");
}
options.stage++;
return "Some load result";
},
init: function (element, options) {
LiveUnit.Assert.areEqual(1, options.stage);
if (options.stage === stageError) {
throw options.stage;
}
if (options.stage > stageError) {
LiveUnit.Assert.fail("error should have occured earlier and not propogated");
}
options.stage++;
},
render: function (element, options, loadResult) {
LiveUnit.Assert.areEqual(2, options.stage);
LiveUnit.Assert.areEqual("Some load result", loadResult);
if (options.stage === stageError) {
throw options.stage;
}
if (options.stage > stageError) {
LiveUnit.Assert.fail("error should have occured earlier and not propogated");
}
options.stage++;
var content = document.createElement("div");
content.textContent = "hit";
element.appendChild(content);
return content;
},
processed: function (element, options) {
LiveUnit.Assert.areEqual(3, options.stage);
if (options.stage === stageError) {
throw options.stage;
}
if (options.stage > stageError) {
LiveUnit.Assert.fail("error should have occured earlier and not propogated");
}
options.stage++;
},
ready: function (element, options) {
LiveUnit.Assert.areEqual(4, options.stage);
if (options.stage === stageError) {
throw options.stage;
}
if (options.stage > stageError) {
LiveUnit.Assert.fail("error should have occured earlier and not propogated");
}
options.stage++;
},
error: function (e) {
LiveUnit.Assert.isFalse(err >= 0, "error handler should only be called once");
LiveUnit.Assert.areEqual(stageError, e, "expected failure in appropriate stage");
err = e;
// "recover" by not returning error
}
});
function allStages() {
options = { stage: 0 };
stageError = 5;
var instance = new ctor(d, options);
LiveUnit.Assert.isTrue(instance !== undefined);
LiveUnit.Assert.isTrue(instance.element === d);
LiveUnit.Assert.isTrue(instance.elementReady !== undefined);
LiveUnit.Assert.isTrue(instance.renderComplete !== undefined);
return instance.renderComplete.then(function () {
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("hit", rendered.textContent);
LiveUnit.Assert.areEqual(5, options.stage);
}).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
}).
then(null, Helper.unhandledTestError);
}
function failStage(num) {
options = { stage: 0 };
stageError = num;
err = -1;
var instance = new ctor(d, options);
return instance.renderComplete.then(function () {
LiveUnit.Assert.areEqual(stageError, options.stage, "should have only completed up to the error stage");
}).
then(null, function (e) {
LiveUnit.Assert.areEqual(stageError, e, "expected failure in appropriate stage");
}).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
}).
then(null, Helper.unhandledTestError);
}
allStages().then(function () {
return failStage(0);
}).then(function () {
return failStage(1);
}).then(function () {
return failStage(2);
}).then(function () {
return failStage(3);
}).then(function () {
return failStage(4);
}).then(function () {
complete();
});
};
testSelfHost = function (complete) {
var fragfile = "$(TESTDATA)/FragmentControlSelfHost.html";
WinJS.UI.Pages._remove(fragfile);
var iframe = document.createElement("iframe");
var signal;
var listener = function (m) {
if (m.data === "FragmentControlSelfHost_ready:true") {
signal(true);
} else if (m.data === "FragmentControlSelfHost_ready:false") {
LiveUnit.Assert.fail("Should not reach here!");
}
}
var cleanup = function () {
window.removeEventListener("message", listener);
document.body.removeChild(iframe);
}
WinJS.Promise.timeout(5000, new WinJS.Promise(function (c) { signal = c; }))
.then(
function (result) {
LiveUnit.Assert.isTrue(result, "Should have recieved a message from the self-hosted fragment in the iframe");
},
function () {
LiveUnit.Assert.fail("Should not get here");
}
)
.then(null, Helper.unhandledTestError)
.then(cleanup)
.then(complete);
window.addEventListener("message", listener);
document.body.appendChild(iframe);
iframe.src = fragfile;
}
testSelfHostDocumentRunsWhenNotSelfHosted = function (complete) {
// load fragment with links to external JS and CSS, call fragment JS function, validate CSS
var fragfile = "$(TESTDATA)/FragmentControlNotSelfHost.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
document.body.appendChild(d);
WinJS.UI.Pages.render(fragfile, d).
then(function (control: any) {
LiveUnit.Assert.isTrue(control !== undefined, "expecting rendered fragment returned from render");
LiveUnit.Assert.isTrue(control.element === d);
LiveUnit.Assert.isFalse(control.selfhost);
LiveUnit.Assert.isTrue(control.runWithoutSelfHost);
}).
then(null, Helper.unhandledTestError).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(fragfile);
WinJS.Utilities.disposeSubTree(d);
document.body.removeChild(d);
}).
then(complete);
}
xtestPageControlScenario1 = function (complete) {
// bug#522041 scripts get loaded twice if script tags differ by '\' or '/'
// emulate usage scenario utilized in VS Templates
WinJS.UI.Pages._remove("Page1");
WinJS.Navigation.history = {};
var contentElement = document.createElement("div");
contentElement.setAttribute("id", "pageContent");
document.body.appendChild(contentElement);
WinJS.Navigation.addEventListener("navigated", pageNavigated);
// pass the name of the Control to navigation.
// Note: "Page1" is the member name inside the PageControlsDemo namespace defined by page1.js when it was
// included at the top of this test
WinJS.Navigation.navigate("Page1").
then(function (navigationSuccess) {
LiveUnit.Assert.isTrue(navigationSuccess, "navigate(Page1) returned false");
// get the control that's been inserted into our content element
var pageControl = contentElement.winControl;
LiveUnit.Assert.isTrue(pageControl !== undefined, "pageControl is undefined");
// wait for the control to finish rendering, then verify content has been added to DOM
pageControl.renderComplete.then(function (fragment) {
// now we should have navigated to Page1
LiveUnit.Assert.isTrue(fragment.element.id == "pageContent", "expecting fragment.element.id == pageContent");
// verify content from page1.html is on the page
var page1Content = WinJS.Utilities.query(".page1")[0];
LiveUnit.Assert.isTrue(page1Content !== undefined);
}).
then(null, Helper.unhandledTestError).
then(function () {
// clean up after the test
WinJS.UI.Pages._remove(contentElement);
WinJS.Navigation.history = {};
WinJS.Navigation.removeEventListener("navigated", pageNavigated, true);
}).
then(complete);
});
};
testRenderSetsWinControlOnHostElement = function (complete) {
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
WinJS.UI.Pages.render(fragfile, d).then(function () {
var rendered = d.firstElementChild;
LiveUnit.Assert.areEqual("This is just a test.", rendered.textContent);
LiveUnit.Assert.isTrue(d.winControl !== undefined);
}).
then(null, Helper.unhandledTestError).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
}).
then(complete);
};
testNewInstanceSetsWinControlOnHostElement = function () {
var fragfile = "$(TESTDATA)/FragmentControlBasic.html";
WinJS.UI.Pages._remove(fragfile);
var d = document.createElement("div");
var ctor = WinJS.UI.Pages.get(fragfile);
var instance = new ctor(d);
LiveUnit.Assert.isTrue(d.winControl !== undefined);
LiveUnit.Assert.areEqual(instance, d.winControl);
};
testDisposePageControl = function (complete) {
var fragfile = "$(TESTDATA)/FragmentForDisposeTests.html";
WinJS.UI.Pages._remove(fragfile);
WinJS.UI.Pages.render(fragfile).then(function (page: any) {
var count = 0;
var disposeElement = page.element.querySelector("#dispose");
for (var i = 0; i < disposeElement.children.length; i++) {
WinJS.Utilities.markDisposable(disposeElement.children[i], function () { count++ });
}
LiveUnit.Assert.isNotNull(page.dispose);
page.dispose();
LiveUnit.Assert.areEqual(disposeElement.children.length, count);
WinJS.UI.Pages.render(fragfile).then(function (page2: any) {
LiveUnit.Assert.isFalse(page == page2);
LiveUnit.Assert.isFalse(page2._disposed);
complete();
});
});
};
testOverridePagePolicy = function () {
var pageUri = "";
WinJS.UI.Pages._remove(pageUri);
var customLoad = function () { };
var Page = WinJS.UI.Pages.define(pageUri, {
load: customLoad
});
LiveUnit.Assert.areEqual(customLoad, Page.prototype.load);
Page = WinJS.UI.Pages.define(pageUri, {
process: function () { }
});
LiveUnit.Assert.areEqual(customLoad, Page.prototype.load);
};
testHandleRenderErrors = function (complete) {
var fragfile = "";
WinJS.UI.Pages._remove(fragfile);
var errorHandled = false;
var d = document.createElement("div");
WinJS.UI.Pages.render(fragfile, d).then(null, function(err) {
return err.page.readyComplete;
}).
then(null, function(err) {
errorHandled = true;
}).
then(function () {
// cleanup
WinJS.UI.Pages._remove(fragfile);
LiveUnit.Assert.isTrue(errorHandled);
}).
then(complete);
};
};
}
LiveUnit.registerTestClass("WinJSTests.FragmentControl");