# Copyright 2026 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Full test of abandon_old_changes module."""

from __future__ import annotations

from collections.abc import Iterator

from recipe_engine import post_process, recipe_api, recipe_test_api

from PB.recipe_modules.pigweed.trigger.options import Options
from PB.recipe_modules.pigweed.trigger.tests.full import InputProperties

DEPS = [
    'fuchsia/buildbucket_util',
    'pigweed/checkout',
    'pigweed/trigger',
    'recipe_engine/properties',
    'recipe_engine/step',
]


INLINE_PROPERTIES_PROTO = """
import "recipe_modules/pigweed/trigger/options.proto";

message InputProperties {
  repeated recipe_modules.pigweed.trigger.Options trigger_options = 1;
}
"""

PROPERTIES = InputProperties


def RunSteps(api: recipe_api.RecipeScriptApi, props: InputProperties):
    pres = api.step.empty('properties').presentation
    pres.step_summary_text = repr(api.properties.thaw())
    checkout = api.checkout.fake_context()
    api.trigger(props.trigger_options, checkout)


def GenTests(api) -> Iterator[recipe_test_api.TestData]:
    def properties(*variables: dict):
        return api.properties(
            InputProperties(
                trigger_options=[Options(**args) for args in variables],
            ),
        )

    yield api.buildbucket_util.test(
        'no-op',
        properties(),
        api.post_check(post_process.DoesNotRun, 'trigger builders'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.buildbucket_util.test(
        'defaults',
        properties({'builder': 'foo'}),
        api.post_check(post_process.MustRun, 'trigger builders'),
        api.post_check(post_process.MustRun, 'trigger builders.foo'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.buildbucket_util.test(
        'specify',
        properties({'project': 'proj', 'bucket': 'buck', 'builder': 'foo'}),
        api.post_check(post_process.MustRun, 'trigger builders'),
        api.post_check(post_process.DoesNotRun, 'trigger builders.foo'),
        api.post_check(post_process.MustRun, 'trigger builders.proj/buck/foo'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.buildbucket_util.test(
        'gitiles-commit',
        properties(
            {
                'builder': 'foo',
                'inherit_gitiles_commit': True,
                'create_gitiles_commit_if_missing': True,
            },
        ),
        api.post_check(post_process.MustRun, 'trigger builders'),
        api.post_check(post_process.MustRun, 'trigger builders.foo'),
        api.post_process(post_process.DropExpectation),
        generic=True,
    )
