1717from __future__ import annotations
1818
1919from enum import Enum
20- from typing import Dict
20+ from typing import Any , Dict
2121
2222
2323class FieldType (Enum ):
@@ -48,18 +48,19 @@ class ProjectMetadataForm:
4848 "プロジェクトの分野" : FieldType .POWER_SELECT ,
4949 }
5050
51- def __init__ (self , page ):
51+ def __init__ (self , page , parent_locator = None ):
5252 self .page = page
53+ self ._root = parent_locator or page
5354
5455 def _get_locator (self , label : str , field_type : FieldType ):
5556 base = "//*"
5657 match field_type :
5758 case FieldType .INPUT :
58- return self .page .locator (
59+ return self ._root .locator (
5960 f'{ base } [contains(text(), "{ label } ")]/../following-sibling::div[1]//input'
6061 )
6162 case FieldType .POWER_SELECT :
62- return self .page .locator (
63+ return self ._root .locator (
6364 f'{ base } [contains(text(), "{ label } ")]/../following-sibling::div[1]'
6465 )
6566 case _:
@@ -81,7 +82,7 @@ async def fill(self, label: str, value: str) -> None:
8182 await locator .fill (value )
8283 case FieldType .POWER_SELECT :
8384 await locator .locator (".ember-power-select-trigger" ).click ()
84- option = self .page .locator (
85+ option = self ._root .locator (
8586 f'//li[contains(@class, "ember-power-select-option") and contains(., "{ value } ")]'
8687 )
8788 await option .click ()
@@ -102,7 +103,7 @@ async def fill_power_select_by_search(self, label: str, value: str) -> None:
102103 field_type = self .FIELDS [label ]
103104 locator = self ._get_locator (label , field_type )
104105 await locator .locator (".ember-power-select-trigger" ).click ()
105- search = self .page .locator (".ember-power-select-search-input" )
106+ search = self ._root .locator (".ember-power-select-search-input" )
106107 await search .fill (value )
107108 await search .press ("Enter" )
108109
@@ -115,6 +116,7 @@ class FileMetadataForm:
115116
116117 FIELDS : Dict [str , FieldType ] = {
117118 # Basic info
119+ "ファイル種別" : FieldType .SELECT ,
118120 "データ No." : FieldType .INPUT ,
119121 "データの名称または論文表題 (日本語)" : FieldType .INPUT ,
120122 "Title (English)" : FieldType .INPUT ,
@@ -139,10 +141,22 @@ class FileMetadataForm:
139141 "リポジトリURL・DOIリンク" : FieldType .INPUT ,
140142 # Creators
141143 "データ作成者" : FieldType .TABLE ,
144+ "著者名" : FieldType .TABLE ,
142145 # Hosting institution
143146 "データ管理機関 (日本語)" : FieldType .INPUT ,
144147 "Hosting institution (English)" : FieldType .INPUT ,
145148 "データ管理機関コード" : FieldType .INPUT ,
149+ # Bibliographic specific fields
150+ "論文(出版社版)のDOI" : FieldType .INPUT ,
151+ "論文の種類" : FieldType .SELECT ,
152+ "掲載誌名 (日本語)" : FieldType .INPUT ,
153+ "Journal Name (English)" : FieldType .INPUT ,
154+ "発行年月" : FieldType .INPUT ,
155+ "巻" : FieldType .INPUT ,
156+ "号" : FieldType .INPUT ,
157+ "掲載ページ (開始)" : FieldType .INPUT ,
158+ "掲載ページ (終了)" : FieldType .INPUT ,
159+ "学術論文を掲載した「機関リポジトリ等の情報基盤」のDOI" : FieldType .INPUT ,
146160 # Data manager
147161 "データ管理者の種類" : FieldType .SELECT ,
148162 "データ管理者の e-Rad 研究者番号" : FieldType .INPUT ,
@@ -159,42 +173,51 @@ class FileMetadataForm:
159173 "Remarks (English)" : FieldType .TEXTAREA ,
160174 # Metadata access
161175 "メタデータのアクセス権" : FieldType .SELECT ,
176+ # Publication specific extra
177+ "査読の有無" : FieldType .SELECT ,
178+ "版情報" : FieldType .SELECT ,
162179 }
163180
164- def __init__ (self , page ):
181+ def __init__ (self , page , parent_locator = None ):
165182 self .page = page
183+ self ._root = parent_locator or page
166184
167185 def _get_locator (self , label : str , field_type : FieldType ):
168186 # Special case: 概略データ量 has different xpath
169187 if label == "概略データ量" :
170- return self .page .locator (
188+ return self ._root .locator (
171189 '//label[contains(text(), "概略データ量")]/../..//input[contains(@class, "form-control")]'
172190 )
191+ exact_labels = {"号" }
192+ if label in exact_labels :
193+ label_xpath = f'//label[normalize-space(.) = "{ label } "]'
194+ else :
195+ label_xpath = f'//label[contains(text(), "{ label } ")]'
173196
174197 match field_type :
175198 case FieldType .INPUT :
176- return self .page .locator (
177- f'//label[contains(text(), " { label } ")] /../following-sibling::div[1]//input'
199+ return self ._root .locator (
200+ f'{ label_xpath } /../following-sibling::div[1]//input'
178201 )
179202 case FieldType .INPUT_DIRECT :
180- return self .page .locator (
181- f'//label[contains(text(), " { label } ")] /../following-sibling::input[1]'
203+ return self ._root .locator (
204+ f'{ label_xpath } /../following-sibling::input[1]'
182205 )
183206 case FieldType .TEXTAREA :
184- return self .page .locator (
185- f'//label[contains(text(), " { label } ")] /../following-sibling::textarea[1]'
207+ return self ._root .locator (
208+ f'{ label_xpath } /../following-sibling::textarea[1]'
186209 )
187210 case FieldType .SELECT :
188211 if label == "アクセス権" :
189- return self .page .locator (
190- f'//label[text()="{ label } "]/../following-sibling::select[1]'
212+ return self ._root .locator (
213+ f'//label[normalize-space( text() )="{ label } "]/../following-sibling::select[1]'
191214 )
192- return self .page .locator (
193- f'//label[contains(text(), " { label } ")] /../following-sibling::select[1]'
215+ return self ._root .locator (
216+ f'{ label_xpath } /../following-sibling::select[1]'
194217 )
195218 case FieldType .TABLE :
196- return self .page .locator (
197- f'//label[contains(text(), " { label } ")] /../following-sibling::div[1]'
219+ return self ._root .locator (
220+ f'{ label_xpath } /../following-sibling::div[1]'
198221 )
199222 case _:
200223 raise ValueError (f"Unsupported field type: { field_type } " )
@@ -271,3 +294,32 @@ async def get_table_cell(self, label: str, row_index: int, col_index: int) -> st
271294 row = locator .locator (f"table tbody tr:nth-of-type({ row_index + 1 } )" )
272295 cell_input = row .locator (f"td:nth-of-type({ col_index + 1 } ) input" )
273296 return await cell_input .input_value ()
297+
298+ async def fill_author (self , author : Dict [str , Any ]) -> None :
299+ """Add an author row and fill all author fields."""
300+ container = self .get_locator ("著者名" )
301+ await self .click_table_add_row ("著者名" )
302+
303+ edit_rows = container .locator ('.metadata-edit-mode' )
304+ row_count = await edit_rows .count ()
305+ if row_count == 0 :
306+ raise AssertionError ("No edit rows found for authors" )
307+ panel = edit_rows .nth (row_count - 1 )
308+ await panel .wait_for (state = "visible" )
309+
310+ await panel .locator ('label:has-text("e-Rad 研究者番号") + div input' ).fill (author ['number' ])
311+
312+ ja_inputs = panel .locator ('label:has-text("名前(日本語)") + div table input' )
313+ await ja_inputs .nth (0 ).fill (author ['name_ja' ]['last' ])
314+ await ja_inputs .nth (1 ).fill (author ['name_ja' ]['middle' ])
315+ await ja_inputs .nth (2 ).fill (author ['name_ja' ]['first' ])
316+
317+ en_inputs = panel .locator ('label:has-text("Name (English)") + div table input' )
318+ await en_inputs .nth (0 ).fill (author ['name_en' ]['last' ])
319+ await en_inputs .nth (1 ).fill (author ['name_en' ]['middle' ])
320+ await en_inputs .nth (2 ).fill (author ['name_en' ]['first' ])
321+
322+ await panel .locator ('label:has-text("所属機関名(日本語)") + div input' ).fill (author ['affiliation_ja' ])
323+ await panel .locator ('label:has-text("所属機関名(英語)") + div input' ).fill (author ['affiliation_en' ])
324+
325+ await panel .locator ('.hide-edit-row' ).click ()
0 commit comments