@@ -10,7 +10,7 @@ import {
1010 CustomizationThemeMode ,
1111} from '@gitbook/api' ;
1212import type { GitBookStandalone } from '@gitbook/embed' ;
13- import { expect } from '@playwright/test' ;
13+ import { type FrameLocator , type Locator , expect , test } from '@playwright/test' ;
1414import jwt from 'jsonwebtoken' ;
1515
1616import {
@@ -63,6 +63,43 @@ const overrideAIResponse = () => {
6363 } ) ;
6464} ;
6565
66+ const CLOUDFLARE_TEXTS = [
67+ 'Checking if the site connection is secure' ,
68+ 'Please stand by, while we are checking your browser' ,
69+ 'DDoS protection by Cloudflare' ,
70+ 'Just a moment...' ,
71+ ] ;
72+
73+ async function isCloudflareChallenge ( iframe : FrameLocator ) {
74+ for ( const text of CLOUDFLARE_TEXTS ) {
75+ const visible = await iframe
76+ . getByText ( text , { exact : false } )
77+ . first ( )
78+ . isVisible ( { timeout : 500 } )
79+ . catch ( ( ) => false ) ;
80+ if ( visible ) {
81+ return true ;
82+ }
83+ }
84+ return false ;
85+ }
86+
87+ async function waitForEmbedVisible ( iframe : FrameLocator , locator : Locator , timeout = 30_000 ) {
88+ if ( await isCloudflareChallenge ( iframe ) ) {
89+ test . skip ( true , 'Cloudflare challenge detected in embed iframe' ) ;
90+ }
91+ try {
92+ await locator . waitFor ( { state : 'visible' , timeout } ) ;
93+ } catch ( error ) {
94+ if ( await isCloudflareChallenge ( iframe ) ) {
95+ test . skip ( true , 'Cloudflare challenge detected in embed iframe' ) ;
96+ }
97+ throw error ;
98+ }
99+ await expect ( locator ) . toBeVisible ( { timeout } ) ;
100+ return locator ;
101+ }
102+
66103const searchTestCases : Test [ ] = [
67104 {
68105 name : 'Search - AI Mode: None - Complete flow' ,
@@ -1983,12 +2020,10 @@ const testCases: TestsCase[] = [
19832020 await expect ( page . locator ( '#gitbook-widget-window' ) ) . toBeVisible ( ) ;
19842021 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
19852022 await iframe . getByTestId ( 'embed-tab-docs' ) . click ( ) ; // Switch to docs tab
1986- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
1987- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
1988- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2023+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
19892024
19902025 await iframe . getByTestId ( 'embed-tab-assistant' ) . click ( ) ; // Switch to assistant tab
1991- await expect ( iframe . getByTestId ( 'ai-chat' ) ) . toBeVisible ( ) ;
2026+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'ai-chat' ) ) ;
19922027
19932028 await iframe . owner ( ) . evaluate ( overrideAIInitialState ) ;
19942029 } ,
@@ -2003,9 +2038,7 @@ const testCases: TestsCase[] = [
20032038 } ) ;
20042039 await expect ( page . locator ( '#gitbook-widget-window' ) ) . toBeVisible ( ) ;
20052040 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2006- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
2007- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
2008- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2041+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
20092042 await expect ( iframe . owner ( ) ) . toHaveAttribute (
20102043 'src' ,
20112044 expect . stringContaining ( 'getting-started/quickstart' )
@@ -2021,7 +2054,7 @@ const testCases: TestsCase[] = [
20212054 GitBook ( 'postUserMessage' , aiPrompt ) ;
20222055 } , AI_PROMPT ) ;
20232056 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2024- await expect ( iframe . getByTestId ( 'ai-chat' ) ) . toBeVisible ( ) ;
2057+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'ai-chat' ) ) ;
20252058 await expect ( iframe . getByTestId ( 'ai-chat-message-user' ) . first ( ) ) . toHaveText (
20262059 AI_PROMPT
20272060 ) ;
@@ -2065,9 +2098,11 @@ const testCases: TestsCase[] = [
20652098 } ) ;
20662099 } ) ;
20672100 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2068- await expect (
2069- iframe . getByTestId ( 'ai-chat-suggested-question' ) . nth ( 0 )
2070- ) . toHaveText ( 'What is GitBook?' ) ;
2101+ const firstSuggestion = await waitForEmbedVisible (
2102+ iframe ,
2103+ iframe . getByTestId ( 'ai-chat-suggested-question' ) . first ( )
2104+ ) ;
2105+ await expect ( firstSuggestion ) . toHaveText ( 'What is GitBook?' ) ;
20712106 await expect (
20722107 iframe . getByTestId ( 'ai-chat-suggested-question' ) . nth ( 1 )
20732108 ) . toHaveText ( 'How do I get started?' ) ;
@@ -2124,14 +2159,19 @@ const testCases: TestsCase[] = [
21242159 } ) ;
21252160 } , AI_PROMPT ) ;
21262161 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2127- await expect ( iframe . getByTestId ( 'embed-action' ) ) . toHaveCount ( 4 ) ;
2162+ await waitForEmbedVisible (
2163+ iframe ,
2164+ iframe . getByTestId ( 'embed-action' ) . first ( ) ,
2165+ 30_000
2166+ ) ;
2167+ await expect ( iframe . getByTestId ( 'embed-action' ) ) . toHaveCount ( 4 , {
2168+ timeout : 30_000 ,
2169+ } ) ;
21282170 const actions = iframe . getByTestId ( 'embed-action' ) ;
21292171
21302172 await expect ( actions . nth ( 0 ) ) . toHaveAccessibleName ( 'Open internal link' ) ;
21312173 await actions . nth ( 0 ) . click ( ) ;
2132- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
2133- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
2134- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2174+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
21352175 await expect ( iframe . owner ( ) ) . toHaveAttribute (
21362176 'src' ,
21372177 expect . stringContaining ( 'getting-started/quickstart' )
@@ -2201,9 +2241,7 @@ const testCases: TestsCase[] = [
22012241 const toolConfirmation = iframe
22022242 . getByTestId ( 'ai-chat-tool-confirmation' )
22032243 . first ( ) ;
2204- await expect ( toolConfirmation ) . toBeVisible ( {
2205- timeout : 30000 ,
2206- } ) ;
2244+ await waitForEmbedVisible ( iframe , toolConfirmation , 30_000 ) ;
22072245 await page . waitForTimeout ( 10000 ) ;
22082246 await iframe . owner ( ) . evaluate ( overrideAIResponse ) ;
22092247 } ,
@@ -2220,9 +2258,7 @@ const testCases: TestsCase[] = [
22202258 run : async ( page ) => {
22212259 await expect ( page . locator ( '#gitbook-widget-window' ) ) . toBeVisible ( ) ;
22222260 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2223- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
2224- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
2225- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2261+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
22262262 } ,
22272263 } ,
22282264 {
@@ -2231,9 +2267,7 @@ const testCases: TestsCase[] = [
22312267 run : async ( page ) => {
22322268 await expect ( page . locator ( '#gitbook-widget-window' ) ) . toBeVisible ( ) ;
22332269 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2234- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
2235- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
2236- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2270+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
22372271 const tocButton = iframe . getByTestId ( 'toc-button' ) ;
22382272 await expect ( tocButton ) . toBeVisible ( ) ;
22392273 await tocButton . click ( ) ;
@@ -2246,9 +2280,7 @@ const testCases: TestsCase[] = [
22462280 run : async ( page ) => {
22472281 await expect ( page . locator ( '#gitbook-widget-window' ) ) . toBeVisible ( ) ;
22482282 const iframe = page . frameLocator ( '#gitbook-widget-iframe' ) ;
2249- const docsPage = iframe . getByTestId ( 'embed-docs-page' ) ;
2250- await docsPage . waitFor ( { state : 'visible' , timeout : 10000 } ) ;
2251- await expect ( docsPage ) . toBeVisible ( { timeout : 10000 } ) ;
2283+ await waitForEmbedVisible ( iframe , iframe . getByTestId ( 'embed-docs-page' ) ) ;
22522284 const openInNewTabButton = iframe . getByTestId (
22532285 'embed-docs-page-open-in-new-tab'
22542286 ) ;
0 commit comments