@@ -3,7 +3,7 @@ import * as cp from "child_process"
33import { promises as fs } from "fs"
44import * as path from "path"
55import { Page } from "playwright"
6- import util from "util"
6+ import * as util from "util"
77import { logError , plural } from "../../../src/common/util"
88import { onLine } from "../../../src/node/util"
99import { PASSWORD , workspaceDir } from "../../utils/constants"
@@ -38,12 +38,13 @@ export class CodeServer {
3838 private process : Promise < CodeServerProcess > | undefined
3939 public readonly logger : Logger
4040 private closed = false
41- private _workspaceDir : Promise < string > | undefined
4241
4342 constructor (
4443 name : string ,
45- private readonly codeServerArgs : string [ ] ,
46- private readonly codeServerEnv : NodeJS . ProcessEnv ,
44+ private readonly args : string [ ] ,
45+ private readonly env : NodeJS . ProcessEnv ,
46+ private readonly _workspaceDir : Promise < string > | string | undefined ,
47+ private readonly entry = process . env . CODE_SERVER_TEST_ENTRY || "." ,
4748 ) {
4849 this . logger = logger . named ( name )
4950 }
@@ -75,7 +76,7 @@ export class CodeServer {
7576 */
7677 private async createWorkspace ( ) : Promise < string > {
7778 const dir = await this . workspaceDir
78- await fs . mkdir ( path . join ( dir , "User" ) )
79+ await fs . mkdir ( path . join ( dir , "User" ) , { recursive : true } )
7980 await fs . writeFile (
8081 path . join ( dir , "User/settings.json" ) ,
8182 JSON . stringify ( {
@@ -96,36 +97,33 @@ export class CodeServer {
9697 const dir = await this . createWorkspace ( )
9798
9899 return new Promise ( ( resolve , reject ) => {
99- this . logger . debug ( "spawning" )
100- const proc = cp . spawn (
101- "node" ,
102- [
103- process . env . CODE_SERVER_TEST_ENTRY || "." ,
104- "--extensions-dir" ,
105- path . join ( dir , "extensions" ) ,
106- ...this . codeServerArgs ,
107- // Using port zero will spawn on a random port.
108- "--bind-addr" ,
109- "127.0.0.1:0" ,
110- // Setting the XDG variables would be easier and more thorough but the
111- // modules we import ignores those variables for non-Linux operating
112- // systems so use these flags instead.
113- "--config" ,
114- path . join ( dir , "config.yaml" ) ,
115- "--user-data-dir" ,
116- dir ,
117- // The last argument is the workspace to open.
118- dir ,
119- ] ,
120- {
121- cwd : path . join ( __dirname , "../../.." ) ,
122- env : {
123- ...process . env ,
124- ...this . codeServerEnv ,
125- PASSWORD ,
126- } ,
100+ const args = [
101+ this . entry ,
102+ "--extensions-dir" ,
103+ path . join ( dir , "extensions" ) ,
104+ ...this . args ,
105+ // Using port zero will spawn on a random port.
106+ "--bind-addr" ,
107+ "127.0.0.1:0" ,
108+ // Setting the XDG variables would be easier and more thorough but the
109+ // modules we import ignores those variables for non-Linux operating
110+ // systems so use these flags instead.
111+ "--config" ,
112+ path . join ( dir , "config.yaml" ) ,
113+ "--user-data-dir" ,
114+ dir ,
115+ // The last argument is the workspace to open.
116+ dir ,
117+ ]
118+ this . logger . debug ( "spawning `node " + args . join ( " " ) + "`" )
119+ const proc = cp . spawn ( "node" , args , {
120+ cwd : path . join ( __dirname , "../../.." ) ,
121+ env : {
122+ ...process . env ,
123+ ...this . env ,
124+ PASSWORD ,
127125 } ,
128- )
126+ } )
129127
130128 const timer = idleTimer ( "Failed to extract address; did the format change?" , reject )
131129
@@ -136,7 +134,7 @@ export class CodeServer {
136134 } )
137135
138136 proc . on ( "close" , ( code ) => {
139- const error = new Error ( "closed unexpectedly" )
137+ const error = new Error ( "code-server closed unexpectedly" )
140138 if ( ! this . closed ) {
141139 this . logger . error ( error . message , field ( "code" , code ) )
142140 }
@@ -153,7 +151,7 @@ export class CodeServer {
153151 timer . reset ( )
154152
155153 // Log the line without the timestamp.
156- this . logger . trace ( line . replace ( / \[ .+ \] / , "" ) )
154+ this . logger . debug ( line . replace ( / \[ .+ \] / , "" ) )
157155 if ( resolved ) {
158156 return
159157 }
@@ -194,7 +192,11 @@ export class CodeServer {
194192export class CodeServerPage {
195193 private readonly editorSelector = "div.monaco-workbench"
196194
197- constructor ( private readonly codeServer : CodeServer , public readonly page : Page ) {
195+ constructor (
196+ private readonly codeServer : CodeServer ,
197+ public readonly page : Page ,
198+ private readonly authenticated : boolean ,
199+ ) {
198200 this . page . on ( "console" , ( message ) => {
199201 this . codeServer . logger . debug ( message )
200202 } )
@@ -215,11 +217,18 @@ export class CodeServerPage {
215217 }
216218
217219 /**
218- * Navigate to a code-server endpoint. By default go to the root.
220+ * Navigate to a code-server endpoint (root by default). Then wait for the
221+ * editor to become available.
219222 */
220223 async navigate ( endpoint = "/" ) {
221224 const to = new URL ( endpoint , await this . codeServer . address ( ) )
222225 await this . page . goto ( to . toString ( ) , { waitUntil : "networkidle" } )
226+
227+ // Only reload editor if authenticated. Otherwise we'll get stuck
228+ // reloading the login page.
229+ if ( this . authenticated ) {
230+ await this . reloadUntilEditorIsReady ( )
231+ }
223232 }
224233
225234 /**
@@ -456,21 +465,7 @@ export class CodeServerPage {
456465 }
457466
458467 /**
459- * Navigates to code-server then reloads until the editor is ready.
460- *
461- * It is recommended to run setup before using this model in any tests.
462- */
463- async setup ( authenticated : boolean , endpoint = "/" ) {
464- await this . navigate ( endpoint )
465- // If we aren't authenticated we'll see a login page so we can't wait until
466- // the editor is ready.
467- if ( authenticated ) {
468- await this . reloadUntilEditorIsReady ( )
469- }
470- }
471-
472- /**
473- * Execute a command in t root of the instance's workspace directory.
468+ * Execute a command in the root of the instance's workspace directory.
474469 */
475470 async exec ( command : string ) : Promise < void > {
476471 await util . promisify ( cp . exec ) ( command , {
@@ -488,4 +483,15 @@ export class CodeServerPage {
488483 cwd : path . join ( __dirname , "../../.." ) ,
489484 } )
490485 }
486+
487+ /**
488+ * Wait for state to be flushed to the database.
489+ */
490+ async stateFlush ( ) : Promise < void > {
491+ // If we reload too quickly VS Code will be unable to save the state changes
492+ // so wait until those have been written to the database. It flushes every
493+ // five seconds so we need to wait at least that long.
494+ // TODO@asher : There must be a better way.
495+ await this . page . waitForTimeout ( 5500 )
496+ }
491497}
0 commit comments