Google Search runs JavaScript with an evergreen version of Chromium, and processes JavaScript web apps in three phases: crawling, rendering and indexing. Googlebot checks robots.txt, fetches the URL, and queues pages with a 200 status for rendering unless a robots meta tag or header says not to index them. The page may wait in that queue for a few seconds or longer, and a headless Chromium then renders it. Google also notes that server-side or pre-rendering remains a good idea because not all bots can run JavaScript (Understand JavaScript SEO Basics).
Google’s troubleshooting guide lists the traps. The rendering service does not keep cookies, Local Storage or Session Storage across page loads. Googlebot declines permission requests such as camera access. URL fragments cannot be relied on to load different views, so single-page apps should use the History API. Error pages that return 200 can be indexed as soft 404s, so a real error status, or a redirect to one, is needed (Fix Search-Related JavaScript Problems). Lazy-loaded content must load when it enters the viewport, because Google Search does not interact with your page by scrolling or clicking (Fix Lazy-Loaded Website Content).
We cover JavaScript SEO as part of technical SEO. On the technical SEO page it sits under the question of whether the content is really there: JavaScript, lazy loading and blocked resources.