2828from cli import (
2929 GENERATE_REQUEST_FILE ,
3030 BUILD_REQUEST_FILE ,
31+ CONFIGURE_REQUEST_FILE ,
3132 RELEASE_INIT_REQUEST_FILE ,
3233 SOURCE_DIR ,
3334 STATE_YAML_FILE ,
4344 _get_library_dist_name ,
4445 _get_library_id ,
4546 _get_libraries_to_prepare_for_release ,
47+ _get_new_library_config ,
4648 _get_previous_version ,
49+ _prepare_new_library_config ,
4750 _process_changelog ,
4851 _process_version_file ,
4952 _read_bazel_build_py_rule ,
@@ -160,6 +163,35 @@ def mock_build_request_file(tmp_path, monkeypatch):
160163 return request_file
161164
162165
166+ @pytest .fixture
167+ def mock_configure_request_data ():
168+ """Returns mock data for configure-request.json."""
169+ return {
170+ "libraries" : [
171+ {
172+ "id" : "google-cloud-language" ,
173+ "apis" : [{"path" : "google/cloud/language/v1" , "status" : "new" }],
174+ }
175+ ]
176+ }
177+
178+
179+ @pytest .fixture
180+ def mock_configure_request_file (tmp_path , monkeypatch , mock_configure_request_data ):
181+ """Creates the mock request file at the correct path inside a temp dir."""
182+ # Create the path as expected by the script: .librarian/configure-request.json
183+ request_path = f"{ LIBRARIAN_DIR } /{ CONFIGURE_REQUEST_FILE } "
184+ request_dir = tmp_path / os .path .dirname (request_path )
185+ request_dir .mkdir (parents = True , exist_ok = True )
186+ request_file = request_dir / os .path .basename (request_path )
187+
188+ request_file .write_text (json .dumps (mock_configure_request_data ))
189+
190+ # Change the current working directory to the temp path for the test.
191+ monkeypatch .chdir (tmp_path )
192+ return request_file
193+
194+
163195@pytest .fixture
164196def mock_build_bazel_file (tmp_path , monkeypatch ):
165197 """Creates the mock BUILD.bazel file at the correct path inside a temp dir."""
@@ -236,6 +268,98 @@ def mock_state_file(tmp_path, monkeypatch):
236268 return request_file
237269
238270
271+ def test_handle_configure_success (mock_configure_request_file , mocker ):
272+ """Tests the successful execution path of handle_configure."""
273+ mock_write_json = mocker .patch ("cli._write_json_file" )
274+ mock_prepare_config = mocker .patch (
275+ "cli._prepare_new_library_config" , return_value = {"id" : "prepared" }
276+ )
277+
278+ handle_configure ()
279+
280+ mock_prepare_config .assert_called_once ()
281+ mock_write_json .assert_called_once_with (
282+ f"{ LIBRARIAN_DIR } /configure-response.json" , {"id" : "prepared" }
283+ )
284+
285+
286+ def test_handle_configure_no_new_library (mocker ):
287+ """Tests that handle_configure fails if no new library is found."""
288+ mocker .patch ("cli._read_json_file" , return_value = {"libraries" : []})
289+ # The call to _prepare_new_library_config with an empty dict will raise a ValueError
290+ # because _get_library_id will fail.
291+ with pytest .raises (ValueError , match = "Configuring a new library failed." ):
292+ handle_configure ()
293+
294+
295+ def test_get_new_library_config_found (mock_configure_request_data ):
296+ """Tests that the new library configuration is returned when found."""
297+ config = _get_new_library_config (mock_configure_request_data )
298+ assert config ["id" ] == "google-cloud-language"
299+ # Assert that the config is NOT modified
300+ assert "status" in config ["apis" ][0 ]
301+
302+
303+ def test_get_new_library_config_not_found ():
304+ """Tests that an empty dictionary is returned when no new library is found."""
305+ request_data = {
306+ "libraries" : [
307+ {"id" : "existing-library" , "apis" : [{"path" : "path/v1" , "status" : "existing" }]},
308+ ]
309+ }
310+ config = _get_new_library_config (request_data )
311+ assert config == {}
312+
313+
314+ def test_get_new_library_config_empty_input ():
315+ """Tests that an empty dictionary is returned for empty input."""
316+ config = _get_new_library_config ({})
317+ assert config == {}
318+
319+
320+ def test_prepare_new_library_config ():
321+ """Tests the preparation of a new library's configuration."""
322+ raw_config = {
323+ "id" : "google-cloud-language" ,
324+ "apis" : [{"path" : "google/cloud/language/v1" , "status" : "new" }],
325+ "source_roots" : None ,
326+ "preserve_regex" : None ,
327+ "remove_regex" : None ,
328+ }
329+
330+ prepared_config = _prepare_new_library_config (raw_config )
331+
332+ # Check that status is removed
333+ assert "status" not in prepared_config ["apis" ][0 ]
334+ # Check that defaults are added
335+ assert prepared_config ["source_roots" ] == ["packages/google-cloud-language" ]
336+ assert "packages/google-cloud-language/CHANGELOG.md" in prepared_config ["preserve_regex" ]
337+ assert prepared_config ["remove_regex" ] == ["packages/google-cloud-language" ]
338+ assert prepared_config ["tag_format" ] == "{{id}}-v{{version}}"
339+
340+
341+ def test_prepare_new_library_config_preserves_existing_values ():
342+ """Tests that existing values in the config are not overwritten."""
343+ raw_config = {
344+ "id" : "google-cloud-language" ,
345+ "apis" : [{"path" : "google/cloud/language/v1" , "status" : "new" }],
346+ "source_roots" : ["packages/google-cloud-language-custom" ],
347+ "preserve_regex" : ["custom/regex" ],
348+ "remove_regex" : ["custom/remove" ],
349+ "tag_format" : "custom-format-{{version}}" ,
350+ }
351+
352+ prepared_config = _prepare_new_library_config (raw_config )
353+
354+ # Check that status is removed
355+ assert "status" not in prepared_config ["apis" ][0 ]
356+ # Check that existing values are preserved
357+ assert prepared_config ["source_roots" ] == ["packages/google-cloud-language-custom" ]
358+ assert prepared_config ["preserve_regex" ] == ["custom/regex" ]
359+ assert prepared_config ["remove_regex" ] == ["custom/remove" ]
360+ assert prepared_config ["tag_format" ] == "custom-format-{{version}}"
361+
362+
239363def test_get_library_id_success ():
240364 """Tests that _get_library_id returns the correct ID when present."""
241365 request_data = {"id" : "test-library" , "name" : "Test Library" }
@@ -261,17 +385,6 @@ def test_get_library_id_empty_id():
261385 _get_library_id (request_data )
262386
263387
264- def test_handle_configure_success (caplog , mock_generate_request_file ):
265- """
266- Tests the successful execution path of handle_configure.
267- """
268- caplog .set_level (logging .INFO )
269-
270- handle_configure ()
271-
272- assert "'configure' command executed." in caplog .text
273-
274-
275388def test_run_post_processor_success (mocker , caplog ):
276389 """
277390 Tests that the post-processor helper calls the correct command.
0 commit comments