<commit_before>describe("Saving sessions.", function() {

  var windowId;
  var bookmarks;
  var tabsInfo;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, (newWindow) => {
        windowId = newWindow.id
        tabsInfo = getTabsOrBookmarksInfo(newWindow.id, false);
        createTabs(tabsInfo, done);
      });
    }, 1000);
  });

  it("Should be able to save a set of tabs as bookmarks in a folder.", function(done) {
    callTest(done);
  });

  it("Should delete all the bookmarks in the session folder before saving an existing session.", function(done) {
    saveTestSession(windowId, () => {
      callTest(done);
    });
  });

  it("Saves a session if it is given a name and it is not already saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  })

  it("Puts the text field for the current session's name into edit mode ready to be saved when the session manager " +
  "is opened and the current session is not already saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  });

  it("Only saves sessions the user has flagged to be saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  });

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });

  function callTest(done) {
    saveSession(windowId); // Method under test.
    setTimeout(getBookmarksFolder, 1000);

    function getBookmarksFolder() {
      var query = {
        'title': 'Test Session'
      }
      chrome.bookmarks.search(query, getBookmarks);
    }

    function getBookmarks(bookmarkSessionFolderSearchResults) {
      // Only one bookmark session folder with the correct saved tabs ensures that the original bookmarks were deleted.
      expect(bookmarkSessionFolderSearchResults.length).toEqual(1);

      chrome.bookmarks.getChildren(bookmarkSessionFolderSearchResults[0].id, function(bookmarkTreeNodes) {
        bookmarks = bookmarkTreeNodes;
        assertSavedBookmarks(bookmarks, tabsInfo);
      });
    }

    function assertSavedBookmarks(bookmarks, expectedTabsInfo) {
      for (var i = 0; i < bookmarks.length; i++) {
        var bookmark = bookmarks[i];
        var expectedTabInfo = expectedTabsInfo[i];
        expect(bookmark.index).toEqual(expectedTabInfo.index);
        expect(bookmark.url).toEqual(expectedTabInfo.url);
      }
      done();
    }
  }
});

describe("Resuming sessions.", function() {

  describe("User restores a session from the session manager.", function() {

    var windowId;
    var sessionFolderId;
    var bookmarksInfo;

    beforeEach(function(done) {
      clearLocalStorageAndInitialise();
      // Necessary because it takes time to create Seshy folder.
      setTimeout(() => {
        chrome.windows.create({}, (newWindow) => {
          windowId = newWindow.id;
          bookmarksInfo = getTabsOrBookmarksInfo(newWindow.id, false);
          createTabs(bookmarksInfo, saveTestSessionAndCaptureSessionFolderId);
        });
      }, 1000);

      function saveTestSessionAndCaptureSessionFolderId() {
        saveTestSession(windowId, captureSessionFolderId);
      }

      function captureSessionFolderId(newSessionFolderId) {
        sessionFolderId = newSessionFolderId;
        chrome.windows.remove(windowId, () => {
          done();
        });
      }
    });

    it("Adds a window ID to session folder ID mapping in local storage.", function(done) {
      resumeSession(sessionFolderId, () => {
        chrome.storage.local.get(null, assertWindowToSessionFolderMappingAdded)
      });

      function assertWindowToSessionFolderMappingAdded(allLocalStorageObject) {
        var allLocalStorageKeys = Object.keys(allLocalStorageObject);

        var matchingLocalStorageKey;
        var matchingLocalStorageKeyValue;

        for (var i = 0; i < allLocalStorageKeys.length; i++) {
          var localStorageKey = allLocalStorageKeys[i];
          if (localStorageKey == windowId) {
            matchingLocalStorageKey = localStorageKey;
            matchingLocalStorageKeyValue = allLocalStorageObject[windowId.toString()]
          }
        }
        expect(matchingLocalStorageKey).toBe(windowId.toString());
        expect(matchingLocalStorageKeyValue).toBe(sessionFolderId);
        done();
      }
    });

    it("Opens a window with all the tabs as they were when the session was saved.", function(done) {
      resumeSession(sessionFolderId, (newWindow) => {
        assertSessionRestored(newWindow, bookmarksInfo);
      });

      function assertSessionRestored(newWindow, bookmarksInfo) {
        var tabs = newWindow.tabs;

        var expectedTabsNumber = bookmarksInfo.length;
        expect(tabs.length).toBe(expectedTabsNumber);

        var allTabsEqualToBookmarks = true;
        for (var i = 0; i++; i < tabs.length) {
          var tab = tabs[i];
          var bookmark = bookmarksInfo[i];
          if (tabEqualToBookmark(tab, bookmark)) {
            allTabsEqualBookmarks = false;
          }
        }
        expect(allTabsEqualToBookmarks).toBe(true);
        done();
      }
    });

    it("Focuses the appropriate window if the session is already open.", function(done) {
      console.log("Unimplemented test.");
      done();
    });

    afterEach(function(done) {
      cleanUp();
      // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
      setTimeout(done, 1000);
    });
  })

  describe("Identifying existing session and prompting to resume.", function() {

    // TODO set variables on `this` instead.
    var expectedSessionFolderId;
    var windowToCheck;
    var bookmarksInfo;
    var actualSessionFolderId;

    beforeEach(function(done) {
      clearLocalStorageAndInitialise();
      // Necessary because it takes time to create Seshy folder.
      setTimeout(() => {
        getSeshyFolder(createSessionBookmarksFolderThenBookmarks);
      }, 1000);

      function createSessionBookmarksFolderThenBookmarks(bookmarkTreeNodes) {
        createSessionBookmarksFolder(bookmarkTreeNodes, createBookmarks);
      }

      function createBookmarks(sessionBookmarksFolder) {
        expectedSessionFolderId = sessionBookmarksFolder.id;
        var asBookmarks = true;
        bookmarksInfo = getTabsOrBookmarksInfo(expectedSessionFolderId, asBookmarks);

        chrome.bookmarks.create(bookmarksInfo[0]);
        chrome.bookmarks.create(bookmarksInfo[1]);
        chrome.bookmarks.create(bookmarksInfo[2]);
        chrome.bookmarks.create(bookmarksInfo[3], createWindow);
      }

      function createWindow(bookmarkTreeNode) {
        chrome.windows.create({}, createTabs);
      }

      function createTabs(newWindow) {
        windowToCheck = newWindow;
        var tabsInfo = getTabsOrBookmarksInfo(windowToCheck.id);

        chrome.tabs.create(tabsInfo[0]);
        chrome.tabs.create(tabsInfo[1]);
        chrome.tabs.create(tabsInfo[2], getWindow);
        // Don't create new tab as the new window creates that for us.
      }

      function getWindow() {
        chrome.windows.get(windowToCheck.id, {'populate': true}, callTest);
      }

      function callTest(uptodateWindowToCheck) {
        windowToCheck = uptodateWindowToCheck;
        getSession(windowToCheck, captureExistingSession); // Method under test.
      }

      function captureExistingSession(actualSessionFolder) {
        actualSessionFolderId = actualSessionFolder === null ? null : actualSessionFolder.id;
        done();
      }
    });

    afterEach(function(done) {
      cleanUp();
      // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
      setTimeout(done, 1000);
    });

    it("Should recognise when a set of opened tabs represents an existing session.", function() {
      expect(expectedSessionFolderId).toEqual(actualSessionFolderId);
    });
  });
});

describe("Ending sessions.", function() {

  var windowId;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, addWindowToSessionMapping);
    }, 1000);

    function addWindowToSessionMapping(newWindow) {
      windowId = newWindow.id;
      var fakeSessionFolderId = 1;
      var items = {};
      items[newWindow.id.toString()] = fakeSessionFolderId;
      chrome.storage.local.set(items, done);
    }
  });

  it("Removes any window to session folder mapping from local storage.", function(done) {
    removeWindowToSessionFolderMapping(windowId, () => {
      getAllLocalStorage(assertWindowToSessionFolderMappingRemoved);
    });

    function assertWindowToSessionFolderMappingRemoved(allLocalStorageObject) {
      var allLocalStorageKeys = Object.keys(allLocalStorageObject);

      var matchingLocalStorageKey = false;
      var windowIdString = windowId.toString();

      for (var i = 0; i < allLocalStorageKeys.length; i++) {
        var localStorageKey = allLocalStorageKeys[i];
        if (localStorageKey == windowIdString) {
          matchingLocalStorageKey = true;
        }
      }
      expect(matchingLocalStorageKey).toBe(false);
      done();
    }
  });

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });
});

describe("Deleting sessions.", function() {

  var windowId;
  var expectedDeletedSessionFolderId;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, (newWindow) => {
        windowId = newWindow.id;
        tabsInfo = getTabsOrBookmarksInfo(newWindow.id, false);
        createTabs(tabsInfo, saveTestSessionAndCaptureSessionFolderId);
      });
    }, 1000);

    function saveTestSessionAndCaptureSessionFolderId() {
      saveTestSession(windowId, captureSessionFolderId);

      function captureSessionFolderId(sessionFolderId) {
        expectedDeletedSessionFolderId = sessionFolderId;
        done();
      }
    }
  });

  it("Deletes the session folder.", function(done) {
    deleteSession(expectedDeletedSessionFolderId, tryGetSessionFolder); // Method under test.

    function tryGetSessionFolder(sessionFolderId) {
      chrome.bookmarks.get(sessionFolderId.toString(), assertSessionFolderDeleted);
      var sessionFolderDeleted = false;

      function assertSessionFolderDeleted(sessionFolderId) {
        if (chrome.runtime.lastError) {
          sessionFolderDeleted = true;
        }
        expect(sessionFolderDeleted).toBe(true);
        done();
      }
    }
  })

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });
});

//---===~ Functions ~===------------------------------------------------------------------------------------------------
function createTabs(tabsInfo, callback) {
  chrome.tabs.create(tabsInfo[0]);
  chrome.tabs.create(tabsInfo[1]);
  if (typeof callback != 'undefined') {
    chrome.tabs.create(tabsInfo[2], callback);
  }
  else {
    chrome.tabs.create(tabsInfo[2]);
  }
}

function getTabsOrBookmarksInfo(windowOrParentId, asBookmarks, tabSetNumber) {
  var tabsInfo1 = [
    {
      'index': 0,
      'url': 'chrome://extensions/'
    },
    {
      'index': 1,
      'url': 'chrome://settings/'
    },
    {
      'index': 2,
      'url': 'chrome://about/'
    },
    {
      'index': 3,
      'url': 'chrome://newtab/'
    }
  ]
  var tabsInfo2 = [
    {
      'index': 0,
      'url': 'chrome://apps/'
    },
    {
      'index': 1,
      'url': 'chrome://downloads/'
    },
    {
      'index': 2,
      'url': 'chrome://history/'
    },
    {
      'index': 3,
      'url': 'chrome://newtab/'
    }
  ]

  if (tabSetNumber === 2) {
    var tabsInfo = tabsInfo2;
  }
  else {
    var tabsInfo = tabsInfo1;
  }

  for (var i = 0; i < tabsInfo.length; i++) {
    var tabInfo = tabsInfo[i];
    if (asBookmarks === true) {
      tabInfo.parentId = windowOrParentId;
    }
    else {
      tabInfo.windowId = windowOrParentId;
    }
  }
  return tabsInfo;
}

function saveTestSession(windowId, callback) {
  var expectedSessionFolderId;

  getSeshyFolder((seshyFolder) => {
    createSessionBookmarksFolder(seshyFolder, createBookmarksThenSaveMapping);
  });

  function createBookmarksThenSaveMapping(sessionBookmarksFolder) {
    expectedSessionFolderId = sessionBookmarksFolder.id;

    createBookmarks(sessionBookmarksFolder, () => {
      addWindowToSessionMapping(windowId, expectedSessionFolderId, returnSessionFolderId);
    })
  }

  function returnSessionFolderId() {
    callback(expectedSessionFolderId);
  }
}

function createSessionBookmarksFolder(bookmarkTreeNodes, callback) {
  var seshyFolder = bookmarkTreeNodes[0];
  var options = {
    'parentId': seshyFolder.id, // From seshy.js
    'title': 'Test Session'
  }
  chrome.bookmarks.create(options, callback);
}

function createBookmarks(sessionBookmarksFolder, callback) {
  var asBookmarks = true;
  var sessionFolderId = sessionBookmarksFolder.id;
  var bookmarksInfo = getTabsOrBookmarksInfo(sessionFolderId, asBookmarks, 2);

  chrome.bookmarks.create(bookmarksInfo[0]);
  chrome.bookmarks.create(bookmarksInfo[1]);
  chrome.bookmarks.create(bookmarksInfo[2]);

  // TODO Properly identify if function.
  if (typeof callback != 'undefined') {
    chrome.bookmarks.create(bookmarksInfo[3], () => {
      callback(bookmarksInfo);
    });
  }
  else {
    chrome.bookmarks.create(bookmarksInfo[3]);
  }
}

function addWindowToSessionMapping(windowId, expectedSessionFolderId, callback) {
  var items = {};
  items[windowId.toString()] = expectedSessionFolderId;
  chrome.storage.local.set(items, () => {
    callback();
  });
}

function cleanUp() {
  getSeshyFolder(removeBookmarksFolder);
}

function getSeshyFolder(callback) {
  var query = {
    'title': 'Seshy'
  }
  chrome.bookmarks.search(query, callback);
}

function removeBookmarksFolder(bookmarkTreeNodes) {
  bookmarksFolder = bookmarkTreeNodes[0];
  chrome.bookmarks.removeTree(bookmarksFolder.id, getAllWindows);
}

function getAllWindows() {
  chrome.windows.getAll({}, removeWindows);
}

function removeWindows(windows) {
  // Don't remove first window because it will have Jasmine test results.
  for (var i = 1; i < windows.length; i++) {
    var window = windows[i];
    chrome.windows.remove(window.id);
  }
}

function clearLocalStorageAndInitialise() {
  chrome.storage.local.clear(initialise);
}

function getAllLocalStorage(callback) {
  chrome.storage.local.get(null, callback);
}
<commit_msg>Changed unimplemented tests to 'pending' specs.<commit_after>describe("Saving sessions.", function() {

  var windowId;
  var bookmarks;
  var tabsInfo;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, (newWindow) => {
        windowId = newWindow.id
        tabsInfo = getTabsOrBookmarksInfo(newWindow.id, false);
        createTabs(tabsInfo, done);
      });
    }, 1000);
  });

  it("Should be able to save a set of tabs as bookmarks in a folder.", function(done) {
    callTest(done);
  });

  it("Should delete all the bookmarks in the session folder before saving an existing session.", function(done) {
    saveTestSession(windowId, () => {
      callTest(done);
    });
  });

  xit("Saves a session if it is given a name and it is not already saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  })

  xit("Puts the text field for the current session's name into edit mode ready to be saved when the session manager " +
  "is opened and the current session is not already saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  });

  xit("Only saves sessions the user has flagged to be saved.", function(done) {
    console.log("Unimplemented test.");
    done();
  });

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });

  function callTest(done) {
    saveSession(windowId); // Method under test.
    setTimeout(getBookmarksFolder, 1000);

    function getBookmarksFolder() {
      var query = {
        'title': 'Test Session'
      }
      chrome.bookmarks.search(query, getBookmarks);
    }

    function getBookmarks(bookmarkSessionFolderSearchResults) {
      // Only one bookmark session folder with the correct saved tabs ensures that the original bookmarks were deleted.
      expect(bookmarkSessionFolderSearchResults.length).toEqual(1);

      chrome.bookmarks.getChildren(bookmarkSessionFolderSearchResults[0].id, function(bookmarkTreeNodes) {
        bookmarks = bookmarkTreeNodes;
        assertSavedBookmarks(bookmarks, tabsInfo);
      });
    }

    function assertSavedBookmarks(bookmarks, expectedTabsInfo) {
      for (var i = 0; i < bookmarks.length; i++) {
        var bookmark = bookmarks[i];
        var expectedTabInfo = expectedTabsInfo[i];
        expect(bookmark.index).toEqual(expectedTabInfo.index);
        expect(bookmark.url).toEqual(expectedTabInfo.url);
      }
      done();
    }
  }
});

describe("Resuming sessions.", function() {

  describe("User restores a session from the session manager.", function() {

    var windowId;
    var sessionFolderId;
    var bookmarksInfo;

    beforeEach(function(done) {
      clearLocalStorageAndInitialise();
      // Necessary because it takes time to create Seshy folder.
      setTimeout(() => {
        chrome.windows.create({}, (newWindow) => {
          windowId = newWindow.id;
          bookmarksInfo = getTabsOrBookmarksInfo(newWindow.id, false);
          createTabs(bookmarksInfo, saveTestSessionAndCaptureSessionFolderId);
        });
      }, 1000);

      function saveTestSessionAndCaptureSessionFolderId() {
        saveTestSession(windowId, captureSessionFolderId);
      }

      function captureSessionFolderId(newSessionFolderId) {
        sessionFolderId = newSessionFolderId;
        chrome.windows.remove(windowId, () => {
          done();
        });
      }
    });

    it("Adds a window ID to session folder ID mapping in local storage.", function(done) {
      resumeSession(sessionFolderId, () => {
        chrome.storage.local.get(null, assertWindowToSessionFolderMappingAdded)
      });

      function assertWindowToSessionFolderMappingAdded(allLocalStorageObject) {
        var allLocalStorageKeys = Object.keys(allLocalStorageObject);

        var matchingLocalStorageKey;
        var matchingLocalStorageKeyValue;

        for (var i = 0; i < allLocalStorageKeys.length; i++) {
          var localStorageKey = allLocalStorageKeys[i];
          if (localStorageKey == windowId) {
            matchingLocalStorageKey = localStorageKey;
            matchingLocalStorageKeyValue = allLocalStorageObject[windowId.toString()]
          }
        }
        expect(matchingLocalStorageKey).toBe(windowId.toString());
        expect(matchingLocalStorageKeyValue).toBe(sessionFolderId);
        done();
      }
    });

    it("Opens a window with all the tabs as they were when the session was saved.", function(done) {
      resumeSession(sessionFolderId, (newWindow) => {
        assertSessionRestored(newWindow, bookmarksInfo);
      });

      function assertSessionRestored(newWindow, bookmarksInfo) {
        var tabs = newWindow.tabs;

        var expectedTabsNumber = bookmarksInfo.length;
        expect(tabs.length).toBe(expectedTabsNumber);

        var allTabsEqualToBookmarks = true;
        for (var i = 0; i++; i < tabs.length) {
          var tab = tabs[i];
          var bookmark = bookmarksInfo[i];
          if (tabEqualToBookmark(tab, bookmark)) {
            allTabsEqualBookmarks = false;
          }
        }
        expect(allTabsEqualToBookmarks).toBe(true);
        done();
      }
    });

    xit("Focuses the appropriate window if the session is already open.", function(done) {
      console.log("Unimplemented test.");
      done();
    });

    afterEach(function(done) {
      cleanUp();
      // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
      setTimeout(done, 1000);
    });
  })

  describe("Identifying existing session and prompting to resume.", function() {

    // TODO set variables on `this` instead.
    var expectedSessionFolderId;
    var windowToCheck;
    var bookmarksInfo;
    var actualSessionFolderId;

    beforeEach(function(done) {
      clearLocalStorageAndInitialise();
      // Necessary because it takes time to create Seshy folder.
      setTimeout(() => {
        getSeshyFolder(createSessionBookmarksFolderThenBookmarks);
      }, 1000);

      function createSessionBookmarksFolderThenBookmarks(bookmarkTreeNodes) {
        createSessionBookmarksFolder(bookmarkTreeNodes, createBookmarks);
      }

      function createBookmarks(sessionBookmarksFolder) {
        expectedSessionFolderId = sessionBookmarksFolder.id;
        var asBookmarks = true;
        bookmarksInfo = getTabsOrBookmarksInfo(expectedSessionFolderId, asBookmarks);

        chrome.bookmarks.create(bookmarksInfo[0]);
        chrome.bookmarks.create(bookmarksInfo[1]);
        chrome.bookmarks.create(bookmarksInfo[2]);
        chrome.bookmarks.create(bookmarksInfo[3], createWindow);
      }

      function createWindow(bookmarkTreeNode) {
        chrome.windows.create({}, createTabs);
      }

      function createTabs(newWindow) {
        windowToCheck = newWindow;
        var tabsInfo = getTabsOrBookmarksInfo(windowToCheck.id);

        chrome.tabs.create(tabsInfo[0]);
        chrome.tabs.create(tabsInfo[1]);
        chrome.tabs.create(tabsInfo[2], getWindow);
        // Don't create new tab as the new window creates that for us.
      }

      function getWindow() {
        chrome.windows.get(windowToCheck.id, {'populate': true}, callTest);
      }

      function callTest(uptodateWindowToCheck) {
        windowToCheck = uptodateWindowToCheck;
        getSession(windowToCheck, captureExistingSession); // Method under test.
      }

      function captureExistingSession(actualSessionFolder) {
        actualSessionFolderId = actualSessionFolder === null ? null : actualSessionFolder.id;
        done();
      }
    });

    afterEach(function(done) {
      cleanUp();
      // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
      setTimeout(done, 1000);
    });

    it("Should recognise when a set of opened tabs represents an existing session.", function() {
      expect(expectedSessionFolderId).toEqual(actualSessionFolderId);
    });
  });
});

describe("Ending sessions.", function() {

  var windowId;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, addWindowToSessionMapping);
    }, 1000);

    function addWindowToSessionMapping(newWindow) {
      windowId = newWindow.id;
      var fakeSessionFolderId = 1;
      var items = {};
      items[newWindow.id.toString()] = fakeSessionFolderId;
      chrome.storage.local.set(items, done);
    }
  });

  it("Removes any window to session folder mapping from local storage.", function(done) {
    removeWindowToSessionFolderMapping(windowId, () => {
      getAllLocalStorage(assertWindowToSessionFolderMappingRemoved);
    });

    function assertWindowToSessionFolderMappingRemoved(allLocalStorageObject) {
      var allLocalStorageKeys = Object.keys(allLocalStorageObject);

      var matchingLocalStorageKey = false;
      var windowIdString = windowId.toString();

      for (var i = 0; i < allLocalStorageKeys.length; i++) {
        var localStorageKey = allLocalStorageKeys[i];
        if (localStorageKey == windowIdString) {
          matchingLocalStorageKey = true;
        }
      }
      expect(matchingLocalStorageKey).toBe(false);
      done();
    }
  });

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });
});

describe("Deleting sessions.", function() {

  var windowId;
  var expectedDeletedSessionFolderId;

  beforeEach(function(done) {
    clearLocalStorageAndInitialise();
    // Necessary because it takes time to create Seshy folder.
    setTimeout(() => {
      chrome.windows.create({}, (newWindow) => {
        windowId = newWindow.id;
        tabsInfo = getTabsOrBookmarksInfo(newWindow.id, false);
        createTabs(tabsInfo, saveTestSessionAndCaptureSessionFolderId);
      });
    }, 1000);

    function saveTestSessionAndCaptureSessionFolderId() {
      saveTestSession(windowId, captureSessionFolderId);

      function captureSessionFolderId(sessionFolderId) {
        expectedDeletedSessionFolderId = sessionFolderId;
        done();
      }
    }
  });

  it("Deletes the session folder.", function(done) {
    deleteSession(expectedDeletedSessionFolderId, tryGetSessionFolder); // Method under test.

    function tryGetSessionFolder(sessionFolderId) {
      chrome.bookmarks.get(sessionFolderId.toString(), assertSessionFolderDeleted);
      var sessionFolderDeleted = false;

      function assertSessionFolderDeleted(sessionFolderId) {
        if (chrome.runtime.lastError) {
          sessionFolderDeleted = true;
        }
        expect(sessionFolderDeleted).toBe(true);
        done();
      }
    }
  })

  afterEach(function(done) {
    cleanUp();
    // Necessary because it takes time to delete Seshy folder in cleanup of previous test.
    setTimeout(done, 1000);
  });
});

//---===~ Functions ~===------------------------------------------------------------------------------------------------
function createTabs(tabsInfo, callback) {
  chrome.tabs.create(tabsInfo[0]);
  chrome.tabs.create(tabsInfo[1]);
  if (typeof callback != 'undefined') {
    chrome.tabs.create(tabsInfo[2], callback);
  }
  else {
    chrome.tabs.create(tabsInfo[2]);
  }
}

function getTabsOrBookmarksInfo(windowOrParentId, asBookmarks, tabSetNumber) {
  var tabsInfo1 = [
    {
      'index': 0,
      'url': 'chrome://extensions/'
    },
    {
      'index': 1,
      'url': 'chrome://settings/'
    },
    {
      'index': 2,
      'url': 'chrome://about/'
    },
    {
      'index': 3,
      'url': 'chrome://newtab/'
    }
  ]
  var tabsInfo2 = [
    {
      'index': 0,
      'url': 'chrome://apps/'
    },
    {
      'index': 1,
      'url': 'chrome://downloads/'
    },
    {
      'index': 2,
      'url': 'chrome://history/'
    },
    {
      'index': 3,
      'url': 'chrome://newtab/'
    }
  ]

  if (tabSetNumber === 2) {
    var tabsInfo = tabsInfo2;
  }
  else {
    var tabsInfo = tabsInfo1;
  }

  for (var i = 0; i < tabsInfo.length; i++) {
    var tabInfo = tabsInfo[i];
    if (asBookmarks === true) {
      tabInfo.parentId = windowOrParentId;
    }
    else {
      tabInfo.windowId = windowOrParentId;
    }
  }
  return tabsInfo;
}

function saveTestSession(windowId, callback) {
  var expectedSessionFolderId;

  getSeshyFolder((seshyFolder) => {
    createSessionBookmarksFolder(seshyFolder, createBookmarksThenSaveMapping);
  });

  function createBookmarksThenSaveMapping(sessionBookmarksFolder) {
    expectedSessionFolderId = sessionBookmarksFolder.id;

    createBookmarks(sessionBookmarksFolder, () => {
      addWindowToSessionMapping(windowId, expectedSessionFolderId, returnSessionFolderId);
    })
  }

  function returnSessionFolderId() {
    callback(expectedSessionFolderId);
  }
}

function createSessionBookmarksFolder(bookmarkTreeNodes, callback) {
  var seshyFolder = bookmarkTreeNodes[0];
  var options = {
    'parentId': seshyFolder.id, // From seshy.js
    'title': 'Test Session'
  }
  chrome.bookmarks.create(options, callback);
}

function createBookmarks(sessionBookmarksFolder, callback) {
  var asBookmarks = true;
  var sessionFolderId = sessionBookmarksFolder.id;
  var bookmarksInfo = getTabsOrBookmarksInfo(sessionFolderId, asBookmarks, 2);

  chrome.bookmarks.create(bookmarksInfo[0]);
  chrome.bookmarks.create(bookmarksInfo[1]);
  chrome.bookmarks.create(bookmarksInfo[2]);

  // TODO Properly identify if function.
  if (typeof callback != 'undefined') {
    chrome.bookmarks.create(bookmarksInfo[3], () => {
      callback(bookmarksInfo);
    });
  }
  else {
    chrome.bookmarks.create(bookmarksInfo[3]);
  }
}

function addWindowToSessionMapping(windowId, expectedSessionFolderId, callback) {
  var items = {};
  items[windowId.toString()] = expectedSessionFolderId;
  chrome.storage.local.set(items, () => {
    callback();
  });
}

function cleanUp() {
  getSeshyFolder(removeBookmarksFolder);
}

function getSeshyFolder(callback) {
  var query = {
    'title': 'Seshy'
  }
  chrome.bookmarks.search(query, callback);
}

function removeBookmarksFolder(bookmarkTreeNodes) {
  bookmarksFolder = bookmarkTreeNodes[0];
  chrome.bookmarks.removeTree(bookmarksFolder.id, getAllWindows);
}

function getAllWindows() {
  chrome.windows.getAll({}, removeWindows);
}

function removeWindows(windows) {
  // Don't remove first window because it will have Jasmine test results.
  for (var i = 1; i < windows.length; i++) {
    var window = windows[i];
    chrome.windows.remove(window.id);
  }
}

function clearLocalStorageAndInitialise() {
  chrome.storage.local.clear(initialise);
}

function getAllLocalStorage(callback) {
  chrome.storage.local.get(null, callback);
}
<|endoftext|>


<commit_before>const nock = require("nock");
const Webdav = require("../../source/factory");
const { expect } = require("chai");
const DUMMYSERVER = "https://dummy.webdav.server";

describe("Authentication", function() {
    afterEach(() => {
        nock.cleanAll();
    });
    it("should go unauthenticated if no credentials are passed", async () => {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.be.undefined;
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER);
        await webdav.getFileContents("/file");
    });

    it("should use HTTP Basic if user and password are provided", async () => {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.deep.equal(["Basic dXNlcjpwYXNz"]);
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER, "user", "pass");
        await webdav.getFileContents("/file");
    });

    it("should use Bearer if an object is provided", async () => {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.deep.equal(["Bearer ABC123"]);
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER, { token_type: "Bearer", access_token: "ABC123" });
        await webdav.getFileContents("/file");
    });
});
<commit_msg>Use ES5 Syntax node CI node4 tests<commit_after>const nock = require("nock");
const Webdav = require("../../dist/factory");
const { expect } = require("chai");
const DUMMYSERVER = "https://dummy.webdav.server";

describe("Authentication", function() {
    afterEach(function() {
        nock.cleanAll();
    });
    it("should go unauthenticated if no credentials are passed", function() {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.be.undefined;
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER);
        return webdav.getFileContents("/file");
    });

    it("should use HTTP Basic if user and password are provided", function() {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.deep.equal(["Basic dXNlcjpwYXNz"]);
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER, "user", "pass");
        return webdav.getFileContents("/file");
    });

    it("should use Bearer if an object is provided", function() {
        nock(DUMMYSERVER)
            .get("/file")
            .reply(200, function() {
                expect(this.req.headers.authorization).to.deep.equal(["Bearer ABC123"]);
                return "";
            });
        const webdav = Webdav.createClient(DUMMYSERVER, { token_type: "Bearer", access_token: "ABC123" });
        return webdav.getFileContents("/file");
    });
});
<|endoftext|>


<commit_before>var Builder = require('../index');
var builder = new Builder();

var minify = false;

builder.loadConfigSync('./test/fixtures/test-tree.config.js');

builder.config({
  transpiler: false,
  meta: {
    'a.js': {
      format: 'esm'
    },
    'b.js': {
      format: 'esm'
    },
    'global-dep.js': {
      format: 'esm'
    },
    'global-dep-loader.js': {
      format: 'esm'
    }
  },
  paths: {
    '*': './test/fixtures/es-tree/*',
    'global': './test/fixtures/test-tree/global-inner.js'
  }
});

suite('SFX Optimizations', function() {
  test('All ES6 rollup optimization', function(done) {
    builder.buildStatic('a.js', 'test/output/es-sfx.js', { runtime: false, minify: minify, format: 'esm', rollup: true })
    .then(function(output) {
      assert(output.source, 'var b = \'b\';\n\nvar a = \'a\';\n\nexport { a, b };');
      done();
    }, done)
  });

  test('ES6 rollup with a global dep', function(done) {
    builder.buildStatic('global-dep.js', 'test/output/es-sfx.js', { runtime: false, minify: minify, format: 'esm', rollup: true })
    .then(function(output) {
      assert(output.source.indexOf('System.registerDynamic("2"') != -1 && output.source.indexOf(', [\'2\'') != -1);
      done();
    }, done);
  });
});<commit_msg>disable rollup tests in node 10<commit_after>var Builder = require('../index');
var builder = new Builder();

var minify = false;

builder.loadConfigSync('./test/fixtures/test-tree.config.js');

builder.config({
  transpiler: false,
  meta: {
    'a.js': {
      format: 'esm'
    },
    'b.js': {
      format: 'esm'
    },
    'global-dep.js': {
      format: 'esm'
    },
    'global-dep-loader.js': {
      format: 'esm'
    }
  },
  paths: {
    '*': './test/fixtures/es-tree/*',
    'global': './test/fixtures/test-tree/global-inner.js'
  }
});

suite('SFX Optimizations', function() {
  if (process.versions.node && process.versions.node.substr(0, 5) !== '0.10.')
  test('All ES6 rollup optimization', function(done) {
    builder.buildStatic('a.js', 'test/output/es-sfx.js', { runtime: false, minify: minify, format: 'esm', rollup: true })
    .then(function(output) {
      assert(output.source, 'var b = \'b\';\n\nvar a = \'a\';\n\nexport { a, b };');
      done();
    }, done)
  });

  if (process.versions.node && process.versions.node.substr(0, 5) !== '0.10.')
  test('ES6 rollup with a global dep', function(done) {
    builder.buildStatic('global-dep.js', 'test/output/es-sfx.js', { runtime: false, minify: minify, format: 'esm', rollup: true })
    .then(function(output) {
      assert(output.source.indexOf('System.registerDynamic("2"') != -1 && output.source.indexOf(', [\'2\'') != -1);
      done();
    }, done);
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

//Modules Required
var color     = require( 'ansi-color' ).set;
var fs        = require( 'fs'         );
var fsmonitor = require( 'fsmonitor'  );
var jsonlint  = require( 'jsonlint'   );
var prompt    = require( 'cli-prompt' );

//Get my libs
var commands    = require( './libs/commands.js'    );
var env         = require( './libs/env.js'         );
var connections = require( './libs/connections.js' );
var queues      = require( './libs/queues.js'      );

//Load global variables
env.setGlobalVariables();

//Start logs
env.initializeLogs();

//Initialize sript
console.log(color('SyncMaster started...', 'blue'));

//Load argv
argv = process.argv;

//Load configs
try {
    config = fs.readFileSync('./config/user_list.json', 'utf8');
    //Parse user list setup JSON
    config = jsonlint.parse(config);
}
catch (error) {
    //Log error
    errors_log.error(error);
    //Exit with error
    console.log("\n" + color('Failed to load user key files config', 'red') + "\n");
    //End process
    return;
}

//Check for script args
env.checkScriptArgs();

//Load environment
env.loadSyncEnv(machine, origin, target, user, password, key);

//Initialize ssh connection
connections.initializeConnection();

//Log rsync errors
rsync.output(
    function(data) {
        //nothing to do on success
    },
    function(data) {
        //Log to file the std err
        errors_log.error(data);
    }
);

rsync2.output(
    function(data) {
        //nothing to do on success
    },
    function(data) {
        //Log to file the std err
        errors_log.error(data);
    }
);

//Defer prompt's
setTimeout(
    function() {
        //Ask user if wants to syncronize origin from target
        prompt( 'Syncronize all from target? Yes/[No] ', function (val) {
            if ( val === 'n' || val === 'N' || !val ) {
                //Ask user if wants to syncronize all on target
                prompt('Syncronize all to target? [Yes]/No ', function (val) {
                    if ( val[0] === 'y' || val[0] === 'Y' || val[0] === 's' || val[0] === 'S' || !val ) {
                        //Execute the rsync command
                        rsync.execute( function(error, code, cmd) {
                            //Print rsync success
                            console.log(color('Target is syncronized! Lets wait for changes...', 'white'));
                            //Log errors too
                            if (error) {
                                errors_log.error(error);
                            }
                            //start syncronization
                            handleSycronization(user, machine, key, password, origin, target);
                        });
                    }
                    else { //Don't syncronize at start
                        //start syncronization
                        handleSycronization(user, machine, key, password, origin, target);
                    }
                });
            }
            else { //Don't syncronize from target at start
                //Execute the rsync command
                rsync2.execute( function(error, code, cmd) {
                    //Print rsync success
                    console.log(color('Origin is syncronized! Lets wait for changes...', 'white'));
                    //Log errors too
                    if (error) {
                        errors_log.error(error);
                    }
                    //Ask user if wants to syncronize all on target
                    prompt('Syncronize all to target? [Yes]/No ', function (val) {
                        if ( val[0] === 'y' || val[0] === 'Y' || val[0] === 's' || val[0] === 'S' || !val ) {
                            //Execute the rsync command
                            rsync.execute( function(error, code, cmd) {
                                //Print rsync success
                                console.log(color('Target is syncronized! Lets wait for changes...', 'white'));
                                //Log errors too
                                if (error) {
                                    errors_log.error(error);
                                }
                                //start syncronization
                                handleSycronization(user, machine, key, password, origin, target);
                            });
                        }
                        else { //Don't syncronize at start
                            //start syncronization
                            handleSycronization(user, machine, key, password, origin, target);
                        }
                    });
                });
            }
        });
    },
    2000 //wait 1s
);

//Check if there are files on queue to process
//setInterval(
//    function() {
//        console.log(color('Checking file change queue...', 'green'));
//
//        if (fileActionsQueue.length > 0) {
//            console.log( 'There are ' + fileActionsQueue.length + ' changes to process! (1)' );
//
//            queues.processQueues();
//        }
//    },
//    30000
//);

//Main function to maintain syncronization
function handleSycronization(user, machine, key, password, origin, target) {
    //Watch for files changes on origin
    fsmonitor.watch(origin, '', function(change) {
        //File added, upload to target
        if (change.addedFiles) {
            //Loop through files added
            change.addedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'sendFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.sendFile(file, connection);
                    }
                }
            );
        }
        //Test change updated file
        if (change.modifiedFiles) {
            //Loop through files updated
            change.modifiedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'sendFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.sendFile(file, connection);
                    }
                }
            );
        }
        //Test change removed file
        if (change.removedFiles) { //File removed, upload to target
            //Loop through files removed
            change.removedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'removeFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.removeFile(file, connection);
                    }
                }
            );
        }
        //Test change added folder
        if (change.addedFolders) { //Folder added, create on target
            //Loop through files removed
            change.addedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'addFolder'});
                    }
                    else { //We have a ready connection, send file
                        commands.addFolder(folder, connection);
                    }
                }
            );
        }
        //Test change modified folder
        if (change.modifiedFolders) { //Folder updated, change on target
            //Loop through files removed
            change.modifiedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'updateFolder' });
                    }
                    else { //We have a ready connection, send file
                        commands.updateFolder(folder, connection);
                    }
                }
            );
        }
        //Test change remove folder
        if (change.removedFolders) { //Folder removed, removed from target
            //Loop through files removed
            change.removedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'deleteFolder'});
                    }
                    else { //We have a ready connection, send file
                        commands.deleteFolder(folder, connection);
                    }
                }
            );
        }
    });

    console.log(color('Syncronization started...', 'green'));
}

//Handle Process Exceptions
process.on('SIGUSR2', function() {
    //Log signal
    console.log(color('SIGUSR2 signal thriggered!', 'red'));
});

//Handle uncaught exceptions
process.on('uncaughtException', function(err) {
    //Get error trace
    var stack = new Error(err).stack;
    //Log exception
    console.log(color('Uncaught Exception:', 'red+underline'));
    //Log error
    console.error(err);
    //Log stack trace
    console.log(stack);
    //Log error to file
    errors_log.error(err, 'Uncaught Exception');
    //Just as a failsafe rsync files
    //Syncronize file with target
    rsync.execute(function(error, code, cmd) {
        console.log(color('NEED TO RESTART SYNCRONIZATION...', 'red+underline'));
        //Re-Handle Syncronization
        handleSycronization(user, machine, key, password, origin, target);
    });
});
<commit_msg>Fixes process exit<commit_after>#!/usr/bin/env node

'use strict';

//Modules Required
var color     = require( 'ansi-color' ).set;
var fs        = require( 'fs'         );
var fsmonitor = require( 'fsmonitor'  );
var jsonlint  = require( 'jsonlint'   );
var prompt    = require( 'cli-prompt' );

//Get my libs
var commands    = require( './libs/commands.js'    );
var env         = require( './libs/env.js'         );
var connections = require( './libs/connections.js' );
var queues      = require( './libs/queues.js'      );

//Load global variables
env.setGlobalVariables();

//Start logs
env.initializeLogs();

//Initialize sript
console.log(color('SyncMaster started...', 'blue'));

//Load argv
argv = process.argv;

//Load configs
try {
    config = fs.readFileSync('./config/user_list.json', 'utf8');
    //Parse user list setup JSON
    config = jsonlint.parse(config);
}
catch (error) {
    //Log error
    errors_log.error(error);
    //Exit with error
    console.log("\n" + color('Failed to load user key files config', 'red') + "\n");
    //End process
    process.exit(1);
}

//Check for script args
env.checkScriptArgs();

//Load environment
env.loadSyncEnv(machine, origin, target, user, password, key);

//Initialize ssh connection
connections.initializeConnection();

//Log rsync errors
rsync.output(
    function(data) {
        //nothing to do on success
    },
    function(data) {
        //Log to file the std err
        errors_log.error(data);
    }
);

rsync2.output(
    function(data) {
        //nothing to do on success
    },
    function(data) {
        //Log to file the std err
        errors_log.error(data);
    }
);

//Defer prompt's
setTimeout(
    function() {
        //Ask user if wants to syncronize origin from target
        prompt( 'Syncronize all from target? Yes/[No] ', function (val) {
            if ( val === 'n' || val === 'N' || !val ) {
                //Ask user if wants to syncronize all on target
                prompt('Syncronize all to target? [Yes]/No ', function (val) {
                    if ( val[0] === 'y' || val[0] === 'Y' || val[0] === 's' || val[0] === 'S' || !val ) {
                        //Execute the rsync command
                        rsync.execute( function(error, code, cmd) {
                            //Print rsync success
                            console.log(color('Target is syncronized! Lets wait for changes...', 'white'));
                            //Log errors too
                            if (error) {
                                errors_log.error(error);
                            }
                            //start syncronization
                            handleSycronization(user, machine, key, password, origin, target);
                        });
                    }
                    else { //Don't syncronize at start
                        //start syncronization
                        handleSycronization(user, machine, key, password, origin, target);
                    }
                });
            }
            else { //Don't syncronize from target at start
                //Execute the rsync command
                rsync2.execute( function(error, code, cmd) {
                    //Print rsync success
                    console.log(color('Origin is syncronized! Lets wait for changes...', 'white'));
                    //Log errors too
                    if (error) {
                        errors_log.error(error);
                    }
                    //Ask user if wants to syncronize all on target
                    prompt('Syncronize all to target? [Yes]/No ', function (val) {
                        if ( val[0] === 'y' || val[0] === 'Y' || val[0] === 's' || val[0] === 'S' || !val ) {
                            //Execute the rsync command
                            rsync.execute( function(error, code, cmd) {
                                //Print rsync success
                                console.log(color('Target is syncronized! Lets wait for changes...', 'white'));
                                //Log errors too
                                if (error) {
                                    errors_log.error(error);
                                }
                                //start syncronization
                                handleSycronization(user, machine, key, password, origin, target);
                            });
                        }
                        else { //Don't syncronize at start
                            //start syncronization
                            handleSycronization(user, machine, key, password, origin, target);
                        }
                    });
                });
            }
        });
    },
    2000 //wait 1s
);

//Check if there are files on queue to process
//setInterval(
//    function() {
//        console.log(color('Checking file change queue...', 'green'));
//
//        if (fileActionsQueue.length > 0) {
//            console.log( 'There are ' + fileActionsQueue.length + ' changes to process! (1)' );
//
//            queues.processQueues();
//        }
//    },
//    30000
//);

//Main function to maintain syncronization
function handleSycronization(user, machine, key, password, origin, target) {
    //Watch for files changes on origin
    fsmonitor.watch(origin, '', function(change) {
        //File added, upload to target
        if (change.addedFiles) {
            //Loop through files added
            change.addedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'sendFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.sendFile(file, connection);
                    }
                }
            );
        }
        //Test change updated file
        if (change.modifiedFiles) {
            //Loop through files updated
            change.modifiedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'sendFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.sendFile(file, connection);
                    }
                }
            );
        }
        //Test change removed file
        if (change.removedFiles) { //File removed, upload to target
            //Loop through files removed
            change.removedFiles.forEach(
                function(file) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: file, action: 'removeFile'});
                    }
                    else { //We have a ready connection, send file
                        commands.removeFile(file, connection);
                    }
                }
            );
        }
        //Test change added folder
        if (change.addedFolders) { //Folder added, create on target
            //Loop through files removed
            change.addedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'addFolder'});
                    }
                    else { //We have a ready connection, send file
                        commands.addFolder(folder, connection);
                    }
                }
            );
        }
        //Test change modified folder
        if (change.modifiedFolders) { //Folder updated, change on target
            //Loop through files removed
            change.modifiedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'updateFolder' });
                    }
                    else { //We have a ready connection, send file
                        commands.updateFolder(folder, connection);
                    }
                }
            );
        }
        //Test change remove folder
        if (change.removedFolders) { //Folder removed, removed from target
            //Loop through files removed
            change.removedFolders.forEach(
                function(folder) {
                    if (!active_connection) { //Queue file
                        fileActionsQueue.push({path: folder, action: 'deleteFolder'});
                    }
                    else { //We have a ready connection, send file
                        commands.deleteFolder(folder, connection);
                    }
                }
            );
        }
    });

    console.log(color('Syncronization started...', 'green'));
}

//Handle Process Exceptions
process.on('SIGUSR2', function() {
    //Log signal
    console.log(color('SIGUSR2 signal thriggered!', 'red'));
});

//Handle uncaught exceptions
process.on('uncaughtException', function(err) {
    //Get error trace
    var stack = new Error(err).stack;
    //Log exception
    console.log(color('Uncaught Exception:', 'red+underline'));
    //Log error
    console.error(err);
    //Log stack trace
    console.log(stack);
    //Log error to file
    errors_log.error(err, 'Uncaught Exception');
    //Just as a failsafe rsync files
    //Syncronize file with target
    rsync.execute(function(error, code, cmd) {
        console.log(color('NEED TO RESTART SYNCRONIZATION...', 'red+underline'));
        //Re-Handle Syncronization
        handleSycronization(user, machine, key, password, origin, target);
    });
});
<|endoftext|>


<commit_before>/*1* KEEP THIS CODE AT THE TOP TO AVOID LINE NUMBER CHANGES */
/*2*/'use strict';
/*3*/function foo(n) {
/*4*/  return n+42;
/*5*/}
/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var breakpointInFoo = {
  id: 'fake-id-123',
  location: { path: 'test-v8debugapi.js', line: 4 }
};

var assert = require('assert');
var v8debugapi = require('../lib/v8debugapi.js');
var Logger = require('../lib/logger.js');
var config = require('../config.js');
var StatusMessage = require('../lib/apiclasses.js').StatusMessage;

function stateIsClean(api) {
  assert.equal(api.numBreakpoints_(), 0,
    'there should be no breakpoints active');
  assert.equal(api.numListeners_(), 0,
    'there should be no listeners active');
  return true;
}

describe('v8debugapi', function() {
  config.cwd = process.cwd() + '/test';
  var logger = new Logger(config.logLevel);

  var api = v8debugapi.create(logger, config);
  assert.ok(api, 'should be able to create the api');

  beforeEach(function() { assert(stateIsClean(api)); });
  afterEach(function() { assert(stateIsClean(api)); });

  it('should be able to set and remove breakpoints', function() {
    // clone a clean breakpointInFoo
    var bp = {id: breakpointInFoo.id, location: breakpointInFoo.location};
    var result = api.set(bp);
    assert.ok(result);
    assert.equal(api.numBreakpoints_(), 1);
    api.clear(bp);
  });

  it('should accept breakpoint with ids 0 as a valid breakpoint',
    function() {
      var bp = { id: 0, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.clear(bp);
    });

  describe('invalid breakpoints', function() {
    var badBreakpoints = [
      {},
      { id: 'with no location'},
      { id: 'with bad location', location: {}},
      { id: 'with no path', location: {line: 4}},
      { id: 'with no line', location: {path: 'foo.js'}},
      { id: 'with incomplete path', location: {path: 'st-v8debugapi.js', line: 4}}
    ];

    badBreakpoints.forEach(function(bp) {
      it('should reject breakpoint ' + bp.id, function() {
        var result = api.set(bp);
        assert(result === false, 'should return false');
        assert.ok(bp.status);
        assert.ok(bp.status instanceof StatusMessage);
        assert.ok(bp.status.isError);
      });
    });

    it('should reject breakpoint when filename is ambiguous', function() {
      require('./fixtures/a/hello.js');
      require('./fixtures/b/hello.js');
      var bp = {id: 'ambiguous', location: {line: 1, path: 'hello.js'}};
      var result = api.set(bp);
      assert(result === false);
      assert.ok(bp.status);
      assert.ok(bp.status instanceof StatusMessage);
      assert.ok(bp.status.isError);
      assert(bp.status.description.format ===
        api.messages.SOURCE_FILE_AMBIGUOUS);
    });
  });

  function conditionTests(subject, test, expressions) {
    describe(subject, function() {
      expressions.forEach(function(expr) {
        it('should validate breakpoint with condition "'+expr+'"', function() {
          // make a clean copy of breakpointInFoo
          var bp = {
            id: breakpointInFoo.id,
            location: breakpointInFoo.location,
            condition: expr
          };
          var result = api.set(bp);
          test(result);
          api.clear(bp);
        });
      });
    });
  }
  conditionTests('invalid conditions', function(result) { assert(!result); }, [
    // syntax errors
    '*',
    'j+',
    'break',
    ':)',

    // mutability
    'x = 1',
    'var x = 1;',
    'console.log(1)',
    'while (true) ;',
    'return 3',
    'throw new Error()',
    'new Error()',
    'try { 1 }',
    'let me_pass = 1',
    'debugger',
    'function newfunction() { 1 }',
    '{ f: fib(3) }',
    'function () { 1 }',
    '() => { 1 }',
    '1, 2, 3, fib(), 4',
    '!fib()',
    '1+fib()',
    'x++'
  ]);
  conditionTests('valid conditions', assert, [
    'x == 1',
    'x === 1',
    'global <= 1',
    'this + 1',
    '!this',
    'this?this:1',
    '{f: this?1:2}',
    '{f: process.env}',
    '1,2,3,{f:2},4',
    'A[this?this:1]'
  ]);

  describe('path normalization', function() {
    var breakpoints = [
      { id: 'path0', location: {line: 4, path: '/test/test-v8debugapi.js'}},
      { id: 'path1', location: {line: 4, path: 'test/test-v8debugapi.js' }},
      { id: 'path2', location: {line: 4, path: __filename }},
      { id: 'with . in path', location: {path: 'test/./test-v8debugapi.js', line: 4}},
      { id: 'with . in path', location: {path: './test-v8debugapi.js', line: 4}},
      { id: 'with .. in path', location: {path: 'test/../test-v8debugapi.js', line: 4}},
      { id: 'with .. in path', location: {path: '../test/test-v8debugapi.js', line: 4}}
    ];

    breakpoints.forEach(function(bp) {
      it('should handle breakpoint as ' + bp.location.path, function(done) {
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          api.clear(bp);
          done();
        });
        process.nextTick(function() {foo(7);});
      });
    });
  });

  describe('set and wait', function() {

    it('should be possible to wait on a breakpoint', function(done) {
      // clone a clean breakpointInFoo
      var bp = {id: breakpointInFoo.id, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(1);});
    });

    it('should capture state', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {id: breakpointInFoo.id, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);

        var topFrame = bp.stackFrames[0];
        assert.ok(topFrame);
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '2');
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(2);});
    });

    it('should capture state with watch expressions', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        expressions: ['process']
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);
        assert.ok(bp.evaluatedExpressions);

        var topFrame = bp.stackFrames[0];
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '3');

        var watch = bp.evaluatedExpressions[0];
        assert.equal(watch.name, 'process');
        assert.ok(watch.varTableIndex);

        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(3);});
    });

    it('should capture without values for invalid watch expressions', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        expressions: [':)', 'process()', 'process=this']
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);
        assert.ok(bp.evaluatedExpressions);

        for (var i in bp.evaluatedExpressions) {
          var expr = bp.evaluatedExpressions[i];
          assert(expr.status && expr.status.isError);
        }

        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(3);});
    });

    it('should be possible to set conditional breakpoints', function (done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        condition: 'n===5'
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);

        var topFrame = bp.stackFrames[0];
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '5');
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(4); foo(5);});
    });

    it('should be possible to set conditional breakpoints in compiled code',
      function (done) {
        var bp = {
          id: 'coffee-id-1729',
          location: { path: './test/fixtures/coffee/transpile.coffee',
            line: 3 },
          condition: 'if n == 3 then true else false'
        };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);

          var topFrame = bp.stackFrames[0];
          assert.equal(topFrame['function'], 'foo');
          assert.equal(topFrame.arguments[0].name, 'n');
          assert.equal(topFrame.arguments[0].value, '3');
          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(2); tt.foo(3);});
    });

    it('should be possible to view watch expressions in compiled code',
      function(done) {
        var bp = {
            id: 'coffee-id-1729',
            location: { path: './test/fixtures/coffee/transpile.coffee',
              line: 3 },
            expressions: ['if n == 3 then Math.PI * n else n']
          };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);
          assert.ok(bp.variableTable);
          assert.ok(bp.evaluatedExpressions);

          for (var i in bp.evaluatedExpressions) {
            var expr = bp.evaluatedExpressions[i];
            assert(expr.value === String(Math.PI * 3));
          }

          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(3);});
    });

    it('should capture without values for invalid watch expressions in compiled code',
      function(done) {
        var bp = {
            id: 'coffee-id-1729',
            location: { path: './test/fixtures/coffee/transpile.coffee',
              line: 3 },
            expressions: [':)', 'n n, n', 'process=this', '((x) -> x x) n', 'return']
          };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);
          assert.ok(bp.variableTable);
          assert.ok(bp.evaluatedExpressions);

          for (var i in bp.evaluatedExpressions) {
            var expr = bp.evaluatedExpressions[i];
            assert(expr.status && expr.status.isError);
          }

          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(3);});
    });

    it('should remove listener when breakpoint is cleared before hitting',
      function(done) {
        var bp  = {
          id: breakpointInFoo.id,
          location: breakpointInFoo.location,
          condition: 'n===447'
        };
        assert.ok(api.set(bp));
        api.wait(bp, function() {
          assert(false, 'should not reach here');
        });
        process.nextTick(function() {
          foo(6);
          process.nextTick(function() {
            api.clear(bp);
            assert(stateIsClean(api));
            done();
          });
        });
      });

      it('should be possible to set multiple breakpoints at once', function() {
        var bp1 = { id: 'bp1', location: { path: __filename, line: 4 }};
        var bp2 = { id: 'bp2', location: { path: __filename, line: 5 }};
        assert.ok(api.set(bp1));
        assert.ok(api.set(bp2));
        assert.equal(api.numBreakpoints_(), 2);
        api.clear(bp1);
        assert.equal(api.numBreakpoints_(), 1);
        api.clear(bp2);
        assert.equal(api.numBreakpoints_(), 0);
      });

  });

  it('should be possible to set deferred breakpoints');
  it('should be possible to access intercepted properties');
});
<commit_msg>minor fixes to improve coverage<commit_after>/*1* KEEP THIS CODE AT THE TOP TO AVOID LINE NUMBER CHANGES */
/*2*/'use strict';
/*3*/function foo(n) {
/*4*/  return n+42;
/*5*/}
/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var breakpointInFoo = {
  id: 'fake-id-123',
  location: { path: 'test-v8debugapi.js', line: 4 }
};

var assert = require('assert');
var v8debugapi = require('../lib/v8debugapi.js');
var Logger = require('../lib/logger.js');
var config = require('../config.js');
var StatusMessage = require('../lib/apiclasses.js').StatusMessage;

function stateIsClean(api) {
  assert.equal(api.numBreakpoints_(), 0,
    'there should be no breakpoints active');
  assert.equal(api.numListeners_(), 0,
    'there should be no listeners active');
  return true;
}

describe('v8debugapi', function() {
  config.cwd = process.cwd() + '/test';
  var logger = new Logger(config.logLevel);

  var api = v8debugapi.create(logger, config);
  assert.ok(api, 'should be able to create the api');

  beforeEach(function() { assert(stateIsClean(api)); });
  afterEach(function() { assert(stateIsClean(api)); });

  it('should be able to set and remove breakpoints', function() {
    // clone a clean breakpointInFoo
    var bp = {id: breakpointInFoo.id, location: breakpointInFoo.location};
    var result = api.set(bp);
    assert.ok(result);
    assert.equal(api.numBreakpoints_(), 1);
    api.clear(bp);
  });

  it('should accept breakpoint with ids 0 as a valid breakpoint',
    function() {
      var bp = { id: 0, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.clear(bp);
    });

  describe('invalid breakpoints', function() {
    var badBreakpoints = [
      {},
      { id: 'with no location'},
      { id: 'with bad location', location: {}},
      { id: 'with no path', location: {line: 4}},
      { id: 'with no line', location: {path: 'foo.js'}},
      { id: 'with incomplete path', location: {path: 'st-v8debugapi.js', line: 4}}
    ];

    badBreakpoints.forEach(function(bp) {
      it('should reject breakpoint ' + bp.id, function() {
        var result = api.set(bp);
        assert(result === false, 'should return false');
        assert.ok(bp.status);
        assert.ok(bp.status instanceof StatusMessage);
        assert.ok(bp.status.isError);
      });
    });

    it('should reject breakpoint when filename is ambiguous', function() {
      require('./fixtures/a/hello.js');
      require('./fixtures/b/hello.js');
      var bp = {id: 'ambiguous', location: {line: 1, path: 'hello.js'}};
      var result = api.set(bp);
      assert(result === false);
      assert.ok(bp.status);
      assert.ok(bp.status instanceof StatusMessage);
      assert.ok(bp.status.isError);
      assert(bp.status.description.format ===
        api.messages.SOURCE_FILE_AMBIGUOUS);
    });
  });

  function conditionTests(subject, test, expressions) {
    describe(subject, function() {
      expressions.forEach(function(expr) {
        it('should validate breakpoint with condition "'+expr+'"', function() {
          // make a clean copy of breakpointInFoo
          var bp = {
            id: breakpointInFoo.id,
            location: breakpointInFoo.location,
            condition: expr
          };
          var result = api.set(bp);
          test(result);
          api.clear(bp);
        });
      });
    });
  }
  conditionTests('invalid conditions', function(result) { assert(!result); }, [
    // syntax errors
    '*',
    'j+',
    'break',
    ':)',

    // mutability
    'x = 1',
    'var x = 1;',
    'console.log(1)',
    'while (true) ;',
    'return 3',
    'throw new Error()',
    'new Error()',
    'try { 1 }',
    'let me_pass = 1',
    'debugger',
    'function newfunction() { 1 }',
    '{ f: fib(3) }',
    'function () { 1 }',
    '() => { 1 }',
    '1, 2, 3, fib(), 4',
    '!fib()',
    '1+fib()',
    'x++',
    '[1, 2, 3, 4, x = 1, x == 1, x === 1]'
  ]);
  conditionTests('valid conditions', assert, [
    null,
    '',
    ';',
    'x == 1',
    'x === 1',
    'global <= 1',
    'this + 1',
    '!this',
    'this?this:1',
    '{f: this?1:2}',
    '{f: process.env}',
    '1,2,3,{f:2},4',
    'A[this?this:1]',
    '[1, 2, 3, 4, x == 1, x === 1, null, undefined]'
  ]);

  describe('path normalization', function() {
    var breakpoints = [
      { id: 'path0', location: {line: 4, path: '/test/test-v8debugapi.js'}},
      { id: 'path1', location: {line: 4, path: 'test/test-v8debugapi.js' }},
      { id: 'path2', location: {line: 4, path: __filename }},
      { id: 'with . in path', location: {path: 'test/./test-v8debugapi.js', line: 4}},
      { id: 'with . in path', location: {path: './test-v8debugapi.js', line: 4}},
      { id: 'with .. in path', location: {path: 'test/../test-v8debugapi.js', line: 4}},
      { id: 'with .. in path', location: {path: '../test/test-v8debugapi.js', line: 4}}
    ];

    breakpoints.forEach(function(bp) {
      it('should handle breakpoint as ' + bp.location.path, function(done) {
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          api.clear(bp);
          done();
        });
        process.nextTick(function() {foo(7);});
      });
    });
  });

  describe('set and wait', function() {

    it('should be possible to wait on a breakpoint', function(done) {
      // clone a clean breakpointInFoo
      var bp = {id: breakpointInFoo.id, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(1);});
    });

    it('should capture state', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {id: breakpointInFoo.id, location: breakpointInFoo.location};
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);

        var topFrame = bp.stackFrames[0];
        assert.ok(topFrame);
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '2');
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(2);});
    });

    it('should capture state with watch expressions', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        expressions: ['process']
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);
        assert.ok(bp.evaluatedExpressions);

        var topFrame = bp.stackFrames[0];
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '3');

        var watch = bp.evaluatedExpressions[0];
        assert.equal(watch.name, 'process');
        assert.ok(watch.varTableIndex);

        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(3);});
    });

    it('should capture without values for invalid watch expressions', function(done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        expressions: [':)', 'process()', 'process=this']
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);
        assert.ok(bp.variableTable);
        assert.ok(bp.evaluatedExpressions);

        for (var i in bp.evaluatedExpressions) {
          var expr = bp.evaluatedExpressions[i];
          assert(expr.status && expr.status.isError);
        }

        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(3);});
    });

    it('should be possible to set conditional breakpoints', function (done) {
      // clone a clean breakpointInFoo
      var bp  = {
        id: breakpointInFoo.id,
        location: breakpointInFoo.location,
        condition: 'n===5'
      };
      var result = api.set(bp);
      assert.ok(result);
      api.wait(bp, function(err) {
        assert.ifError(err);
        assert.ok(bp.stackFrames);

        var topFrame = bp.stackFrames[0];
        assert.equal(topFrame['function'], 'foo');
        assert.equal(topFrame.arguments[0].name, 'n');
        assert.equal(topFrame.arguments[0].value, '5');
        api.clear(bp);
        done();
      });
      process.nextTick(function() {foo(4); foo(5);});
    });

    it('should be possible to set conditional breakpoints in compiled code',
      function (done) {
        var bp = {
          id: 'coffee-id-1729',
          location: { path: './test/fixtures/coffee/transpile.coffee',
            line: 3 },
          condition: 'if n == 3 then true else false'
        };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);

          var topFrame = bp.stackFrames[0];
          assert.equal(topFrame['function'], 'foo');
          assert.equal(topFrame.arguments[0].name, 'n');
          assert.equal(topFrame.arguments[0].value, '3');
          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(2); tt.foo(3);});
    });

    it('should be possible to view watch expressions in compiled code',
      function(done) {
        var bp = {
            id: 'coffee-id-1729',
            location: { path: './test/fixtures/coffee/transpile.coffee',
              line: 3 },
            expressions: ['if n == 3 then Math.PI * n else n']
          };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);
          assert.ok(bp.variableTable);
          assert.ok(bp.evaluatedExpressions);

          for (var i in bp.evaluatedExpressions) {
            var expr = bp.evaluatedExpressions[i];
            assert(expr.value === String(Math.PI * 3));
          }

          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(3);});
    });

    it('should capture without values for invalid watch expressions in compiled code',
      function(done) {
        var bp = {
            id: 'coffee-id-1729',
            location: { path: './test/fixtures/coffee/transpile.coffee',
              line: 3 },
            expressions: [':)', 'n n, n', 'process=this', '((x) -> x x) n', 'return']
          };
        var tt = require('./fixtures/coffee/transpile');
        var result = api.set(bp);
        assert.ok(result);
        api.wait(bp, function(err) {
          assert.ifError(err);
          assert.ok(bp.stackFrames);
          assert.ok(bp.variableTable);
          assert.ok(bp.evaluatedExpressions);

          for (var i in bp.evaluatedExpressions) {
            var expr = bp.evaluatedExpressions[i];
            assert(expr.status && expr.status.isError);
          }

          api.clear(bp);
          done();
        });
        process.nextTick(function() {tt.foo(3);});
    });

    it('should remove listener when breakpoint is cleared before hitting',
      function(done) {
        var bp  = {
          id: breakpointInFoo.id,
          location: breakpointInFoo.location,
          condition: 'n===447'
        };
        assert.ok(api.set(bp));
        api.wait(bp, function() {
          assert(false, 'should not reach here');
        });
        process.nextTick(function() {
          foo(6);
          process.nextTick(function() {
            api.clear(bp);
            assert(stateIsClean(api));
            done();
          });
        });
      });

      it('should be possible to set multiple breakpoints at once', function() {
        var bp1 = { id: 'bp1', location: { path: __filename, line: 4 }};
        var bp2 = { id: 'bp2', location: { path: __filename, line: 5 }};
        assert.ok(api.set(bp1));
        assert.ok(api.set(bp2));
        assert.equal(api.numBreakpoints_(), 2);
        api.clear(bp1);
        assert.equal(api.numBreakpoints_(), 1);
        api.clear(bp2);
        assert.equal(api.numBreakpoints_(), 0);
      });

  });

  it('should be possible to set deferred breakpoints');
  it('should be possible to access intercepted properties');
});
<|endoftext|>