Productivity App Testing Guide
How to Test Notion Onboarding: Workspace Setup, Templates & Block Editor
A scenario-by-scenario walkthrough of testing Notion workspace onboarding with Playwright. Template gallery selection, keyboard-driven block editor interactions, drag-and-drop page organization, workspace settings, member invitations, and the pitfalls that break real onboarding test suites.
“Notion surpassed 100 million users in 2024, with workspace onboarding being the first experience every team encounters before adopting the platform.”
Notion (2024 company announcement)
Notion Workspace Onboarding Flow
1. Why Testing Notion Workspace Onboarding Is Harder Than It Looks
Notion workspace onboarding looks straightforward on the surface: sign up, name your workspace, pick a use case, choose some templates, and start editing. But under the hood, the experience is built on a rich client-side application that makes heavy use of keyboard shortcuts, contentEditable regions, drag-and-drop interactions, and dynamically rendered block trees. Every one of those patterns is notoriously difficult to automate with Playwright.
The template gallery is the first challenge. When a new user selects a use case (engineering, design, marketing, personal), Notion presents a curated set of templates with live previews. These templates are not static HTML pages. They are rendered as interactive block trees that load asynchronously, with skeleton placeholders that transition to real content. Your test needs to wait for the template preview to fully render before asserting on its contents, and the timing varies significantly based on template complexity.
The block editor is the second major obstacle. Notion's editor is built on contentEditable elements with a custom input handling layer that intercepts keyboard events. Standard Playwright fill() calls do not work reliably because Notion captures keydown events and routes them through its own command system. You need page.keyboard.type() and page.keyboard.press() to simulate real keystrokes. Slash commands (typing/ to open the block menu) require precise timing between the slash keystroke and the subsequent selection.
Drag-and-drop page organization is the third pain point. The sidebar allows users to reorder pages, nest them inside other pages, and move them between sections. Playwright's native drag API works inconsistently with Notion's custom drag handlers because Notion uses a virtual drag layer with its own hit detection. You often need to simulate the full mouse event sequence (mousedown, multiple mousemove events, mouseup) with precise coordinates.
Finally, workspace settings involve modals, permission dropdowns, email invitation forms, and plan selection screens that load asynchronously. Each modal has its own focus trap, and clicking outside dismisses it, which means stray mouse events in your test can close a settings panel before your assertions run.
Notion Onboarding Step Sequence
Sign Up
Email or Google OAuth
Workspace Name
Name and icon
Use Case
Team type selection
Template Gallery
Pick starter templates
Invite Members
Email invitations
Workspace Home
Landing page with templates
Block Editor Input Pipeline
Keystroke
User presses key
Event Capture
Notion intercepts keydown
Command Router
Slash, markdown, or text
Block Update
Virtual DOM patch
Render
contentEditable reflects change
A thorough Notion onboarding test suite must handle all of these surfaces. The sections below walk through each scenario with runnable Playwright TypeScript you can paste into a real project.
2. Setting Up a Reliable Test Environment
Notion does not offer a public API for creating or deleting workspaces programmatically, so your test environment setup requires a different strategy than API-first products like Auth0 or Stripe. You need a dedicated test account, a clean workspace for each test run, and a way to reset state between runs.
Notion Test Environment Checklist
- Create a dedicated Notion account using a test email (e.g., test+notion@yourcompany.com)
- Use a fresh workspace for each test suite run (delete via settings after each run)
- Store session cookies using Playwright storageState to avoid re-authentication
- Configure Playwright for a 30-second navigation timeout (template loading is slow)
- Set viewport to 1280x800 minimum (Notion sidebar collapses on narrow viewports)
- Disable Notion's onboarding tooltips using localStorage flags when possible
- Use a stable network connection (Notion's real-time sync is sensitive to latency)
- Pin the Playwright browser version to avoid rendering differences across updates
Environment Variables
Playwright Configuration
Notion is a heavy client-side application with aggressive lazy loading. Your Playwright config needs generous timeouts, a fixed viewport size, and permission for clipboard access (Notion uses clipboard heavily for copy-paste between blocks).
Authentication Helper
Since Notion does not expose a headless authentication API, your global setup must log in through the browser and save the session. Use Playwright's storageState to persist cookies across test projects.
3. Scenario: Workspace Creation Wizard
The workspace creation wizard is the first thing a new Notion user sees after signing up. It collects a workspace name, an optional icon, a use case selection (team engineering, design, product, personal), and the team size. Each step transitions with an animation, and the wizard does not expose traditional form inputs. Instead, it uses clickable cards for use case selection and a contentEditable field for the workspace name.
Complete Workspace Creation Wizard
ModerateGoal
Navigate through the full workspace creation wizard, set a workspace name, select a use case, and arrive at the workspace home page with the correct workspace name displayed.
Preconditions
- Authenticated Notion account with no existing workspaces
- Browser viewport at least 1280x800
Playwright Implementation
Assrt Equivalent
# scenarios/notion-workspace-creation.assrt
describe: Complete workspace creation wizard
given:
- I am logged in to a Notion account with no workspaces
- I am on the onboarding page
steps:
- type "QA Test Workspace" into the workspace name field
- click "Continue"
- select the "Engineering" use case card
- click "Continue"
- select "Just me" for team size
- click "Continue"
expect:
- the sidebar is visible within 30 seconds
- the sidebar shows "QA Test Workspace"
- at least one default page exists in the sidebarWorkspace Creation: Playwright vs Assrt
import { test, expect } from '@playwright/test';
test('workspace creation wizard', async ({ page }) => {
await page.goto('https://www.notion.so/onboarding');
const nameInput = page.locator('[data-testid="workspace-name-input"]');
await nameInput.click();
await page.keyboard.type('QA Test Workspace');
await page.getByRole('button', { name: /continue/i }).click();
await page.waitForSelector('[data-testid="usecase-card"]');
const card = page.locator(
'[data-testid="usecase-card"]:has-text("Engineering")'
);
await card.click();
await page.getByRole('button', { name: /continue/i }).click();
await page.locator(
'[data-testid="team-size-option"]:has-text("Just me")'
).click();
await page.getByRole('button', { name: /continue/i }).click();
await page.waitForSelector('[data-testid="sidebar"]', {
timeout: 30_000,
});
const name = page.locator(
'[data-testid="sidebar-workspace-switcher"]'
);
await expect(name).toContainText('QA Test Workspace');
});4. Scenario: Template Gallery Selection
The template gallery is one of Notion's most important onboarding surfaces. After creating a workspace, users are presented with a gallery of pre-built templates organized by category: project management, meeting notes, engineering wiki, product roadmap, and more. Each template card shows a live preview that loads asynchronously, and clicking “Use this template” duplicates the entire block tree into the user's workspace. Testing this flow requires handling asynchronous content loading, verifying the duplicated page structure, and confirming that all template blocks rendered correctly.
Template Gallery Selection and Duplication
ComplexGoal
Browse the template gallery, select a template, duplicate it into the workspace, and verify the resulting page contains the expected block structure.
Preconditions
- Authenticated session with an existing workspace
- Workspace has no custom pages yet (clean state)
Playwright Implementation
What to Assert Beyond the UI
Template Duplication Assertions
- Page URL contains a valid 32-character hex ID
- At least 3 content blocks rendered (heading, text, table or list)
- Page title matches the template name
- Sidebar reflects the new page in the correct section
- No skeleton loaders remain after 10 seconds
- Sub-pages from the template are also duplicated (if applicable)
Template Gallery: Playwright vs Assrt
import { test, expect } from '@playwright/test';
test('template gallery: select and duplicate', async ({ page }) => {
await page.goto('https://www.notion.so');
await page.waitForSelector('[data-testid="sidebar"]');
await page.getByRole('button', { name: /templates/i }).click();
await page.waitForSelector('[data-testid="template-gallery"]');
await page.locator(
'[data-testid="template-category"]:has-text("Engineering")'
).click();
const cards = page.locator('[data-testid="template-card"]');
await expect(cards.first()).toBeVisible();
await cards.first().click();
await page.waitForSelector(
'[data-testid="template-preview-content"]'
);
await page.getByRole('button', {
name: /use this template/i,
}).click();
await page.waitForURL(/\/[a-f0-9]{32}/);
const blocks = page.locator('[data-block-id]');
expect(await blocks.count()).toBeGreaterThan(3);
});5. Scenario: Block Editor Keyboard Interactions
Notion's block editor is the core of the product, and testing it requires understanding how Notion handles keyboard input. Unlike a standard textarea or input field, Notion's editor uses contentEditable divs with a custom event handler layer. Calling locator.fill() will not work because Notion intercepts and re-routes keydown events through its own command pipeline. You must use page.keyboard.type() for text input and page.keyboard.press() for shortcuts and special keys.
Slash commands are Notion's power feature. Typing/ opens a searchable command menu that lets users create headings, toggle lists, callout blocks, code blocks, databases, and more. Testing slash commands requires typing the slash, waiting for the menu to appear, typing a filter query, and then pressing Enter or clicking the correct menu item. The menu is a floating overlay positioned relative to the cursor, and it updates its contents as you type.
Block Editor: Text Input and Slash Commands
ComplexGoal
Create a new page, type text into the block editor using keyboard simulation, use slash commands to create different block types, and verify the resulting block structure.
Preconditions
- Authenticated session with an existing workspace
- No tooltip overlays blocking the editor area
Playwright Implementation
Keyboard Shortcuts Reference
Notion supports over 40 keyboard shortcuts in the editor. Here are the most important ones to test during onboarding flows, along with the Playwright method to trigger each.
Assrt Equivalent
# scenarios/notion-block-editor.assrt
describe: Block editor text input and slash commands
given:
- I am logged in to my workspace
- I create a new blank page
steps:
- type "E2E Test Page" as the page title
- press Enter to move to the first content block
- type "This is an automated test paragraph."
- press Enter
- type "/" to open the slash command menu
- type "heading 2" and press Enter
- type "Test Section Heading"
- press Enter
- type "/" and select "to-do"
- type "First task item" and press Enter
- type "Second task item"
expect:
- the page title is "E2E Test Page"
- a heading "Test Section Heading" is visible
- two to-do items are visible
- at least 4 content blocks exist on the page6. Scenario: Drag-and-Drop Page Organization
Notion's sidebar allows users to organize pages by dragging them into different positions and nesting them under other pages. This is a critical part of workspace onboarding because new users need to organize the templates and pages they have created into a coherent structure. Testing drag-and-drop in Notion is notoriously difficult because Notion uses a custom virtual drag layer that does not respond reliably to Playwright's built-in dragTo() method.
The reliable approach is to simulate the full mouse event sequence: mousedown on the source element, a series of mousemove events along the drag path, and mouseup on the target. You also need to account for Notion's drop indicators, which are thin colored lines that appear between items or indented under a parent page. The drop indicator position determines whether the page is placed before, after, or nested inside the target.
Sidebar Drag-and-Drop Page Nesting
ComplexGoal
Drag a page in the sidebar and nest it under another page, then verify the page hierarchy updated correctly.
Playwright Implementation
Assrt Equivalent
# scenarios/notion-drag-drop-sidebar.assrt
describe: Nest a page under another page via drag-and-drop
given:
- I am logged in to my workspace
- "Child Page" and "Parent Page" exist in the sidebar
steps:
- drag "Child Page" onto "Parent Page" in the sidebar
- wait for the page hierarchy to update
expect:
- "Child Page" is nested under "Parent Page"
- expanding "Parent Page" reveals "Child Page" as a sub-page7. Scenario: Workspace Settings and Member Invitations
Workspace settings are a key part of the onboarding experience, especially for team workspaces. New workspace owners need to configure the workspace name, icon, allowed email domains, and default permissions. They also need to invite team members via email. All of this happens inside modal dialogs that load asynchronously and have their own focus management.
Workspace Settings and Email Invitation
ModerateGoal
Open workspace settings, update the workspace name and icon, invite a team member via email, and verify the invitation was sent.
Playwright Implementation
Assrt Equivalent
# scenarios/notion-workspace-settings.assrt
describe: Update workspace settings and invite a member
given:
- I am logged in as the workspace owner
steps:
- open workspace settings from the sidebar
- change the workspace name to "Updated Workspace Name"
- click "Update"
- go to the Members tab
- invite a new member by entering their email
- click "Invite"
expect:
- a success message appears for the invitation
- the invited email shows in the member list
- the sidebar reflects "Updated Workspace Name"8. Scenario: Mobile Responsive Onboarding
Notion's onboarding flow adapts to mobile viewports, and a significant portion of new signups happen on mobile devices. On narrow screens, the sidebar collapses into a hamburger menu, the template gallery switches to a vertical scroll layout, and the block editor adjusts its toolbar positioning. Testing the mobile experience requires a separate Playwright project with a mobile viewport and touch emulation.
Mobile Viewport Onboarding Flow
ModerateGoal
Complete the workspace creation wizard on a mobile viewport, verify the sidebar is accessible via hamburger menu, and confirm template selection works with a vertical layout.
Playwright Implementation
Assrt Equivalent
# scenarios/notion-mobile-onboarding.assrt
describe: Mobile workspace onboarding flow
device: iPhone 14
given:
- I am on the onboarding page on a mobile device
steps:
- type "Mobile Test Workspace" as the workspace name
- click "Continue"
- select the "Personal" use case
- click "Continue" twice
expect:
- a hamburger menu icon is visible
- tapping the hamburger menu reveals the sidebar
- the sidebar shows "Mobile Test Workspace"
- at least one default page is listed9. Common Pitfalls That Break Notion Onboarding Tests
Using fill() Instead of keyboard.type() in the Block Editor
The most common mistake when automating Notion is using Playwright's fill()method on contentEditable elements. Notion's editor intercepts keyboard events at the document level and routes them through its own command pipeline. The fill()method sets the value programmatically, bypassing Notion's input handlers entirely. This causes the block content to appear visually but not be registered by Notion's internal state, leading to data loss on save. Always use page.keyboard.type() for any text entry in the Notion editor.
Insufficient Timeouts for Template Loading
Notion templates load asynchronously, and complex templates (like project management boards with multiple database views) can take 10 to 15 seconds to fully render. Playwright's default 5-second timeout will cause intermittent failures. Use explicit waitForSelector calls with 15-second timeouts for template content, and add an additional check that skeleton loaders have disappeared before asserting on block content.
Onboarding Tooltips and Coach Marks Blocking Interactions
Notion shows onboarding tooltips, coach marks, and feature announcement banners to new users. These overlays can intercept click events intended for buttons or editor elements. Dismiss them explicitly at the start of each test by looking for known tooltip selectors like[data-testid="tooltip-dismiss"] and clicking them. Alternatively, set localStorage flags before navigation to suppress tooltips:page.evaluate(() => localStorage.setItem('hasSeenOnboardingTooltips', 'true')).
Notion's Real-Time Sync Causing Race Conditions
Notion syncs changes in real time via WebSocket connections. If your test types text and immediately reads it back from the DOM, you may hit a race condition where Notion's sync layer has not yet committed the change. This is especially problematic with the sidebar, which updates asynchronously when new pages are created. Add a short wait or use expect().toContainText()with Playwright's auto-retry behavior instead of reading the DOM directly.
Drag-and-Drop Failing Silently
Playwright's dragTo()method dispatches a simplified drag event sequence that Notion's custom drag handler may not recognize. The drag appears to execute (no error is thrown), but the page order does not change. Always verify the result after a drag operation. If the order has not changed, fall back to the manual mouse event sequence with small incremental moves (mousedown, multiple mousemove events at 10-pixel intervals, mouseup) as shown in Section 6. The incremental moves are necessary because Notion only activates its drop target detection after the pointer moves a minimum distance from the drag origin.
Notion Test Suite Anti-Patterns
- Using fill() on contentEditable elements in the block editor
- Using default 5-second timeouts for template loading
- Ignoring onboarding tooltips that block click targets
- Reading DOM immediately after typing without waiting for sync
- Using dragTo() for sidebar page reordering
- Hardcoding Notion selectors that change between releases
- Running tests without clearing workspace state between runs
- Testing on a viewport narrower than 1280px without mobile-specific assertions
10. Writing These Scenarios in Plain English with Assrt
Every scenario above requires deep knowledge of Notion's internal DOM structure: data-testid attributes that may change between releases, contentEditable quirks, custom drag handlers, and floating menu positioning. The block editor scenario alone is 50+ lines of Playwright TypeScript with precise timing for slash command menus. Multiply that by eight scenarios and you have a test suite that is fragile, hard to read, and expensive to maintain.
Assrt lets you describe what you want to test in plain English. The framework resolves selectors at runtime, adapts to DOM changes, and regenerates the underlying Playwright code when Notion updates its interface. Your scenario descriptions stay stable even when Notion renames a data-testid attribute, moves a button, or restructures its template gallery layout.
Here is the complete onboarding suite from Sections 3 through 8 compiled into a single Assrt file. Notice how the drag-and-drop scenario, which required 40+ lines of manual mouse event simulation in Playwright, becomes a single step in Assrt.
Assrt compiles each scenario block into the same Playwright TypeScript you saw in the preceding sections. The compiled tests are committed to your repo as real, runnable spec files that you can inspect, modify, and run directly with npx playwright test. When Notion updates its DOM structure, renames a button, or changes the template gallery layout, Assrt detects the failure, analyzes the new DOM, and opens a pull request with updated selectors. Your scenario descriptions stay untouched.
Start with the workspace creation wizard. Once it is green in CI, add the template gallery scenario, then the block editor with slash commands, then drag-and-drop, then workspace settings. Within an afternoon, you can have complete Notion onboarding coverage that most teams never achieve by writing raw Playwright scripts.
Related Guides
How to Test CodeMirror
A practical, scenario-by-scenario guide to testing CodeMirror 6 editors with Playwright....
How to Test Lexical Editor
A practical, scenario-by-scenario guide to testing Lexical rich text editors with...
How to Test Monaco Editor
A practical, scenario-by-scenario guide to testing Monaco Editor with Playwright. Covers...
Ready to automate your testing?
Assrt discovers test scenarios, writes Playwright tests from plain English, and self-heals when your UI changes.