Programmatically change Angular routes in Puppeteer without page refresh

I’m working on a project where I need to take screenshots of different pages in an Angular app using Puppeteer. The problem is that when I use page.goto(), it causes a full page reload. This isn’t ideal since Angular’s client-side routing should allow for smoother transitions.

I’ve tried clicking on routerLink elements, which works fine:

await page.click('a[routerLink="/dashboard"]');

But what I really want is a way to programmatically navigate to different routes without relying on existing links in the DOM. Is there a way to use something similar to Angular’s Router.navigate() method through Puppeteer?

I’m looking for a solution that doesn’t trigger a full page reload for each route change. Any ideas on how to achieve this would be greatly appreciated!

I’ve faced a similar challenge in my work with Puppeteer and Angular apps. One effective approach I’ve found is to leverage Angular’s window.history API. You can execute a script in the context of the page to programmatically change routes without a full reload:

await page.evaluate(() => {
  window.history.pushState({}, '', '/your-new-route');
  window.dispatchEvent(new Event('popstate'));
});

This method mimics how Angular’s router works internally. The ‘popstate’ event triggers Angular to re-evaluate the current route and update the view accordingly. It’s been reliable in my experience and doesn’t cause the unwanted page refresh. Just make sure your app is fully loaded before attempting this navigation method.

hey, i’ve had success with this approach:

await page.evaluate(() => {
const angularApp = document.querySelector(‘app-root’);
const router = angularApp.ngContext[1].get(Router);
router.navigateByUrl(‘/new-route’);
});

it uses angular’s internal api to grab the router and navigate. no page reload, works great for screenshots!

Having worked extensively with Puppeteer and Angular, I can share a technique that’s worked well for me. Instead of using page.goto() or clicking on links, you can inject JavaScript directly into the page to manipulate Angular’s router. Here’s how I’ve done it:

await page.evaluate(() => {
  const router = window.ng.getComponent(document.querySelector('app-root')).injector.get('Router');
  router.navigate(['/your-desired-route']);
});

This approach accesses Angular’s Router service directly and uses its navigate method. It avoids full page reloads and works seamlessly with Angular’s routing system. Just ensure your app is fully loaded before executing this code.

One caveat: this method assumes your Angular app exposes the ng object globally. If it doesn’t, you might need to adjust the code slightly to locate the router instance. It’s been a reliable solution in my projects, allowing for smooth transitions between routes when taking screenshots with Puppeteer.