Short answer
Do not set ignoreSynchronization globally. Leave Angular synchronization on by default, and toggle it off only around the specific steps that touch non-Angular pages, then turn it back on immediately. The flag is session-wide, not per-page, so a global true silently removes all of Protractor's built-in waiting and makes your Angular tests flaky.
Why the default hangs on mixed apps
With synchronization enabled (the default), Protractor waits for Angular's $http and $timeout queues to drain before each command. On a server-rendered or static page there is no Angular to signal, so the wait either fails or times out. That is the only situation the flag exists for.
The per-step pattern
Use the modern API browser.waitForAngularEnabled(). The older browser.ignoreSynchronization = true still works in many versions but is deprecated in later releases — check which your installed version supports.
async function visitStaticPage(url) {
await browser.waitForAngularEnabled(false);
await browser.driver.get(url); // use driver.get, not browser.get
// sync is off: add explicit waits, Protractor no longer waits for you
const el = element(by.css('#content'));
await browser.wait(ExpectedConditions.visibilityOf(el), 5000);
// ... assertions ...
await browser.waitForAngularEnabled(true); // re-enable before Angular navigation
}
Two details matter here:
- Explicit waits while disabled. With sync off, Protractor will not wait for page loads or element stability. Every interaction on the non-Angular page needs an
ExpectedConditions wait (or equivalent), otherwise you trade hangs for race conditions. - Always re-enable. Forgetting
waitForAngularEnabled(true) is the most common cause of "works locally, flakes in CI" — the next Angular test runs with no synchronization and passes or fails unpredictably depending on machine speed. Wrap the toggle in a helper (or try/finally) so it cannot be skipped.
Deciding the value per environment
The correct value is determined by the page, not the environment. If local and CI behave differently, the cause is usually timing (lazy bundles loading slower in CI), not a need for a different flag value. Fix that with longer explicit-wait timeouts in CI config, not by changing synchronization. The exception: if an Angular page never stabilizes because of polling ($interval, long-polling), synchronization will hang no matter what — the real fix is moving that work outside Angular's zone, not disabling sync globally.
Lightweight verification
- Write one test that disables sync, loads a known static page, asserts an element, re-enables sync, then loads an Angular page. Both halves should pass with no timeout.
- Log
await browser.waitForAngularEnabled() at each step to confirm the flag actually toggles where you think it does. - Run the suite once with sync left disabled throughout: Angular tests should get flaky. That confirms the toggling — not luck — is what stabilizes them.
Note: Protractor is end-of-life, so treat this as maintenance knowledge; new suites should target Playwright, WebdriverIO, or Cypress, which handle Angular waiting differently.