Skip to content

Conversation

@YangLyu89
Copy link

Adding file save restore tests for:

cdnjs and unpackage provider, including adding/deleting file/library.

}

[TestCleanup]
public void Cleanup()
Copy link
Author

@YangLyu89 YangLyu89 Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for revert the libman.json file to its original status and also delete the libraries downloads during each test so as to not affect later tests. #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have to explain your code with a comment, then the code should be made more clear. I think you could just add a comment // Reset libman.json file contents

You also assume here that the undo stack will always work/be accurate. A better way to reset would be for TestInitialize to get the file content, and for Cleanup to set it back to the exact same content.


In reply to: 194349724 [](ancestors = 194349724)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That make sense, I will try using this way to revert the change in the file.


In reply to: 194549775 [](ancestors = 194549775,194349724)

}

[TestMethod]
public void FileSaveRestore_Cdnjs_DeleteLibrary()
Copy link
Author

@YangLyu89 YangLyu89 Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FileSaveRestore_Cdnjs_DeleteLibrary() [](start = 20, length = 37)

Using another existing project with a ready libman.json can reduced the amount of Editor typing related code here. #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it could, that's a good idea.


In reply to: 194350175 [](ancestors = 194350175)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could probably try getting content from the other json file as you point out for reverting file change.


In reply to: 194552391 [](ancestors = 194552391,194350175)


if(dir.Exists)
{
foreach(FileSystemInfo item in dir.EnumerateDirectories())
Copy link
Contributor

@ToddGrun ToddGrun Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as Directory.EnumerateFileSystemEntries ? #Closed

Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1.

Also, shouldn't this be recursive? Why do you limit to the top directory? You could just use Directory.EnumerateFileSystemEntries(path, "*", SearchOption.AllDirectories)


In reply to: 194396415 [](ancestors = 194396415)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(That could replace this whole method)


In reply to: 194556460 [](ancestors = 194556460,194396415)

Copy link
Author

@YangLyu89 YangLyu89 Jun 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During the test design discussion, we are going to verify only top level items. If it's not too much work, I think verifying the sub-folder items also make sense to me. I will try using the enumeratefilesystem function.


In reply to: 194556684 [](ancestors = 194556684,194556460,194396415)

{
string errorMessage = WaitForRestoredFilesHelper(cwd, new[] { expectedFileOrFolder }, caseInsensitive, timeout);

if (errorMessage == null)
Copy link
Contributor

@ToddGrun ToddGrun Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is similar to the completion issue in that you appear to be waiting for a timeout for this method to pass #Closed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be an different issue. Because the restoring is in progress after save the libman.json file. It needs sufficient time for restoring before we believe the unexpected file is not presented.


In reply to: 194397045 [](ancestors = 194397045)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is deleted.


In reply to: 194937801 [](ancestors = 194937801,194397045)

Copy link
Contributor

@ToddGrun ToddGrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

{
get
{
return _solutionRootPath;
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_solutionRootPath [](start = 23, length = 17)

Can it just be auto-property instead of having a backing field?

public string SolutionRootPath { get; private set; } #Resolved 
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It can be. I can change it.


In reply to: 194547773 [](ancestors = 194547773)

{
errorMessage = String.Concat(errorMessage, "\r\n*Didn't* fail when forcing completion with double timeout");
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to do the "doubled timeout" thing in multiple places, it should be its own helper.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For here. I use the doubled timeout for WaitForRestoredFile for file restore. But not using timeout for WaitForRestoredFileNotPresent because it is called after the WaitForRestore just verifying the not specified files are not included. So I think this doubled timeout can be written here.


In reply to: 194547985 [](ancestors = 194547985)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's now only used here for the waitforrestoredfiles.


In reply to: 194883862 [](ancestors = 194883862,194547985)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that we're copying the logic of retrying with an extra timeout duration from the completion helper method. Is this a pattern we want to do commonly? Then there should be a base waiter method to contain that retry logic.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. using a delagate waiter for both waitforrestoredfileshelper and waitfordeletedfileshelper function


In reply to: 195513255 [](ancestors = 195513255)

{
public class LibmanTestsUtility
{
private static HashSet<string> GetTopLevelDirectoriesAndFiles(string cwd, bool caseInsensitive)
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cwd [](start = 77, length = 3)

don't use abbreviated variable names #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change


In reply to: 194548281 [](ancestors = 194548281)

return topLevelItems;
}

public static void WaitForRestoredFiles(string cwd, IEnumerable<string> expectedFilesAndFolders, bool caseInsensitive, int timeout = 10000)
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cwd [](start = 55, length = 3)

don't use abbreviated variable names #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change


In reply to: 194548392 [](ancestors = 194548392)

public void initialize()
{
_webProject = Solution.ProjectsRecursive[_projectName];
_libManConfig = _webProject.Find(SolutionItemFind.FileName, "libman.json");
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Find(SolutionItemFind.FileName, "libman.json") [](start = 40, length = 46)

This should be in the project root, so use _webProject["libman.json"] #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will try


In reply to: 194548636 [](ancestors = 194548636)

[TestInitialize()]
public void initialize()
{
_webProject = Solution.ProjectsRecursive[_projectName];
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProjectsRecursive [](start = 35, length = 17)

Is the project not in the root? Usually we do Solution[_projectName] #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project folder will be in the root of the solution folder.


In reply to: 194548753 [](ancestors = 194548753)

Editor.Caret.MoveToExpression("\"libraries\"");
Editor.Caret.MoveDown(2);
Editor.KeyboardCommands.Type("\"library\":");
LibmanTestsUtility.WaitForCompletionEntry(Editor, "jquery", caseInsensitive: true, timeout: 5000);
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5000 [](start = 104, length = 4)

This is a really long timeout. Can we do something to make this shorter? #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a little, because it takes time when first time we are trying to getting all library IDs from the server.


In reply to: 194550054 [](ancestors = 194550054)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get rid of this line as using new json file


In reply to: 194894203 [](ancestors = 194894203,194550054)

public void FileSaveRestore_Unpkg_AddNewLibraryWithoutSpecifingFiles()
{
_libManConfig.Open();
string[] expectedFilesAndFolders = new[] {
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expectedFilesAndFolders [](start = 21, length = 23)

Are you going to verify that there's anything inside of dist? #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently not. Do you think we should verifying it for now?


In reply to: 194551666 [](ancestors = 194551666)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verifying sub-folder item now


In reply to: 194894377 [](ancestors = 194894377,194551666)

Editor.KeyboardCommands.Type("\"jquery.js\"");

_libManConfig.Save();
string cwd = Path.Combine(Path.GetDirectoryName(_webProject.FullPath), "wwwroot", "lib", "jquery");
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cwd [](start = 19, length = 3)

don't abbreviate this name. I can't understand what it represents. #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will change. This is current working directory I think. I follow the name pattern from otherwhere in libman.


In reply to: 194551848 [](ancestors = 194551848)

Editor.KeyboardCommands.Type("\"files\": [");
Editor.KeyboardCommands.Enter();
Editor.KeyboardCommands.Type("\"LICENSE.txt\"");

Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A much more realistic user scenarios (i.e. much more worth protecting with a test) would be to get the jquery.min.js file. #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I will do this check.


In reply to: 194552135 [](ancestors = 194552135)

for (int i = 0; i < 4; ++i)
{
Editor.Edit.DeleteLine();
}
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeleteLine takes a parameter for how many times to do it. You don't need a loop here. #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will try.


In reply to: 194552547 [](ancestors = 194552547)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like Editor.Edit.deleteLine doesn't accept parameter


In reply to: 194894785 [](ancestors = 194894785,194552547)

Editor.KeyboardCommands.Type("\"library\":");
LibmanTestsUtility.WaitForCompletionEntry(Editor, "jquery", caseInsensitive: true, timeout: 5000);
Editor.KeyboardCommands.Type("jquery@3.3.1");
Editor.KeyboardCommands.Right();
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this line? Why can't we type something from jquery through the comma? #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a bug. If have comma in the line before, there will be two commas!


In reply to: 194552816 [](ancestors = 194552816)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get rid of it in new iteration.


In reply to: 194895044 [](ancestors = 194895044,194552816)


_libManConfig.Save();
LibmanTestsUtility.WaitForDeletedFiles(cwd, expectedFilesAndFolders, caseInsensitive: true);
}
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this just check that there are no files left under the path? Instead of checking a hardcoded list? #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For that matter, we should be deleting the folder too, but I can't remember if that fix is submitted yet.


In reply to: 194555302 [](ancestors = 194555302)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It make sense. I can try verifying there's no files in it


In reply to: 194555373 [](ancestors = 194555373,194555302)

Copy link
Contributor

@jimmylewis jimmylewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

LibmanTestsUtility.WaitForRestoredFiles(cwd, expectedFilesAndFolders, caseInsensitive: true);

Editor.Edit.DeleteToBeginningOfLine();
_libManConfig.Save();
Copy link
Contributor

@jimmylewis jimmylewis Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this leave a comma after "jquery.js", which invalidates the json file? I'm surprised this even works if the file doesn't parse. #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a bug make this comma work. However, I should not leave the extra comma here.


In reply to: 194557761 [](ancestors = 194557761)

Copy link
Contributor

@jimmylewis jimmylewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this PR some more, and it doesn't make sense to me that we're testing multiple providers separately, or even at all.

The Restore on Save functionality needs to verify that:

  • A restore happens when the file is saved
  • Any delta from the previous version of the libman.json file is cleaned up.

It does not need to test that individual providers are working, or that different file configurations are working. Those should be tested elsewhere.

{
public class LibmanTestsUtility
{
private static HashSet<string> GetSubDirectoriesAndFiles(string currentWorkingDirectory, bool caseInsensitive)
Copy link
Contributor

@ToddGrun ToddGrun Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private static HashSet GetSubDirectoriesAndFiles(string currentWorkingDirectory, bool caseInsensitive) [](start = 8, length = 110)

nit: I would probably implement this like the following

 private static HashSet<string> GetSubDirectoriesAndFiles(string currentWorkingDirectory, bool caseInsensitive) { StringComparer comparer = caseInsensitive ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; IEnumerable<string> subItems = Directory.EnumerateFileSystemEntries(currentWorkingDirectory, "*", SearchOption.AllDirectories); return new HashSet(subItems, comparer); } 

But it doesn't really bother me the other way. #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for pointing out


In reply to: 195502551 [](ancestors = 195502551)

Editor.KeyboardCommands.Type("wwwroot/lib/jquery-validate");
Editor.Caret.MoveRight();
Editor.KeyboardCommands.Type(",");
Editor.KeyboardCommands.Enter();
Copy link
Author

@YangLyu89 YangLyu89 Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PathCompletionProvider will throw an exception if I combine it with "destination":
so currently I have to separate the comma to make the test work #Closed

Path.Combine(pathToLibrary, "localization", "messages_ar.js"),
};

Editor.Caret.MoveToExpression("\"libraries\"");
Copy link
Contributor

@jimmylewis jimmylewis Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole block of typing - now you depend on the content generated above from being constant. Instead just replace the text buffer contents with the document you want:

string libmanContents = @"{ everything that goes in the file }"; Editor.Selection.SelectAll(); Editor.KeyboardCommands.Backspace(); Editor.Edit.InsertTextInBuffer(libmanContents); libmanConfig.Save(); 

#Resolved

Copy link
Contributor

@jimmylewis jimmylewis Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably do this 3 times in this test:

  1. Save the original contents of the file for use in (3)
  2. Paste the file contents you want for the first library and verify.
  3. Paste the file contents you want for the changed file (added/removed libraries) and verify.
  4. Restore the original file contents from 0.
    #Resolved
Copy link
Contributor

@jimmylewis jimmylewis Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And those 4 lines could be refactored into a method like ReplaceFileContents(string) #Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do


In reply to: 195512080 [](ancestors = 195512080)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add the function


In reply to: 195511264 [](ancestors = 195511264)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add


In reply to: 195512249 [](ancestors = 195512249)

{
errorMessage = String.Concat(errorMessage, "\r\n*Didn't* fail when forcing completion with double timeout");
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that we're copying the logic of retrying with an extra timeout duration from the completion helper method. Is this a pattern we want to do commonly? Then there should be a base waiter method to contain that retry logic.


namespace Microsoft.Web.LibraryManager.IntegrationTest
{
public class LibmanTestsUtility
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This utility class is just becoming a dumping ground for various helpers. Can you organize these to make them discoverable to new test authors in the future? This has been a significant compaint about test code on our team for a while, let's not repeat past mistakes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seperate it into two helper class


In reply to: 195513583 [](ancestors = 195513583)

@ToddGrun ToddGrun dismissed their stale review June 15, 2018 16:52

revoking review

Yang Lyu and others added 2 commits June 15, 2018 15:14
The goal is to create a simpler API for discovering test utilities through the Helpers property, instead of having to reference static utilities.
@YangLyu89
Copy link
Author

close this one as merged to preview 4

@YangLyu89 YangLyu89 closed this Jun 19, 2018
@YangLyu89 YangLyu89 deleted the dev/yalyu/fileSaveRestore3 branch June 19, 2018 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants