|
| 1 | +## ADDED Requirements |
| 2 | + |
| 3 | +### Requirement: ReviewAutoApprovalSubscriber sets accepted status for auto-approved store reviews |
| 4 | +The test SHALL verify that when a `StoreReviewInterface` entity triggers `prePersist` and the store auto-approval checker returns true, the entity's status is set to `ReviewInterface::STATUS_ACCEPTED`. |
| 5 | + |
| 6 | +#### Scenario: Store review is auto-approved |
| 7 | +- **WHEN** `prePersist` is called with a `StoreReviewInterface` entity and the store checker returns `shouldAutoApprove() === true` |
| 8 | +- **THEN** the entity's status SHALL be set to `ReviewInterface::STATUS_ACCEPTED` |
| 9 | + |
| 10 | +#### Scenario: Store review is not auto-approved |
| 11 | +- **WHEN** `prePersist` is called with a `StoreReviewInterface` entity and the store checker returns `shouldAutoApprove() === false` |
| 12 | +- **THEN** the entity's status SHALL NOT be changed |
| 13 | + |
| 14 | +### Requirement: ReviewAutoApprovalSubscriber sets accepted status for auto-approved product reviews |
| 15 | +The test SHALL verify that when a `ProductReviewInterface` entity triggers `prePersist` and the product auto-approval checker returns true, the entity's status is set to `ReviewInterface::STATUS_ACCEPTED`. |
| 16 | + |
| 17 | +#### Scenario: Product review is auto-approved |
| 18 | +- **WHEN** `prePersist` is called with a `ProductReviewInterface` entity and the product checker returns `shouldAutoApprove() === true` |
| 19 | +- **THEN** the entity's status SHALL be set to `ReviewInterface::STATUS_ACCEPTED` |
| 20 | + |
| 21 | +#### Scenario: Product review is not auto-approved |
| 22 | +- **WHEN** `prePersist` is called with a `ProductReviewInterface` entity and the product checker returns `shouldAutoApprove() === false` |
| 23 | +- **THEN** the entity's status SHALL NOT be changed |
| 24 | + |
| 25 | +### Requirement: ReviewAutoApprovalSubscriber ignores unrelated entities |
| 26 | +The test SHALL verify that entities not implementing `StoreReviewInterface` or `ProductReviewInterface` are ignored. |
| 27 | + |
| 28 | +#### Scenario: Unrelated entity triggers prePersist |
| 29 | +- **WHEN** `prePersist` is called with an entity that is neither a store review nor a product review |
| 30 | +- **THEN** no checker SHALL be called and no status SHALL be changed |
| 31 | + |
| 32 | +### Requirement: CheckEligibilityChecksSubscriber cancels requests exceeding maximum checks |
| 33 | +The test SHALL verify that when a review request's eligibility checks exceed the maximum, the workflow cancel transition is applied and a processing error is set. |
| 34 | + |
| 35 | +#### Scenario: Eligibility checks exceed maximum |
| 36 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires and `getEligibilityChecks()` returns a value greater than `maximumChecks` |
| 37 | +- **THEN** the workflow `cancel` transition SHALL be applied and `setProcessingError` SHALL be called with an error message |
| 38 | + |
| 39 | +#### Scenario: Eligibility checks equal maximum |
| 40 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires and `getEligibilityChecks()` returns exactly `maximumChecks` |
| 41 | +- **THEN** no workflow transition SHALL be applied (checks <= max is allowed) |
| 42 | + |
| 43 | +#### Scenario: Eligibility checks below maximum |
| 44 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires and `getEligibilityChecks()` returns a value less than `maximumChecks` |
| 45 | +- **THEN** no workflow transition SHALL be applied |
| 46 | + |
| 47 | +### Requirement: CheckEligibilityChecksSubscriber subscribes with correct priority |
| 48 | +The test SHALL verify `getSubscribedEvents()` returns the correct event class, method, and priority. |
| 49 | + |
| 50 | +#### Scenario: Subscribed events mapping |
| 51 | +- **WHEN** `getSubscribedEvents()` is called |
| 52 | +- **THEN** it SHALL return `ReviewRequestProcessingStarted::class` mapped to `['check', 200]` |
| 53 | + |
| 54 | +### Requirement: IncrementEligibilityChecksSubscriber increments the counter |
| 55 | +The test SHALL verify that `incrementEligibilityChecks()` is called on the review request. |
| 56 | + |
| 57 | +#### Scenario: Counter is incremented |
| 58 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires |
| 59 | +- **THEN** `incrementEligibilityChecks()` SHALL be called on the review request |
| 60 | + |
| 61 | +### Requirement: IncrementEligibilityChecksSubscriber subscribes with correct priority |
| 62 | +The test SHALL verify `getSubscribedEvents()` returns the correct event class, method, and priority. |
| 63 | + |
| 64 | +#### Scenario: Subscribed events mapping |
| 65 | +- **WHEN** `getSubscribedEvents()` is called |
| 66 | +- **THEN** it SHALL return `ReviewRequestProcessingStarted::class` mapped to `['incrementEligibilityChecks', 300]` |
| 67 | + |
| 68 | +### Requirement: ResetSubscriber clears processing state |
| 69 | +The test SHALL verify that both `setIneligibilityReason(null)` and `setProcessingError(null)` are called. |
| 70 | + |
| 71 | +#### Scenario: State is reset |
| 72 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires |
| 73 | +- **THEN** `setIneligibilityReason(null)` and `setProcessingError(null)` SHALL both be called on the review request |
| 74 | + |
| 75 | +### Requirement: ResetSubscriber subscribes with correct priority |
| 76 | +The test SHALL verify `getSubscribedEvents()` returns the correct event class, method, and priority. |
| 77 | + |
| 78 | +#### Scenario: Subscribed events mapping |
| 79 | +- **WHEN** `getSubscribedEvents()` is called |
| 80 | +- **THEN** it SHALL return `ReviewRequestProcessingStarted::class` mapped to `['reset', 400]` |
| 81 | + |
| 82 | +### Requirement: UpdateNextEligibilityCheckSubscriber calculates exponential backoff |
| 83 | +The test SHALL verify that `setNextEligibilityCheckAt()` is called with a datetime computed as `initialDelayHours * 2^(eligibilityChecks - 1)` hours from now. |
| 84 | + |
| 85 | +#### Scenario: First eligibility check (checks = 1, default delay = 24h) |
| 86 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires with `getEligibilityChecks() === 1` and default `initialDelayHours` of 24 |
| 87 | +- **THEN** `setNextEligibilityCheckAt()` SHALL be called with a datetime approximately 24 hours from now |
| 88 | + |
| 89 | +#### Scenario: Second eligibility check (checks = 2, default delay = 24h) |
| 90 | +- **WHEN** a `ReviewRequestProcessingStarted` event fires with `getEligibilityChecks() === 2` and default `initialDelayHours` of 24 |
| 91 | +- **THEN** `setNextEligibilityCheckAt()` SHALL be called with a datetime approximately 48 hours from now |
| 92 | + |
| 93 | +#### Scenario: Custom initial delay |
| 94 | +- **WHEN** the subscriber is constructed with `initialDelayHours = 12` and event fires with `getEligibilityChecks() === 1` |
| 95 | +- **THEN** `setNextEligibilityCheckAt()` SHALL be called with a datetime approximately 12 hours from now |
| 96 | + |
| 97 | +### Requirement: UpdateNextEligibilityCheckSubscriber subscribes with correct priority |
| 98 | +The test SHALL verify `getSubscribedEvents()` returns the correct event class, method, and priority. |
| 99 | + |
| 100 | +#### Scenario: Subscribed events mapping |
| 101 | +- **WHEN** `getSubscribedEvents()` is called |
| 102 | +- **THEN** it SHALL return `ReviewRequestProcessingStarted::class` mapped to `['updateNextEligibilityCheck', 100]` |
0 commit comments