1+ import { Page , Locator } from '@playwright/test' ;
2+ import { AdminPageBase } from '@models/AdminPageBase' ;
3+
4+ export class ArticleFormPage extends AdminPageBase {
5+ // Form fields
6+ readonly titleField : Locator ;
7+ readonly urlField : Locator ;
8+ readonly summaryField : Locator ;
9+ readonly metaKeywordsField : Locator ;
10+ readonly metaDescriptionField : Locator ;
11+ readonly counterField : Locator ;
12+ readonly contentFrame : Locator ;
13+ readonly imageThumbUrlField : Locator ;
14+ readonly imageUrlField : Locator ;
15+ readonly articleTypeField : Locator ;
16+ readonly publishDateField : Locator ;
17+ readonly statusDropdown : Locator ;
18+ readonly descriptionField : Locator ;
19+
20+ // Buttons
21+ readonly saveButton : Locator ;
22+ readonly saveAndExitButton : Locator ;
23+ readonly publishButton : Locator ;
24+ readonly cancelButton : Locator ;
25+ readonly randomUrlButton : Locator ;
26+
27+ // Article type dropdown elements
28+ readonly articleTypeDropdown : Locator ;
29+
30+ constructor ( page : Page ) {
31+ super ( page ) ;
32+ // Form fields locators
33+ this . titleField = page . locator ( '#Title' ) ;
34+ this . urlField = page . locator ( '#Url' ) ;
35+ this . summaryField = page . locator ( '#Summary' ) ;
36+ this . metaKeywordsField = page . locator ( '#MetaKeyWords' ) ;
37+ this . metaDescriptionField = page . locator ( '#MetaDescription' ) ;
38+ this . counterField = page . locator ( '#Counter' ) ;
39+ this . contentFrame = page . locator ( '#ArticleContent' ) ;
40+ this . imageThumbUrlField = page . locator ( '#ImageThumbUrl' ) ;
41+ this . imageUrlField = page . locator ( '#ImageUrl' ) ;
42+ this . articleTypeField = page . locator ( '#ArticleTypeID' ) ;
43+ this . publishDateField = page . locator ( '#PublishDate' ) ;
44+ this . statusDropdown = page . locator ( '#Status' ) ;
45+ this . descriptionField = page . locator ( '#Description' ) ;
46+
47+ // Button locators
48+ this . saveButton = page . locator ( 'input[data-value="Create"]' ) ;
49+ this . saveAndExitButton = page . locator ( 'input[data-value="CreateAndExit"]' ) ;
50+ this . publishButton = page . locator ( 'input[data-value="Publish"]' ) ;
51+ this . cancelButton = page . getByRole ( 'link' , { name : '取消' } ) ;
52+ this . randomUrlButton = page . locator ( '#Url' ) . locator ( '..' ) . getByRole ( 'link' ) ;
53+
54+ // Article type dropdown elements
55+ this . articleTypeDropdown = page . locator ( '#dropdown-tree-ArticleTypeID > .form-control' ) ;
56+ }
57+
58+ /**
59+ * Navigates to the default page for this page model
60+ */
61+ async navigateTo ( ) : Promise < void > {
62+ await this . page . goto ( '/admin/article/create' ) ;
63+ // should wait tinymce to load
64+ await this . page . frameLocator ( '#ArticleContent_ifr' ) . locator ( '#tinymce' ) . waitFor ( ) ;
65+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
66+ }
67+
68+ /**
69+ * Navigates to the article creation page
70+ */
71+ async navigateToCreate ( ) : Promise < void > {
72+ await this . page . goto ( '/admin/article/create' ) ;
73+ }
74+
75+ /**
76+ * Navigates to the edit page for a specific article
77+ * @param articleId The ID of the article to edit
78+ */
79+ async navigateToEdit ( articleId : string ) : Promise < void > {
80+ await this . page . goto ( `/admin/article/edit/${ articleId } ` ) ;
81+ }
82+
83+ /**
84+ * Fills the article form with provided data
85+ * @param articleData The data to fill in the form
86+ */
87+ async fillArticleForm ( articleData : {
88+ title ?: string ,
89+ url ?: string ,
90+ summary ?: string ,
91+ metaKeywords ?: string ,
92+ metaDescription ?: string ,
93+ counter ?: string ,
94+ content ?: string ,
95+ imageThumbUrl ?: string ,
96+ imageUrl ?: string ,
97+ articleType ?: string ,
98+ publishDate ?: string ,
99+ status ?: string ,
100+ description ?: string
101+ } ) : Promise < void > {
102+ if ( articleData . title ) await this . titleField . fill ( articleData . title ) ;
103+ if ( articleData . url ) await this . urlField . fill ( articleData . url ) ;
104+ if ( articleData . summary ) await this . summaryField . fill ( articleData . summary ) ;
105+ if ( articleData . metaKeywords ) await this . metaKeywordsField . fill ( articleData . metaKeywords ) ;
106+ if ( articleData . metaDescription ) await this . metaDescriptionField . fill ( articleData . metaDescription ) ;
107+ if ( articleData . counter ) await this . counterField . fill ( articleData . counter ) ;
108+ if ( articleData . content ) await this . page . locator ( '#ArticleContent_ifr' ) . contentFrame ( ) . locator ( '#tinymce' ) . fill ( articleData . content ) ;
109+ if ( articleData . imageThumbUrl ) await this . imageThumbUrlField . fill ( articleData . imageThumbUrl ) ;
110+ if ( articleData . imageUrl ) await this . imageUrlField . fill ( articleData . imageUrl ) ;
111+ if ( articleData . publishDate ) await this . publishDateField . fill ( articleData . publishDate ) ;
112+ if ( articleData . description ) await this . descriptionField . fill ( articleData . description ) ;
113+
114+ // Select article type if provided
115+ if ( articleData . articleType ) {
116+ await this . selectArticleType ( articleData . articleType ) ;
117+ }
118+
119+ // Select status if provided
120+ if ( articleData . status ) {
121+ await this . statusDropdown . selectOption ( articleData . status ) ;
122+ }
123+ }
124+
125+ /**
126+ * Selects an article type from the dropdown tree
127+ * @param articleType The article type to select
128+ */
129+ async selectArticleType ( articleType : string ) : Promise < void > {
130+ // Click the dropdown to open it
131+ if ( await this . articleTypeDropdown . isVisible ( ) ) {
132+ await this . articleTypeDropdown . click ( ) ;
133+ }
134+
135+ const articleTypeOption = this . page . getByRole ( 'treeitem' , { name : articleType , exact : true } ) ;
136+ await articleTypeOption . click ( ) ;
137+ }
138+
139+ /**
140+ * Generates a random URL
141+ */
142+ async generateRandomUrl ( ) : Promise < void > {
143+ await this . randomUrlButton . click ( ) ;
144+ }
145+
146+ /**
147+ * Saves the article form
148+ */
149+ async saveArticle ( ) : Promise < void > {
150+ await this . saveButton . click ( ) ;
151+ }
152+
153+ /**
154+ * Saves the article and exits the form
155+ */
156+ async saveAndExit ( ) : Promise < void > {
157+ await this . saveAndExitButton . click ( ) ;
158+ }
159+
160+ /**
161+ * Publishes the article
162+ */
163+ async publishArticle ( ) : Promise < void > {
164+ await this . publishButton . click ( ) ;
165+ }
166+
167+ /**
168+ * Cancels the form and returns to the previous page
169+ */
170+ async cancel ( ) : Promise < void > {
171+ await this . cancelButton . click ( ) ;
172+ }
173+ }
0 commit comments