2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2018-10-02 20:55:03 -07:00
|
|
|
|
|
|
|
|
#include "frc/shuffleboard/ShuffleboardInstance.h" // NOLINT(build/include_order)
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
#include <string_view>
|
2018-10-02 20:55:03 -07:00
|
|
|
|
2023-08-28 15:13:34 -07:00
|
|
|
#include <gtest/gtest.h>
|
2018-10-02 20:55:03 -07:00
|
|
|
#include <networktables/NetworkTableInstance.h>
|
2023-03-27 06:12:55 +03:00
|
|
|
#include <networktables/NetworkTableListener.h>
|
|
|
|
|
#include <networktables/StringTopic.h>
|
2018-10-02 20:55:03 -07:00
|
|
|
|
|
|
|
|
#include "shuffleboard/MockActuatorSendable.h"
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
class NTWrapper {
|
|
|
|
|
public:
|
|
|
|
|
NTWrapper() { inst = nt::NetworkTableInstance::Create(); }
|
2018-10-02 20:55:03 -07:00
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
~NTWrapper() { nt::NetworkTableInstance::Destroy(inst); }
|
2018-10-02 20:55:03 -07:00
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
nt::NetworkTableInstance inst;
|
2018-10-02 20:55:03 -07:00
|
|
|
};
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
TEST(ShuffleboardInstanceTest, PathFluent) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
|
2022-11-24 09:05:37 -08:00
|
|
|
auto entry = shuffleboardInst.GetTab("Tab Title")
|
|
|
|
|
.GetLayout("List", "List Layout")
|
|
|
|
|
.Add("Data", "string")
|
|
|
|
|
.WithWidget("Text View")
|
|
|
|
|
.GetEntry();
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
|
|
|
|
|
EXPECT_EQ("/Shuffleboard/Tab Title/List/Data", entry->GetTopic().GetName())
|
2018-10-02 20:55:03 -07:00
|
|
|
<< "Entry path generated incorrectly";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
TEST(ShuffleboardInstanceTest, NestedLayoutsFluent) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
|
2022-11-24 09:05:37 -08:00
|
|
|
auto entry = shuffleboardInst.GetTab("Tab")
|
|
|
|
|
.GetLayout("First", "List")
|
|
|
|
|
.GetLayout("Second", "List")
|
|
|
|
|
.GetLayout("Third", "List")
|
|
|
|
|
.GetLayout("Fourth", "List")
|
|
|
|
|
.Add("Value", "string")
|
|
|
|
|
.GetEntry();
|
2018-10-02 20:55:03 -07:00
|
|
|
|
2022-11-24 09:05:37 -08:00
|
|
|
EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
|
2018-10-02 20:55:03 -07:00
|
|
|
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
|
2022-11-24 09:05:37 -08:00
|
|
|
entry->GetTopic().GetName())
|
2018-10-02 20:55:03 -07:00
|
|
|
<< "Entry path generated incorrectly";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
TEST(ShuffleboardInstanceTest, NestedLayoutsOop) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
|
|
|
|
|
frc::ShuffleboardTab& tab = shuffleboardInst.GetTab("Tab");
|
|
|
|
|
frc::ShuffleboardLayout& first = tab.GetLayout("First", "List");
|
|
|
|
|
frc::ShuffleboardLayout& second = first.GetLayout("Second", "List");
|
|
|
|
|
frc::ShuffleboardLayout& third = second.GetLayout("Third", "List");
|
|
|
|
|
frc::ShuffleboardLayout& fourth = third.GetLayout("Fourth", "List");
|
|
|
|
|
frc::SimpleWidget& widget = fourth.Add("Value", "string");
|
2022-11-24 09:05:37 -08:00
|
|
|
auto entry = widget.GetEntry();
|
2018-10-02 20:55:03 -07:00
|
|
|
|
2022-11-24 09:05:37 -08:00
|
|
|
EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value";
|
2018-10-02 20:55:03 -07:00
|
|
|
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
|
2022-11-24 09:05:37 -08:00
|
|
|
entry->GetTopic().GetName())
|
2018-10-02 20:55:03 -07:00
|
|
|
<< "Entry path generated incorrectly";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
TEST(ShuffleboardInstanceTest, LayoutTypeIsSet) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
|
|
|
|
|
std::string_view layoutType = "Type";
|
|
|
|
|
shuffleboardInst.GetTab("Tab").GetLayout("Title", layoutType);
|
|
|
|
|
shuffleboardInst.Update();
|
|
|
|
|
auto entry = ntInst.inst.GetEntry(
|
2018-10-02 20:55:03 -07:00
|
|
|
"/Shuffleboard/.metadata/Tab/Title/PreferredComponent");
|
|
|
|
|
EXPECT_EQ(layoutType, entry.GetString("Not Set")) << "Layout type not set";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 10:21:34 -07:00
|
|
|
TEST(ShuffleboardInstanceTest, NestedActuatorWidgetsAreDisabled) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
|
2018-10-02 20:55:03 -07:00
|
|
|
MockActuatorSendable sendable("Actuator");
|
2021-05-31 10:21:34 -07:00
|
|
|
shuffleboardInst.GetTab("Tab").GetLayout("Title", "Layout").Add(sendable);
|
2018-10-02 20:55:03 -07:00
|
|
|
auto controllableEntry =
|
2021-05-31 10:21:34 -07:00
|
|
|
ntInst.inst.GetEntry("/Shuffleboard/Tab/Title/Actuator/.controllable");
|
|
|
|
|
shuffleboardInst.Update();
|
2018-10-02 20:55:03 -07:00
|
|
|
|
|
|
|
|
// Note: we use the unsafe `GetBoolean()` method because if the value is NOT
|
|
|
|
|
// a boolean, or if it is not present, then something has clearly gone very,
|
|
|
|
|
// very wrong
|
2022-10-08 10:01:31 -07:00
|
|
|
bool controllable = controllableEntry.GetValue().GetBoolean();
|
2018-10-02 20:55:03 -07:00
|
|
|
// Sanity check
|
|
|
|
|
EXPECT_TRUE(controllable)
|
|
|
|
|
<< "The nested actuator widget should be enabled by default";
|
2021-05-31 10:21:34 -07:00
|
|
|
shuffleboardInst.DisableActuatorWidgets();
|
2022-10-08 10:01:31 -07:00
|
|
|
controllable = controllableEntry.GetValue().GetBoolean();
|
2018-10-02 20:55:03 -07:00
|
|
|
EXPECT_FALSE(controllable)
|
|
|
|
|
<< "The nested actuator widget should have been disabled";
|
|
|
|
|
}
|
2023-03-27 06:12:55 +03:00
|
|
|
|
|
|
|
|
TEST(ShuffleboardInstanceTest, DuplicateSelectTabs) {
|
|
|
|
|
NTWrapper ntInst;
|
|
|
|
|
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
|
|
|
|
|
std::atomic_int counter = 0;
|
2023-07-23 17:36:26 -07:00
|
|
|
auto subscriber =
|
|
|
|
|
ntInst.inst.GetStringTopic("/Shuffleboard/.metadata/Selected")
|
|
|
|
|
.Subscribe("", {.keepDuplicates = true});
|
|
|
|
|
ntInst.inst.AddListener(
|
|
|
|
|
subscriber, nt::EventFlags::kValueAll | nt::EventFlags::kImmediate,
|
2023-03-27 06:12:55 +03:00
|
|
|
[&counter](auto& event) { counter++; });
|
|
|
|
|
|
|
|
|
|
// There shouldn't be anything there
|
|
|
|
|
EXPECT_EQ(0, counter);
|
|
|
|
|
|
|
|
|
|
shuffleboardInst.SelectTab("tab1");
|
|
|
|
|
shuffleboardInst.SelectTab("tab1");
|
2023-06-03 09:47:08 -04:00
|
|
|
EXPECT_TRUE(ntInst.inst.WaitForListenerQueue(1.0))
|
2023-03-27 06:12:55 +03:00
|
|
|
<< "Listener queue timed out!";
|
|
|
|
|
EXPECT_EQ(2, counter);
|
|
|
|
|
}
|