@@ -35,19 +35,33 @@ export class TodoPage {
3535 this . filterLinks = page . locator ( "#filters a" ) ;
3636 }
3737
38+ /**
39+ * Wait for one animation frame to allow maquette to render
40+ */
41+ async waitForAnimationFrame ( ) : Promise < void > {
42+ await this . page . evaluate (
43+ ( ) => new Promise ( ( resolve ) => requestAnimationFrame ( ( ) => resolve ( undefined ) ) )
44+ ) ;
45+ }
46+
3847 /**
3948 * Navigate to the TodoMVC application
4049 */
41- async goto ( ) {
50+ async goto ( ) : Promise < void > {
4251 await this . page . goto ( "/examples/todomvc/index.html" ) ;
52+ // Clear any existing data and reload for a fresh state
53+ await this . page . evaluate ( ( ) => {
54+ window . localStorage . removeItem ( "todomvc-maquette" ) ;
55+ } ) ;
56+ await this . page . reload ( ) ;
4357 // Wait for the app to be ready
4458 await this . newTodoInput . waitFor ( ) ;
4559 }
4660
4761 /**
4862 * Clear localStorage to reset application state
4963 */
50- async clearStorage ( ) {
64+ async clearStorage ( ) : Promise < void > {
5165 await this . page . evaluate ( ( ) => {
5266 window . localStorage . setItem ( "todomvc-maquette" , "" ) ;
5367 } ) ;
@@ -56,17 +70,17 @@ export class TodoPage {
5670 /**
5771 * Add a new todo item
5872 */
59- async addTodo ( text : string ) {
73+ async addTodo ( text : string ) : Promise < void > {
6074 await this . newTodoInput . fill ( text ) ;
6175 await this . newTodoInput . press ( "Enter" ) ;
62- // Wait for the UI to update
63- await this . page . waitForTimeout ( 50 ) ;
76+ // Wait for maquette to render
77+ await this . waitForAnimationFrame ( ) ;
6478 }
6579
6680 /**
6781 * Add multiple todo items
6882 */
69- async addTodos ( ...texts : string [ ] ) {
83+ async addTodos ( ...texts : string [ ] ) : Promise < void > {
7084 for ( const text of texts ) {
7185 await this . addTodo ( text ) ;
7286 }
@@ -82,23 +96,25 @@ export class TodoPage {
8296 /**
8397 * Toggle a todo item at the given index
8498 */
85- async toggleTodoAt ( index : number ) {
99+ async toggleTodoAt ( index : number ) : Promise < void > {
86100 await this . todoItems . nth ( index ) . locator ( ".toggle" ) . click ( ) ;
87- await this . page . waitForTimeout ( 50 ) ;
101+ // Wait for maquette to render
102+ await this . waitForAnimationFrame ( ) ;
88103 }
89104
90105 /**
91106 * Double-click a todo item to edit it
92107 */
93- async doubleClickTodoAt ( index : number ) {
108+ async doubleClickTodoAt ( index : number ) : Promise < void > {
94109 await this . todoItems . nth ( index ) . locator ( "label" ) . dblclick ( ) ;
95- await this . page . waitForTimeout ( 50 ) ;
110+ // Wait for maquette to render
111+ await this . waitForAnimationFrame ( ) ;
96112 }
97113
98114 /**
99115 * Edit the currently focused todo item
100116 */
101- async editTodo ( text : string , options ?: { submit ?: "enter" | "escape" | "blur" } ) {
117+ async editTodo ( text : string , options ?: { submit ?: "enter" | "escape" | "blur" } ) : Promise < void > {
102118 const editInput = this . todoList . locator ( "input.edit" ) ;
103119 await editInput . clear ( ) ;
104120 await editInput . fill ( text ) ;
@@ -112,84 +128,91 @@ export class TodoPage {
112128 // Click somewhere else to blur
113129 await this . toggleAll . focus ( ) ;
114130 }
115- await this . page . waitForTimeout ( 50 ) ;
131+ // Wait for maquette to render
132+ await this . waitForAnimationFrame ( ) ;
116133 }
117134
118135 /**
119136 * Click the "Mark all as completed" checkbox
120137 */
121- async toggleAll_click ( ) {
138+ async toggleAll_click ( ) : Promise < void > {
122139 await this . toggleAll . click ( ) ;
123- await this . page . waitForTimeout ( 50 ) ;
140+ // Wait for maquette to render
141+ await this . waitForAnimationFrame ( ) ;
124142 }
125143
126144 /**
127145 * Click the "Clear completed" button
128146 */
129- async clickClearCompleted ( ) {
147+ async clickClearCompleted ( ) : Promise < void > {
130148 await this . clearCompletedButton . click ( ) ;
131- await this . page . waitForTimeout ( 50 ) ;
149+ // Wait for maquette to render
150+ await this . waitForAnimationFrame ( ) ;
132151 }
133152
134153 /**
135154 * Filter by "All" items
136155 */
137- async filterAll ( ) {
156+ async filterAll ( ) : Promise < void > {
138157 await this . filterLinks . nth ( 0 ) . click ( ) ;
139- await this . page . waitForTimeout ( 50 ) ;
158+ // Wait for maquette to render
159+ await this . waitForAnimationFrame ( ) ;
140160 }
141161
142162 /**
143163 * Filter by "Active" items
144164 */
145- async filterActive ( ) {
165+ async filterActive ( ) : Promise < void > {
146166 await this . filterLinks . nth ( 1 ) . click ( ) ;
147- await this . page . waitForTimeout ( 50 ) ;
167+ // Wait for maquette to render
168+ await this . waitForAnimationFrame ( ) ;
148169 }
149170
150171 /**
151172 * Filter by "Completed" items
152173 */
153- async filterCompleted ( ) {
174+ async filterCompleted ( ) : Promise < void > {
154175 await this . filterLinks . nth ( 2 ) . click ( ) ;
155- await this . page . waitForTimeout ( 50 ) ;
176+ // Wait for maquette to render
177+ await this . waitForAnimationFrame ( ) ;
156178 }
157179
158180 /**
159181 * Go back in browser history
160182 */
161- async goBack ( ) {
183+ async goBack ( ) : Promise < void > {
162184 await this . page . goBack ( ) ;
163- await this . page . waitForTimeout ( 50 ) ;
185+ // Wait for maquette to render after navigation
186+ await this . waitForAnimationFrame ( ) ;
164187 }
165188
166189 // ==================== Assertions ====================
167190
168191 /**
169192 * Assert the new todo input is focused
170193 */
171- async assertInputFocused ( ) {
194+ async assertInputFocused ( ) : Promise < void > {
172195 await expect ( this . newTodoInput ) . toBeFocused ( ) ;
173196 }
174197
175198 /**
176199 * Assert the todo items match the expected texts
177200 */
178- async assertTodos ( expected : string [ ] ) {
201+ async assertTodos ( expected : string [ ] ) : Promise < void > {
179202 await expect ( this . todoItems . locator ( "label" ) ) . toHaveText ( expected ) ;
180203 }
181204
182205 /**
183206 * Assert the new todo input is empty
184207 */
185- async assertInputEmpty ( ) {
208+ async assertInputEmpty ( ) : Promise < void > {
186209 await expect ( this . newTodoInput ) . toHaveValue ( "" ) ;
187210 }
188211
189212 /**
190213 * Assert the main section visibility
191214 */
192- async assertMainSectionVisible ( visible : boolean ) {
215+ async assertMainSectionVisible ( visible : boolean ) : Promise < void > {
193216 if ( visible ) {
194217 await expect ( this . mainSection ) . toBeVisible ( ) ;
195218 } else {
@@ -200,7 +223,7 @@ export class TodoPage {
200223 /**
201224 * Assert the footer visibility
202225 */
203- async assertFooterVisible ( visible : boolean ) {
226+ async assertFooterVisible ( visible : boolean ) : Promise < void > {
204227 if ( visible ) {
205228 await expect ( this . footer ) . toBeVisible ( ) ;
206229 } else {
@@ -211,7 +234,7 @@ export class TodoPage {
211234 /**
212235 * Assert which items are completed
213236 */
214- async assertCompletedStates ( expectedStates : boolean [ ] ) {
237+ async assertCompletedStates ( expectedStates : boolean [ ] ) : Promise < void > {
215238 const count = await this . todoItems . count ( ) ;
216239 expect ( count ) . toBe ( expectedStates . length ) ;
217240
@@ -228,7 +251,7 @@ export class TodoPage {
228251 /**
229252 * Assert the "mark all" checkbox is checked
230253 */
231- async assertToggleAllChecked ( checked : boolean ) {
254+ async assertToggleAllChecked ( checked : boolean ) : Promise < void > {
232255 if ( checked ) {
233256 await expect ( this . toggleAll ) . toBeChecked ( ) ;
234257 } else {
@@ -239,21 +262,21 @@ export class TodoPage {
239262 /**
240263 * Assert the todo count text
241264 */
242- async assertTodoCount ( expected : string ) {
265+ async assertTodoCount ( expected : string ) : Promise < void > {
243266 await expect ( this . todoCount ) . toHaveText ( expected ) ;
244267 }
245268
246269 /**
247270 * Assert the clear completed button text
248271 */
249- async assertClearCompletedText ( expected : string ) {
272+ async assertClearCompletedText ( expected : string ) : Promise < void > {
250273 await expect ( this . clearCompletedButton ) . toHaveText ( expected ) ;
251274 }
252275
253276 /**
254277 * Assert the clear completed button visibility
255278 */
256- async assertClearCompletedVisible ( visible : boolean ) {
279+ async assertClearCompletedVisible ( visible : boolean ) : Promise < void > {
257280 if ( visible ) {
258281 await expect ( this . clearCompletedButton ) . toBeVisible ( ) ;
259282 } else {
@@ -264,21 +287,21 @@ export class TodoPage {
264287 /**
265288 * Assert which filter is currently selected
266289 */
267- async assertFilterSelected ( index : number ) {
290+ async assertFilterSelected ( index : number ) : Promise < void > {
268291 await expect ( this . filterLinks . nth ( index ) ) . toHaveClass ( "selected" ) ;
269292 }
270293
271294 /**
272295 * Assert the toggle checkbox is hidden for item at index (during editing)
273296 */
274- async assertItemToggleHidden ( index : number ) {
297+ async assertItemToggleHidden ( index : number ) : Promise < void > {
275298 await expect ( this . todoItems . nth ( index ) . locator ( ".toggle" ) ) . toBeHidden ( ) ;
276299 }
277300
278301 /**
279302 * Assert the label is hidden for item at index (during editing)
280303 */
281- async assertItemLabelHidden ( index : number ) {
304+ async assertItemLabelHidden ( index : number ) : Promise < void > {
282305 await expect ( this . todoItems . nth ( index ) . locator ( "label" ) ) . toBeHidden ( ) ;
283306 }
284307}
0 commit comments