Skip to content

Commit cfad3b9

Browse files
fix(utils): don't duplicate base placements in get_opposite_axis_placements (#340)
* fix(utils): don't duplicate base placements in get_opposite_axis_placements `get_opposite_axis_placements` applied the flip-alignment duplication unconditionally. In the JS source (`@floating-ui/utils`) this block is nested inside `if (alignment)`, so base placements (Top/Bottom/Left/Right) must not be duplicated. Without the guard, e.g. get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), None) returned `[Left, Right, Left, Right]` instead of `[Left, Right]`. Guard the block with `alignment.is_some()` to match the JS behaviour, and add a `#[cfg(test)]` module porting `getOppositeAxisPlacements.test.ts` (16 cases); `utils` previously had no tests. --------- * chore: remove unnecessary comments * chore: format Co-authored-by: Daniëlle Huisman <danielle@huisman.me> --------- Co-authored-by: kno-raziel <8211946+kno-raziel@users.noreply.github.com> Co-authored-by: Daniëlle Huisman <danielle@huisman.me>
1 parent 3c531f7 commit cfad3b9

1 file changed

Lines changed: 367 additions & 1 deletion

File tree

packages/utils/src/lib.rs

Lines changed: 367 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ pub fn get_opposite_axis_placements(
712712
.map(|side| get_placement(side, alignment))
713713
.collect();
714714

715-
if flip_alignment {
715+
if flip_alignment && alignment.is_some() {
716716
let mut opposite_list: Vec<Placement> = list
717717
.clone()
718718
.into_iter()
@@ -762,3 +762,369 @@ pub fn rect_to_client_rect(rect: Rect) -> ClientRectObject {
762762
left: rect.x,
763763
}
764764
}
765+
766+
#[cfg(test)]
767+
mod tests {
768+
use super::{Alignment, Placement, get_opposite_axis_placements};
769+
770+
#[test]
771+
fn side_top() {
772+
assert_eq!(
773+
get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), None),
774+
vec![Placement::Left, Placement::Right]
775+
);
776+
assert_eq!(
777+
get_opposite_axis_placements(Placement::Top, true, Some(Alignment::End), None),
778+
vec![Placement::Right, Placement::Left]
779+
);
780+
}
781+
782+
#[test]
783+
fn side_bottom() {
784+
assert_eq!(
785+
get_opposite_axis_placements(Placement::Bottom, true, Some(Alignment::Start), None),
786+
vec![Placement::Left, Placement::Right]
787+
);
788+
assert_eq!(
789+
get_opposite_axis_placements(Placement::Bottom, true, Some(Alignment::End), None),
790+
vec![Placement::Right, Placement::Left]
791+
);
792+
}
793+
794+
#[test]
795+
fn side_left() {
796+
assert_eq!(
797+
get_opposite_axis_placements(Placement::Left, true, Some(Alignment::Start), None),
798+
vec![Placement::Top, Placement::Bottom]
799+
);
800+
assert_eq!(
801+
get_opposite_axis_placements(Placement::Left, true, Some(Alignment::End), None),
802+
vec![Placement::Bottom, Placement::Top]
803+
);
804+
}
805+
806+
#[test]
807+
fn side_right() {
808+
assert_eq!(
809+
get_opposite_axis_placements(Placement::Right, true, Some(Alignment::Start), None),
810+
vec![Placement::Top, Placement::Bottom]
811+
);
812+
assert_eq!(
813+
get_opposite_axis_placements(Placement::Right, true, Some(Alignment::End), None),
814+
vec![Placement::Bottom, Placement::Top]
815+
);
816+
}
817+
818+
#[test]
819+
fn start_top_start() {
820+
assert_eq!(
821+
get_opposite_axis_placements(Placement::TopStart, false, Some(Alignment::Start), None),
822+
vec![Placement::LeftStart, Placement::RightStart]
823+
);
824+
assert_eq!(
825+
get_opposite_axis_placements(Placement::TopStart, false, Some(Alignment::End), None),
826+
vec![Placement::RightStart, Placement::LeftStart]
827+
);
828+
assert_eq!(
829+
get_opposite_axis_placements(Placement::TopStart, true, Some(Alignment::Start), None),
830+
vec![
831+
Placement::LeftStart,
832+
Placement::RightStart,
833+
Placement::LeftEnd,
834+
Placement::RightEnd
835+
]
836+
);
837+
assert_eq!(
838+
get_opposite_axis_placements(Placement::TopStart, true, Some(Alignment::End), None),
839+
vec![
840+
Placement::RightStart,
841+
Placement::LeftStart,
842+
Placement::RightEnd,
843+
Placement::LeftEnd
844+
]
845+
);
846+
}
847+
848+
#[test]
849+
fn start_bottom_start() {
850+
assert_eq!(
851+
get_opposite_axis_placements(
852+
Placement::BottomStart,
853+
false,
854+
Some(Alignment::Start),
855+
None
856+
),
857+
vec![Placement::LeftStart, Placement::RightStart]
858+
);
859+
assert_eq!(
860+
get_opposite_axis_placements(Placement::BottomStart, false, Some(Alignment::End), None),
861+
vec![Placement::RightStart, Placement::LeftStart]
862+
);
863+
assert_eq!(
864+
get_opposite_axis_placements(
865+
Placement::BottomStart,
866+
true,
867+
Some(Alignment::Start),
868+
None
869+
),
870+
vec![
871+
Placement::LeftStart,
872+
Placement::RightStart,
873+
Placement::LeftEnd,
874+
Placement::RightEnd
875+
]
876+
);
877+
assert_eq!(
878+
get_opposite_axis_placements(Placement::BottomStart, true, Some(Alignment::End), None),
879+
vec![
880+
Placement::RightStart,
881+
Placement::LeftStart,
882+
Placement::RightEnd,
883+
Placement::LeftEnd
884+
]
885+
);
886+
}
887+
888+
#[test]
889+
fn start_left_start() {
890+
assert_eq!(
891+
get_opposite_axis_placements(Placement::LeftStart, false, Some(Alignment::Start), None),
892+
vec![Placement::TopStart, Placement::BottomStart]
893+
);
894+
assert_eq!(
895+
get_opposite_axis_placements(Placement::LeftStart, false, Some(Alignment::End), None),
896+
vec![Placement::BottomStart, Placement::TopStart]
897+
);
898+
assert_eq!(
899+
get_opposite_axis_placements(Placement::LeftStart, true, Some(Alignment::Start), None),
900+
vec![
901+
Placement::TopStart,
902+
Placement::BottomStart,
903+
Placement::TopEnd,
904+
Placement::BottomEnd
905+
]
906+
);
907+
assert_eq!(
908+
get_opposite_axis_placements(Placement::LeftStart, true, Some(Alignment::End), None),
909+
vec![
910+
Placement::BottomStart,
911+
Placement::TopStart,
912+
Placement::BottomEnd,
913+
Placement::TopEnd
914+
]
915+
);
916+
}
917+
918+
#[test]
919+
fn start_right_start() {
920+
assert_eq!(
921+
get_opposite_axis_placements(
922+
Placement::RightStart,
923+
false,
924+
Some(Alignment::Start),
925+
None
926+
),
927+
vec![Placement::TopStart, Placement::BottomStart]
928+
);
929+
assert_eq!(
930+
get_opposite_axis_placements(Placement::RightStart, false, Some(Alignment::End), None),
931+
vec![Placement::BottomStart, Placement::TopStart]
932+
);
933+
assert_eq!(
934+
get_opposite_axis_placements(Placement::RightStart, true, Some(Alignment::Start), None),
935+
vec![
936+
Placement::TopStart,
937+
Placement::BottomStart,
938+
Placement::TopEnd,
939+
Placement::BottomEnd
940+
]
941+
);
942+
assert_eq!(
943+
get_opposite_axis_placements(Placement::RightStart, true, Some(Alignment::End), None),
944+
vec![
945+
Placement::BottomStart,
946+
Placement::TopStart,
947+
Placement::BottomEnd,
948+
Placement::TopEnd
949+
]
950+
);
951+
}
952+
953+
#[test]
954+
fn end_top_end() {
955+
assert_eq!(
956+
get_opposite_axis_placements(Placement::TopEnd, false, Some(Alignment::Start), None),
957+
vec![Placement::LeftEnd, Placement::RightEnd]
958+
);
959+
assert_eq!(
960+
get_opposite_axis_placements(Placement::TopEnd, false, Some(Alignment::End), None),
961+
vec![Placement::RightEnd, Placement::LeftEnd]
962+
);
963+
assert_eq!(
964+
get_opposite_axis_placements(Placement::TopEnd, true, Some(Alignment::Start), None),
965+
vec![
966+
Placement::LeftEnd,
967+
Placement::RightEnd,
968+
Placement::LeftStart,
969+
Placement::RightStart
970+
]
971+
);
972+
assert_eq!(
973+
get_opposite_axis_placements(Placement::TopEnd, true, Some(Alignment::End), None),
974+
vec![
975+
Placement::RightEnd,
976+
Placement::LeftEnd,
977+
Placement::RightStart,
978+
Placement::LeftStart
979+
]
980+
);
981+
}
982+
983+
#[test]
984+
fn end_bottom_end() {
985+
assert_eq!(
986+
get_opposite_axis_placements(Placement::BottomEnd, false, Some(Alignment::Start), None),
987+
vec![Placement::LeftEnd, Placement::RightEnd]
988+
);
989+
assert_eq!(
990+
get_opposite_axis_placements(Placement::BottomEnd, false, Some(Alignment::End), None),
991+
vec![Placement::RightEnd, Placement::LeftEnd]
992+
);
993+
assert_eq!(
994+
get_opposite_axis_placements(Placement::BottomEnd, true, Some(Alignment::Start), None),
995+
vec![
996+
Placement::LeftEnd,
997+
Placement::RightEnd,
998+
Placement::LeftStart,
999+
Placement::RightStart
1000+
]
1001+
);
1002+
assert_eq!(
1003+
get_opposite_axis_placements(Placement::BottomEnd, true, Some(Alignment::End), None),
1004+
vec![
1005+
Placement::RightEnd,
1006+
Placement::LeftEnd,
1007+
Placement::RightStart,
1008+
Placement::LeftStart
1009+
]
1010+
);
1011+
}
1012+
1013+
#[test]
1014+
fn end_left_end() {
1015+
assert_eq!(
1016+
get_opposite_axis_placements(Placement::LeftEnd, false, Some(Alignment::Start), None),
1017+
vec![Placement::TopEnd, Placement::BottomEnd]
1018+
);
1019+
assert_eq!(
1020+
get_opposite_axis_placements(Placement::LeftEnd, false, Some(Alignment::End), None),
1021+
vec![Placement::BottomEnd, Placement::TopEnd]
1022+
);
1023+
assert_eq!(
1024+
get_opposite_axis_placements(Placement::LeftStart, true, Some(Alignment::Start), None),
1025+
vec![
1026+
Placement::TopStart,
1027+
Placement::BottomStart,
1028+
Placement::TopEnd,
1029+
Placement::BottomEnd
1030+
]
1031+
);
1032+
assert_eq!(
1033+
get_opposite_axis_placements(Placement::LeftStart, true, Some(Alignment::End), None),
1034+
vec![
1035+
Placement::BottomStart,
1036+
Placement::TopStart,
1037+
Placement::BottomEnd,
1038+
Placement::TopEnd
1039+
]
1040+
);
1041+
}
1042+
1043+
#[test]
1044+
fn end_right_end() {
1045+
assert_eq!(
1046+
get_opposite_axis_placements(Placement::RightEnd, false, Some(Alignment::Start), None),
1047+
vec![Placement::TopEnd, Placement::BottomEnd]
1048+
);
1049+
assert_eq!(
1050+
get_opposite_axis_placements(Placement::RightEnd, false, Some(Alignment::End), None),
1051+
vec![Placement::BottomEnd, Placement::TopEnd]
1052+
);
1053+
assert_eq!(
1054+
get_opposite_axis_placements(Placement::RightEnd, true, Some(Alignment::Start), None),
1055+
vec![
1056+
Placement::TopEnd,
1057+
Placement::BottomEnd,
1058+
Placement::TopStart,
1059+
Placement::BottomStart
1060+
]
1061+
);
1062+
assert_eq!(
1063+
get_opposite_axis_placements(Placement::RightEnd, true, Some(Alignment::End), None),
1064+
vec![
1065+
Placement::BottomEnd,
1066+
Placement::TopEnd,
1067+
Placement::BottomStart,
1068+
Placement::TopStart
1069+
]
1070+
);
1071+
}
1072+
1073+
#[test]
1074+
fn rtl_top() {
1075+
assert_eq!(
1076+
get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), Some(true)),
1077+
vec![Placement::Right, Placement::Left]
1078+
);
1079+
assert_eq!(
1080+
get_opposite_axis_placements(Placement::Top, true, Some(Alignment::End), Some(true)),
1081+
vec![Placement::Left, Placement::Right]
1082+
);
1083+
}
1084+
1085+
#[test]
1086+
fn rtl_bottom() {
1087+
assert_eq!(
1088+
get_opposite_axis_placements(
1089+
Placement::Bottom,
1090+
true,
1091+
Some(Alignment::Start),
1092+
Some(true)
1093+
),
1094+
vec![Placement::Right, Placement::Left]
1095+
);
1096+
assert_eq!(
1097+
get_opposite_axis_placements(Placement::Bottom, true, Some(Alignment::End), Some(true)),
1098+
vec![Placement::Left, Placement::Right]
1099+
);
1100+
}
1101+
1102+
#[test]
1103+
fn rtl_left() {
1104+
assert_eq!(
1105+
get_opposite_axis_placements(Placement::Left, true, Some(Alignment::Start), Some(true)),
1106+
vec![Placement::Top, Placement::Bottom]
1107+
);
1108+
assert_eq!(
1109+
get_opposite_axis_placements(Placement::Left, true, Some(Alignment::End), Some(true)),
1110+
vec![Placement::Bottom, Placement::Top]
1111+
);
1112+
}
1113+
1114+
#[test]
1115+
fn rtl_right() {
1116+
assert_eq!(
1117+
get_opposite_axis_placements(
1118+
Placement::Right,
1119+
true,
1120+
Some(Alignment::Start),
1121+
Some(true)
1122+
),
1123+
vec![Placement::Top, Placement::Bottom]
1124+
);
1125+
assert_eq!(
1126+
get_opposite_axis_placements(Placement::Right, true, Some(Alignment::End), Some(true)),
1127+
vec![Placement::Bottom, Placement::Top]
1128+
);
1129+
}
1130+
}

0 commit comments

Comments
 (0)