Assert mixed multiphase action boundaries
This commit is contained in:
parent
632873ec5a
commit
a5845fb293
2 changed files with 91 additions and 1 deletions
|
|
@ -170,7 +170,9 @@ Core rules:
|
||||||
- Each phase is a discrete animation using the full curve.
|
- Each phase is a discrete animation using the full curve.
|
||||||
- A phase performs only one action kind per window: move or scale.
|
- A phase performs only one action kind per window: move or scale.
|
||||||
- Movement and scaling are split by axis.
|
- Movement and scaling are split by axis.
|
||||||
- No diagonal motion.
|
- No diagonal motion. Mixed-action phases may combine different per-window
|
||||||
|
actions, but no single window may move or resize on more than one axis in one
|
||||||
|
step.
|
||||||
- A window or synchronized group owns its own timeline.
|
- A window or synchronized group owns its own timeline.
|
||||||
- New layout changes interrupt only windows/groups with changed destinations.
|
- New layout changes interrupt only windows/groups with changed destinations.
|
||||||
- Current hierarchy and target hierarchy both matter. The planner must know
|
- Current hierarchy and target hierarchy both matter. The planner must know
|
||||||
|
|
@ -270,6 +272,7 @@ Tests:
|
||||||
- bounded generated split-tree corpus produces identical plans on repeated runs
|
- bounded generated split-tree corpus produces identical plans on repeated runs
|
||||||
- unsupported and invalid candidate plans produce exact expected diagnostics
|
- unsupported and invalid candidate plans produce exact expected diagnostics
|
||||||
- mixed-action phases are accepted only under exact continuous validation
|
- mixed-action phases are accepted only under exact continuous validation
|
||||||
|
- diagonal per-window motion remains a hard rejection even inside mixed phases
|
||||||
- child waits for parent/container-space phases when moving upward into a
|
- child waits for parent/container-space phases when moving upward into a
|
||||||
toplevel peer position
|
toplevel peer position
|
||||||
- mono-mode tab switches do not animate, while entering/exiting mono can animate
|
- mono-mode tab switches do not animate, while entering/exiting mono can animate
|
||||||
|
|
|
||||||
|
|
@ -1910,6 +1910,56 @@ mod tests {
|
||||||
assert!(validate_plan_continuous(&req, &planned.plan));
|
assert!(validate_plan_continuous(&req, &planned.plan));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mixed_single_phase_accepts_move_and_scale_when_proven() {
|
||||||
|
let req = request(vec![
|
||||||
|
window(1, rect(0, 0, 80, 80), rect(40, 0, 120, 80)),
|
||||||
|
window(2, rect(200, 0, 280, 80), rect(200, 0, 280, 120)),
|
||||||
|
]);
|
||||||
|
let planned = plan_no_overlap_explained(&req).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(planned.explanation.strategy, PlanStrategy::MixedSinglePhase);
|
||||||
|
assert_eq!(
|
||||||
|
planned.plan.phases[0].action,
|
||||||
|
MultiphasePhaseAction::Mixed(vec![
|
||||||
|
PhaseAction {
|
||||||
|
kind: PhaseKind::Move,
|
||||||
|
axis: PhaseAxis::Horizontal,
|
||||||
|
},
|
||||||
|
PhaseAction {
|
||||||
|
kind: PhaseKind::Scale,
|
||||||
|
axis: PhaseAxis::Vertical,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
planned.explanation.phases[0].reason,
|
||||||
|
PhaseReason::MixedAxisActions
|
||||||
|
);
|
||||||
|
assert_eq!(planned.explanation.phases[0].nodes, vec![id(1), id(2)]);
|
||||||
|
assert!(validate_plan_continuous(&req, &planned.plan));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mixed_single_phase_still_rejects_diagonal_per_window_motion() {
|
||||||
|
let req = request(vec![
|
||||||
|
window(1, rect(0, 0, 80, 80), rect(40, 40, 120, 120)),
|
||||||
|
window(2, rect(200, 0, 280, 80), rect(200, 0, 280, 120)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(plan_no_overlap(&req), Err(MultiphaseError::NoPlan));
|
||||||
|
let diagnostic = plan_no_overlap_with_diagnostics(&req).unwrap_err();
|
||||||
|
let rejection = MultiphasePlanFailure::InvalidPhaseStep {
|
||||||
|
action: PhaseAction {
|
||||||
|
kind: PhaseKind::Scale,
|
||||||
|
axis: PhaseAxis::Horizontal,
|
||||||
|
},
|
||||||
|
node_id: id(1),
|
||||||
|
};
|
||||||
|
assert_eq!(diagnostic.forward, rejection);
|
||||||
|
assert_eq!(diagnostic.reverse, Some(rejection));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn generated_nested_size_redistribution_scales_parent_axis_first() {
|
fn generated_nested_size_redistribution_scales_parent_axis_first() {
|
||||||
let old = split(
|
let old = split(
|
||||||
|
|
@ -2518,6 +2568,43 @@ mod tests {
|
||||||
assert!(validate_plan_continuous(&req, &plan));
|
assert!(validate_plan_continuous(&req, &plan));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn continuous_validation_rejects_mixed_phase_action_count_mismatch() {
|
||||||
|
let req = request(vec![
|
||||||
|
window(1, rect(0, 0, 40, 40), rect(40, 0, 80, 40)),
|
||||||
|
window(2, rect(100, 0, 140, 40), rect(100, 0, 140, 80)),
|
||||||
|
]);
|
||||||
|
let plan = MultiphasePlan {
|
||||||
|
phases: vec![MultiphasePhase {
|
||||||
|
action: MultiphasePhaseAction::Mixed(vec![PhaseAction {
|
||||||
|
kind: PhaseKind::Move,
|
||||||
|
axis: PhaseAxis::Horizontal,
|
||||||
|
}]),
|
||||||
|
steps: vec![
|
||||||
|
MultiphaseStep {
|
||||||
|
node_id: id(1),
|
||||||
|
from: rect(0, 0, 40, 40),
|
||||||
|
to: rect(40, 0, 80, 40),
|
||||||
|
},
|
||||||
|
MultiphaseStep {
|
||||||
|
node_id: id(2),
|
||||||
|
from: rect(100, 0, 140, 40),
|
||||||
|
to: rect(100, 0, 140, 80),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
validate_plan_continuous_diagnostic(&req, &plan),
|
||||||
|
Err(MultiphaseValidationError::PhaseActionCount {
|
||||||
|
phase: 0,
|
||||||
|
actions: 1,
|
||||||
|
steps: 2,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn continuous_validation_rejects_stale_step_start_rect() {
|
fn continuous_validation_rejects_stale_step_start_rect() {
|
||||||
let req = request(vec![MultiphaseWindow {
|
let req = request(vec![MultiphaseWindow {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue