afterNavigate = function(evt) {
					calls.push(evt.getParameter("toId"));
					if (calls.length === 6) {
						fnResolve();
					}
					Log.info("afterNavigate with toId: " + evt.getParameter("toId"));
				}
START OF TESTS ***

	QUnit.module("Initial");

	QUnit.test("NavContainer rendered", function(assert) {

		assert.equal(window.mPage1EventLog.beforeFirstShow, 1, "Lifecycle event invocation count page1 beforeFirstShow should be correct");
		assert.equal(window.mPage1EventLog.beforeShow, 1, "Lifecycle event invocation count page1 beforeShow should be correct");
		assert.equal(window.mPage1EventLog.afterShow, 1, "Lifecycle event invocation count page1 afterShow should be correct");
		assert.equal(window.mPage1EventLog.beforeHide, 0, "Lifecycle event invocation count page1 beforeHide should be correct");
		assert.equal(window.mPage1EventLog.afterHide, 0, "Lifecycle event invocation count page1 afterHide should be correct");

		assert.equal(window.mPage2EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page2 beforeFirstShow should be correct");
		assert.equal(window.mPage2EventLog.beforeShow, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterShow, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.beforeHide, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterHide, 0, "Lifecycle event invocation count page2 should be correct");

		assert.equal(window.mPage3EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page3 beforeFirstShow should be correct");
		assert.equal(window.mPage3EventLog.beforeShow, 0, "Lifecycle event invocation count page3 beforeShow should be correct");
		assert.equal(window.mPage3EventLog.afterShow, 0, "Lifecycle event invocation count page3 afterShow should be correct");
		assert.equal(window.mPage3EventLog.beforeHide, 0, "Lifecycle event invocation count page3 beforeHide should be correct");
		assert.equal(window.mPage3EventLog.afterHide, 0, "Lifecycle event invocation count page3 afterHide should be correct");

		assert.ok(document.getElementById("myNC"), "NavContainer should be rendered");
		assert.ok(!document.getElementById("nc2"), "NavContainer 2 should not be rendered");
		assert.ok(document.getElementById("sap-ui-invisible-nc2"), "NavContainer 2 invisible container should be rendered");

		assert.ok(document.getElementById("page1"), "Initially the first page should be rendered");
		assert.equal(nc.getCurrentPage().getId(), "page1", "getCurrentPage should return Page1");
		assert.equal(nc._pageStack.length, 1, "the page stack size should be 1");

		assert.equal(nc._aQueue.length, 0, "transition queue length should be 0");
		assert.ok(nc._bNavigating === false, "NavContainer should not be navigating");

		nc2.setVisible(true);
		Core.applyChanges();

		assert.ok(document.getElementById("nc2"), "NavContainer 2 should be rendered");
	});

	QUnit.module("AutoFocus tests", {
		beforeEach: function () {
			this.fnApplyAutoFocusToSpy = this.spy(NavContainer, "_applyAutoFocusTo");
			this.pageId = "someId";
		},
		afterEach: function () {
		}
	});

	QUnit.test("Auto focus enabled", function (assert) {
		this.stub(nc, "getAutoFocus").returns(true);

		nc._applyAutoFocus({
			isTo: true,
			toId: this.pageId,
			bFocusInsideFromPage: true
		});

		assert.ok(this.fnApplyAutoFocusToSpy.calledWith(this.pageId));

		this.fnApplyAutoFocusToSpy.resetHistory();

		nc._applyAutoFocus({
			isBack: true,
			toId: this.pageId,
			bFocusInsideFromPage: true
		});

		assert.ok(this.fnApplyAutoFocusToSpy.calledWith(this.pageId));

		this.fnApplyAutoFocusToSpy.resetHistory();

		nc._applyAutoFocus({
			isBackToPage: true,
			toId: this.pageId,
			bFocusInsideFromPage: true
		});

		assert.ok(this.fnApplyAutoFocusToSpy.calledWith(this.pageId));

		this.fnApplyAutoFocusToSpy.resetHistory();

		nc._applyAutoFocus({
			isBackToTop: true,
			toId: this.pageId,
			bFocusInsideFromPage: true
		});

		assert.ok(this.fnApplyAutoFocusToSpy.calledWith(this.pageId));

		this.fnApplyAutoFocusToSpy.resetHistory();

		nc._applyAutoFocus({
			isTo: false,
			toId: this.pageId,
			bFocusInsideFromPage: true
		});

		assert.ok(!this.fnApplyAutoFocusToSpy.calledWith(this.pageId));
	});

	QUnit.test("Auto focus disabled", function (assert) {
		// Arrange
		var oApplyAutoFocusSpy = this.spy(NavContainer.prototype, "_applyAutoFocus"),
			fnDone = assert.async(),
			oNavContainer = new NavContainer({
				pages : [
					new Page("firstPage"),
					new Page("secondPage")
				],
				autoFocus: false,
				afterNavigate: function() {
					// Assert
					assert.strictEqual(oApplyAutoFocusSpy.callCount, 0,
							"_applyAutoFocus is never called when autoFocus property is false.");

					// Cleanup
					oApplyAutoFocusSpy.restore();
					oNavContainer.destroy();

					fnDone();
				}
			}).placeAt("qunit-fixture");

		assert.expect(1);
		Core.applyChanges();

		// Act
		oNavContainer.to("secondPage");
	});

	QUnit.test("Auto focus should't be used when inside a popup", function (assert) {
		var oNavContainer = new NavContainer();
		new Popover({content: new Page({content: [oNavContainer]})});
		assert.ok(oNavContainer._isInsideAPopup(), "NavContainer detects that it's nested inside a popup");
	});

	QUnit.test("_applyAutoFocusTo method should't be called when the focus was not on from page", function (oAssert) {
		var oNC = new NavContainer();

		// Act
		oNC._applyAutoFocus({
			isTo: true,
			toId: this.pageId,
			bFocusInsideFromPage: false // We emulate focus not inside the current page
		});

		// Assert
		oAssert.strictEqual(this.fnApplyAutoFocusToSpy.callCount, 0,
			"The method should not be called when focus is not inside the current page");

		// Act
		oNC._applyAutoFocus({
			isTo: true,
			toId: this.pageId,
			bFocusInsideFromPage: true // We emulate focus inside the current page
		});

		// Assert
		oAssert.strictEqual(this.fnApplyAutoFocusToSpy.callCount, 1,
			"The method should be called when focus is inside the current page");
	});

	QUnit.test("Auto focus should't be modified when the focus was not inside the current page", function (oAssert) {
		// Arrange
		var fnDone = oAssert.async(),
			oOutsideButton = new Button({text: "Outside Button"}).placeAt("qunit-fixture"),
			oInsideButton = new Button({text: "Inside Button"}),
			oNavContainer = new NavContainer({
				pages : [
					new Page("firstPage"),
					new Page("secondPage", { content : [oInsideButton] })
				]
			}).placeAt("qunit-fixture");

		Core.applyChanges();

		oNavContainer.attachNavigate(function (oEvent) {
			// Assert
			oAssert.strictEqual(oEvent.getParameter("bFocusInsideFromPage"), false,
				"The bFocusInsideFromPage parameter should be false as focus is outside the current page");

			oAssert.strictEqual(document.activeElement, oOutsideButton.getDomRef(),
				"The focus should remain on the outside button");

			oAssert.notStrictEqual(document.activeElement, oInsideButton.getDomRef(),
				"The focus should not be moved to the inside button");

			fnDone();
		});

		// Act - place focus outside the Nav container current page and navigate to second page
		oOutsideButton.$().trigger("focus");
		oNavContainer.to("secondPage");

		// Cleanup
		oOutsideButton.destroy();
		oNavContainer.destroy();
	});

	QUnit.module("Events", {
		beforeEach: function () {
			// Arrange
			this.nc = new NavContainer({
				pages: [
					new Page("page1a", {
						title: "page1a"
					}),
					new Page("page2a", {
						title: "page2a"
					})
				]
			});
		},
		afterEach: function () {
			// Cleanup
			this.nc.destroy();
			this.nc = null;
		}
	});

	QUnit.test("afterNavigate is fired event if no transition", function (assert) {
		// Arrange
		var oSpy = this.spy(this.nc, "fireAfterNavigate");

		Core.applyChanges();

		// Act
		this.nc.to("page2a");

		this.nc.attachAfterNavigate(function () {
			// Assert
			assert.ok(oSpy.called, "Navigation finished without transition (NavContainer was not rendered) and event was fired");
		});

		this.nc.backToPage("page1a");
	});

	QUnit.test("navigationFinished is fired if the nav container is NOT rendered", function (assert) {
		assert.expect(2);
		// Arrange
		var fnDone = assert.async(),
			oSpy = this.spy(this.nc, "fireNavigationFinished");

		// Assert
		assert.notOk(this.nc.getDomRef(), "NavContainer is not rendered");

		this.nc.attachNavigationFinished(function () {
			// Assert
			assert.ok(oSpy.called, "NavContainer was not rendered and the event was fired");
			fnDone();
		});

		// Act
		this.nc.to("page2a");
	});

	QUnit.test("navigationFinished is fired if the nav container is rendered", function (assert) {
		assert.expect(2);
		// Arrange
		var fnDone = assert.async(),
			oSpy = this.spy(this.nc, "fireNavigationFinished");

		this.nc.placeAt("qunit-fixture");
		Core.applyChanges();

		// Assert
		assert.ok(this.nc.getDomRef(), "NavContainer is rendered");

		this.nc.attachNavigationFinished(function () {
			// Assert
			assert.ok(oSpy.called, "NavContainer was rendered and the event was fired");
			fnDone();
		});

		// Act
		this.nc.to("page2a");
	});

	QUnit.module("Page change");

	QUnit.test("to page 2", function(assert) {
		var done = assert.async();
		assert.expect(65); // including the "navigate" event

		assert.equal(nc.currentPageIsTopPage(), true, "current page should be considered the top page");

		resetEventLog(window.mPage1EventLog);
		resetEventLog(window.mPage2EventLog);
		resetEventLog(window.mPage3EventLog);

		window.expectedNav = {
				fromId: "page1",
				toId: "page2",
				firstTime: true,
				isTo: true,
				isBack: false,
				isBackToPage: false,
				isBackToTop: false,
				direction: "to"
		};

		nc.to("page2", {transferData:"test123"});

		assert.equal(nc.currentPageIsTopPage(), false, "current page should not be considered the top page");

		assert.ok(nc._bNavigating === true, "NavContainer should be navigating");

		assert.equal(window.mPage1EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page1 beforeFirstShow should be correct");
		assert.equal(window.mPage1EventLog.beforeShow, 0, "Lifecycle event invocation count page1 beforeShow should be correct");
		assert.equal(window.mPage1EventLog.afterShow, 0, "Lifecycle event invocation count page1 afterShow should be correct");
		assert.equal(window.mPage1EventLog.beforeHide, 1, "Lifecycle event invocation count page1 beforeHide should be correct");
		assert.equal(window.mPage1EventLog.afterHide, 0, "Lifecycle event invocation count page1 afterHide should be correct");

		assert.equal(window.mPage2EventLog.beforeFirstShow, 1, "Lifecycle event invocation count page2 beforeFirstShow should be correct");
		assert.equal(window.mPage2EventLog.beforeShow, 1, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterShow, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.beforeHide, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterHide, 0, "Lifecycle event invocation count page2 should be correct");

		assert.equal(window.mPage3EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page3 beforeFirstShow should be correct");
		assert.equal(window.mPage3EventLog.beforeShow, 0, "Lifecycle event invocation count page3 beforeShow should be correct");
		assert.equal(window.mPage3EventLog.afterShow, 0, "Lifecycle event invocation count page3 afterShow should be correct");
		assert.equal(window.mPage3EventLog.beforeHide, 0, "Lifecycle event invocation count page3 beforeHide should be correct");
		assert.equal(window.mPage3EventLog.afterHide, 0, "Lifecycle event invocation count page3 afterHide should be correct");

		assert.equal(window.mPage1EventLog.data, null, "Data given to page1 should be correct");
		assert.equal(window.mPage1EventLog.backData, null, "BackData given to page1 should be correct");
		assert.equal(window.mPage2EventLog.data.transferData, "test123", "Data given to page2 should be correct");
		assert.ok(!!window.mPage2EventLog.backData, "BackData given to page2 should be correct");
		assert.equal(window.mPage3EventLog.data, null, "Data given to page3 should be correct");
		assert.equal(window.mPage3EventLog.backData, null, "BackData given to page3 should be correct");

		setTimeout(function() {
			assert.ok(document.getElementById("page1"), "Page 1 should still be in DOM");
			assert.ok(document.getElementById("page2"), "Page 2 should now be rendered");
			assert.equal(nc.getCurrentPage().getId(), "page2", "getCurrentPage should return Page 2");
			assert.equal(nc._pageStack.length, 2, "the page stack size should be 2");

			setTimeout(function() {

				assert.equal(window.mPage1EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page1 beforeFirstShow should be correct");
				assert.equal(window.mPage1EventLog.beforeShow, 0, "Lifecycle event invocation count page1 beforeShow should be correct");
				assert.equal(window.mPage1EventLog.afterShow, 0, "Lifecycle event invocation count page1 afterShow should be correct");
				assert.equal(window.mPage1EventLog.beforeHide, 1, "Lifecycle event invocation count page1 beforeHide should be correct");
				assert.equal(window.mPage1EventLog.afterHide, 1, "Lifecycle event invocation count page1 afterHide should be correct");

				assert.equal(window.mPage2EventLog.beforeFirstShow, 1, "Lifecycle event invocation count page2 beforeFirstShow should be correct");
				assert.equal(window.mPage2EventLog.beforeShow, 1, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.afterShow, 1, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.beforeHide, 0, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.afterHide, 0, "Lifecycle event invocation count page2 should be correct");

				assert.equal(window.mPage3EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page3 beforeFirstShow should be correct");
				assert.equal(window.mPage3EventLog.beforeShow, 0, "Lifecycle event invocation count page3 beforeShow should be correct");
				assert.equal(window.mPage3EventLog.afterShow, 0, "Lifecycle event invocation count page3 afterShow should be correct");
				assert.equal(window.mPage3EventLog.beforeHide, 0, "Lifecycle event invocation count page3 beforeHide should be correct");
				assert.equal(window.mPage3EventLog.afterHide, 0, "Lifecycle event invocation count page3 afterHide should be correct");

				assert.equal(jQuery("#page1").css("display"), "none", "Page 1 should be hidden");
				assert.equal(jQuery("#page1").attr("aria-hidden"), "true", "Page 1 should be aria hidden");
				assert.equal(nc._aQueue.length, 0, "transition queue length should be 0");
				assert.ok(nc._bNavigating === false, "NavContainer should not be navigating");
				assert.ok(!page1.$().hasClass("sapMNavItemSliding"), "Page 1 classes should be cleaned up");
				assert.ok(!page2.$().hasClass("sapMNavItemSliding"), "Page 2 classes should be cleaned up");
				done();
			}, 600);
		}, 100);
	});

	QUnit.test("to page 3", function(assert) {
		var done = assert.async();
		assert.expect(31); // including the "navigate" event

		assert.ok(nc._bNavigating === false, "NavContainer should not be navigating");

		window.expectedNav = {
				fromId: "page2",
				toId: "page3",
				firstTime: true,
				isTo: true,
				isBack: false,
				isBackToPage: false,
				isBackToTop: false,
				direction: "to"
		};

		nc.to("page3", "fade");

		assert.equal(nc.currentPageIsTopPage(), false, "current page should not be considered the top page");

		// more data checks
		assert.equal(window.mPage1EventLog.data, null, "Data given to page1 should be correct");
		assert.equal(window.mPage1EventLog.backData, null, "BackData given to page1 should be correct");
		assert.ok(!!window.mPage3EventLog.data, "Data given to page3 should be correct");
		assert.ok(!!window.mPage3EventLog.backData, "BackData given to page3 should be correct");

		setTimeout(function() {
			assert.ok(document.getElementById("page2"), "Page 2 should still be in DOM");
			assert.ok(document.getElementById("page3"), "Page 3 should now be rendered");
			assert.equal(nc.getCurrentPage().getId(), "page3", "getCurrentPage should return Page 3");
			assert.equal(nc._pageStack.length, 3, "the page stack size should be 3");

			setTimeout(function(){
				assert.equal(jQuery("#page2").css("display"), "none", "Page 2 should be hidden");
				assert.equal(jQuery("#page2").attr("aria-hidden"), "true", "Page 2 should be aria hidden");

				assert.equal(nc._aQueue.length, 0, "transition queue length should be 0");

				assert.ok(!page3.$().hasClass("sapMNavItemFading"), "Page 3 classes should be cleaned up");
				assert.ok(!page2.$().hasClass("sapMNavItemFading"), "Page 2 classes should be cleaned up");
				done();
			}, 600);
		}, 100);
	});


	QUnit.test("navigate back 2", function(assert) {
		var done = assert.async();
		assert.expect(63); // including the "navigate" event

		resetEventLog(window.mPage1EventLog);
		resetEventLog(window.mPage2EventLog);
		resetEventLog(window.mPage3EventLog);

		window.expectedNav = {
				fromId: "page3",
				toId: "page2",
				firstTime: false,
				isTo: false,
				isBack: true,
				isBackToPage: false,
				isBackToTop: false,
				direction: "back"
		};

		nc.back({transferData:"test456"});
		assert.ok(nc._bNavigating === true, "NavContainer should be navigating");

		assert.equal(window.mPage1EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page1 beforeFirstShow should be correct");
		assert.equal(window.mPage1EventLog.beforeShow, 0, "Lifecycle event invocation count page1 beforeShow should be correct");
		assert.equal(window.mPage1EventLog.afterShow, 0, "Lifecycle event invocation count page1 afterShow should be correct");
		assert.equal(window.mPage1EventLog.beforeHide, 0, "Lifecycle event invocation count page1 beforeHide should be correct");
		assert.equal(window.mPage1EventLog.afterHide, 0, "Lifecycle event invocation count page1 afterHide should be correct");

		assert.equal(window.mPage2EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page2 beforeFirstShow should be correct");
		assert.equal(window.mPage2EventLog.beforeShow, 1, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterShow, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.beforeHide, 0, "Lifecycle event invocation count page2 should be correct");
		assert.equal(window.mPage2EventLog.afterHide, 0, "Lifecycle event invocation count page2 should be correct");

		assert.equal(window.mPage3EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page3 beforeFirstShow should be correct");
		assert.equal(window.mPage3EventLog.beforeShow, 0, "Lifecycle event invocation count page3 beforeShow should be correct");
		assert.equal(window.mPage3EventLog.afterShow, 0, "Lifecycle event invocation count page3 afterShow should be correct");
		assert.equal(window.mPage3EventLog.beforeHide, 1, "Lifecycle event invocation count page3 beforeHide should be correct");
		assert.equal(window.mPage3EventLog.afterHide, 0, "Lifecycle event invocation count page3 afterHide should be correct");

		assert.equal(window.mPage1EventLog.data, null, "Data given to page1 should be correct");
		assert.equal(window.mPage1EventLog.backData, null, "BackData given to page1 should be correct");
		assert.equal(window.mPage2EventLog.data.transferData, "test123", "Data given to page2 should be correct");
		assert.equal(window.mPage2EventLog.backData.transferData, "test456", "BackData given to page2 should be correct");
		assert.equal(window.mPage3EventLog.data, null, "Data given to page3 should be correct");
		assert.equal(window.mPage3EventLog.backData, null, "BackData given to page3 should be correct");

		setTimeout(function() {
			assert.ok(document.getElementById("page3"), "Page 3 should still be in DOM");
			assert.ok(document.getElementById("page2"), "Page 2 should now be visible");
			assert.equal(nc.getCurrentPage().getId(), "page2", "getCurrentPage should return Page 2");
			assert.equal(nc._pageStack.length, 2, "getStackLevel should return 2");

			setTimeout(function() {
				assert.equal(window.mPage1EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page1 beforeFirstShow should be correct");
				assert.equal(window.mPage1EventLog.beforeShow, 0, "Lifecycle event invocation count page1 beforeShow should be correct");
				assert.equal(window.mPage1EventLog.afterShow, 0, "Lifecycle event invocation count page1 afterShow should be correct");
				assert.equal(window.mPage1EventLog.beforeHide, 0, "Lifecycle event invocation count page1 beforeHide should be correct");
				assert.equal(window.mPage1EventLog.afterHide, 0, "Lifecycle event invocation count page1 afterHide should be correct");

				assert.equal(window.mPage2EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page2 beforeFirstShow should be correct");
				assert.equal(window.mPage2EventLog.beforeShow, 1, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.afterShow, 1, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.beforeHide, 0, "Lifecycle event invocation count page2 should be correct");
				assert.equal(window.mPage2EventLog.afterHide, 0, "Lifecycle event invocation count page2 should be correct");

				assert.equal(window.mPage3EventLog.beforeFirstShow, 0, "Lifecycle event invocation count page3 beforeFirstShow should be correct");
				assert.equal(window.mPage3EventLog.beforeShow, 0, "Lifecycle event invocation count page3 beforeShow should be correct");
				assert.equal(window.mPage3EventLog.afterShow, 0, "Lifecycle event invocation count page3 afterShow should be correct");
				assert.equal(window.mPage3EventLog.beforeHide, 1, "Lifecycle event invocation count page3 beforeHide should be correct");
				assert.equal(window.mPage3EventLog.afterHide, 1, "Lifecycle event invocation count page3 afterHide should be correct");

				assert.equal(jQuery("#page3").css("display"), "none", "Page 3 should be hidden");
				assert.equal(jQuery("#page3").attr("aria-hidden"), "true", "Page 3 should be aria hidden");
				assert.equal(nc._aQueue.length, 0, "transition queue length should be 0");
				assert.ok(nc._bNavigating === false, "NavContainer should not be navigating");
				assert.ok(!page3.$().hasClass("sapMNavItemFading"), "Page 3 classes should be cleaned up");
				assert.ok(!page2.$().hasClass("sapMNavItemFading"), "Page 2 classes should be cleaned up");
				done();
			}, 600);
		}, 100);
	});

	QUnit.test("Custom Transition Definition (on instance)", function(assert) {
		assert.expect(4);

		assert.equal(!!NavContainer.transitions["c_testTrans"], false, "custom animation should not be defined yet");

		nc.addCustomTransition(
				"c_testTrans",
				/* to