/// <summary> /// Opens the interactive window, clears the screen. /// </summary> internal void Test(Action <NodejsVisualStudioApp, InteractiveWindow> body) { using (var app = new NodejsVisualStudioApp()) { app.SuppressCloseAllOnDispose(); const string interpreterDescription = "Node.js Interactive Window"; app.Dte.ExecuteCommand("View.Node.jsInteractiveWindow"); var interactive = app.GetInteractiveWindow(interpreterDescription); if (interactive == null) { Assert.Inconclusive("Need " + interpreterDescription); } interactive.WaitForIdleState(); app.Element.SetFocus(); interactive.Element.SetFocus(); interactive.ClearInput(); bool isReady = false; for (int retries = 10; retries > 0; --retries) { interactive.Reset(); try { var task = interactive.ReplWindow.Evaluator.ExecuteText("console.log('READY')"); Assert.IsTrue(task.Wait(10000), "ReplWindow did not initialize in time"); if (!task.Result.IsSuccessful) { continue; } } catch (TaskCanceledException) { continue; } interactive.WaitForTextEnd("READY", "undefined", "> "); isReady = true; break; } Assert.IsTrue(isReady, "ReplWindow did not initialize"); interactive.ClearScreen(); interactive.ReplWindow.ClearHistory(); body(app, interactive); interactive.ClearScreen(); interactive.ReplWindow.ClearHistory(); } }
public void TestLongPathCheck() { string[] expectedLongPaths = { @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\trailing-attribute-no-value.js", @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\xmlns-xml-default-prefix-attribute.js", @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\xmlns-xml-default-redefine.js", @"node_modules\azure\node_modules\request\node_modules\form-data\node_modules\combined-stream\node_modules", @"node_modules\azure\node_modules\request\node_modules\http-signature\node_modules\ctype\tst\ctio\uint\tst.roundtrip.js", }; string projectDir = CreateTempPathOfLength(248 - 1 - expectedLongPaths.Min(s => s.Length)); try { foreach (var fileName in new[] { "HelloWorld.njsproj", "HelloWorld.sln", "package.json", "README.md", "server.js" }) { File.Copy(TestData.GetPath(@"TestData\HelloWorld\" + fileName), projectDir + "\\" + fileName); } using (var app = new NodejsVisualStudioApp()) { try { NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths = true; var project = app.OpenProject(projectDir + "\\HelloWorld.sln"); // Wait for new solution to load. for (int i = 0; i < 40 && app.Dte.Solution.Projects.Count == 0; i++) { System.Threading.Thread.Sleep(250); } const string interpreterDescription = "Node.js Interactive Window"; app.Dte.ExecuteCommand("View.Node.jsInteractiveWindow"); var interactive = app.GetInteractiveWindow(interpreterDescription); if (interactive == null) { Assert.Inconclusive("Need " + interpreterDescription); } interactive.WaitForIdleState(); var npmTask = interactive.ReplWindow.ExecuteCommand(".npm install [email protected]"); using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should be there. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsTrue(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.ClickButtonByAutomationId("ExpandoButton"); var detailsText = dialog.FindByAutomationId("ExpandedFooterTextLink"); Assert.IsNotNull(detailsText); var reportedLongPaths = (from line in detailsText.Current.Name.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) where line.StartsWith("•") let nbspIndex = line.IndexOf('\u00A0') where nbspIndex >= 0 select line.Substring(1, nbspIndex - 1).Trim() ).ToArray(); Console.WriteLine("Reported paths:"); foreach (var path in reportedLongPaths) { Console.WriteLine("\t" + path); } reportedLongPaths = reportedLongPaths.Except(expectedLongPaths).ToArray(); if (reportedLongPaths.Length != 0) { Console.WriteLine("Unexpected paths:"); foreach (var path in reportedLongPaths) { Console.WriteLine("\t" + path); } Assert.Fail("Unexpected long paths reported."); } dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { // Click the first command button (dedupe). firstCommandLink.SetFocus(); Keyboard.Press(System.Windows.Input.Key.Enter); }); } // Clicking on that button should not change the option. Assert.IsTrue(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); interactive.WaitForTextContainsAll("dedupe successfully completed"); interactive.WaitForIdleState(); // npm dedupe won't be able to fix the problem, so we should get the dialog once again. using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should not be there anymore. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsFalse(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { Keyboard.Type("\r"); // click the first command button (do nothing, but warn next time) }); } npmTask.Wait(1000); Assert.IsTrue(npmTask.IsCompleted); // Clicking on that button should not change the option. Assert.IsTrue(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); // Try again to see that the dialog still appears. Any npm command triggers the check. // and since we didn't do anything to fix the problem, we should still get the dialog. interactive.WaitForIdleState(); npmTask = interactive.ReplWindow.ExecuteCommand(".npm list"); using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should be there again, since this is a new check. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsTrue(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { // Click the third command button (do nothing, do not warn anymore) firstCommandLink.SetFocus(); Keyboard.Press(System.Windows.Input.Key.Tab); Keyboard.Press(System.Windows.Input.Key.Tab); Keyboard.Press(System.Windows.Input.Key.Enter); }); } npmTask.Wait(1000); Assert.IsTrue(npmTask.IsCompleted); // Clicking on that button should change the option to false. Assert.IsFalse(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); // Try again to see that the dialog does not appear anymore. interactive.WaitForIdleState(); npmTask = interactive.ReplWindow.ExecuteCommand(".npm list"); app.WaitForNoDialog(TimeSpan.FromSeconds(3)); } finally { NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths = true; } } } finally { DeleteLongPath(projectDir); } }