Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ jobs:
strategy:
fail-fast: false
matrix:
ros_distro: [noetic]
ros_distro:
- noetic
- humble
- jazzy
- kilted
node_version: [20, 22, 24]
env:
ROS_DISTRO: ${{ matrix.ros_distro }}
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ COPY test/examples/ /workspace/test/examples/
EXPOSE 9090

# Default command runs the ROS backend for testing
CMD ["bash", "-c", "source /opt/ros/$ROS_DISTRO/setup.bash && roslaunch /workspace/test/examples/setup_examples.launch"]
CMD ["bash", "-c", "source /opt/ros/$ROS_DISTRO/setup.bash && bash /workspace/test/examples/setup_examples.bash"]
10 changes: 7 additions & 3 deletions package.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" ?>
<package>
<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/ros-infrastructure/rep/master/xsd/package_format3.xsd" format="3">
<name>roslibjs</name>
<version>2.0.0</version>
<description>The Robot Web Tools ROS JavaScript Library</description>
Expand All @@ -18,7 +18,11 @@
<test_depend>libnss3-dev</test_depend>
<test_depend>rosbridge_server</test_depend>
<test_depend>tf2_web_republisher</test_depend>
<test_depend>common_tutorials</test_depend>
<test_depend>ros_tutorials</test_depend>
<test_depend condition="$ROS_VERSION == 1">common_tutorials</test_depend>
<test_depend condition="$ROS_VERSION == 1">ros_tutorials</test_depend>
<test_depend condition="$ROS_VERSION == 2">action_tutorials_cpp</test_depend>
<test_depend condition="$ROS_VERSION == 2">examples_rclpy_minimal_service</test_depend>
<test_depend condition="$ROS_VERSION == 2">tf2_ros</test_depend>


</package>
2 changes: 1 addition & 1 deletion src/core/Param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default class Param<T = unknown> {
* @param [failedCallback] - The callback function when the service call failed or the parameter setting was unsuccessful.
*/
set(
value: object,
value: T,
callback?: (message: rosapi.SetParamResponse) => void,
failedCallback: (error: string) => void = console.error,
) {
Expand Down
95 changes: 40 additions & 55 deletions test/examples/check-topics.example.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,57 @@
import { describe, it, expect } from "vitest";
import { describe, it, expect, vi } from "vitest";
import * as ROSLIB from "../../src/RosLib.js";

const expectedTopics = [
/*
* '/turtle1/cmd_vel', '/turtle1/color_sensor', '/turtle1/pose',
* '/turtle2/cmd_vel', '/turtle2/color_sensor', '/turtle2/pose',
*/
"/tf2_web_republisher/status",
"/tf2_web_republisher/feedback",
// '/tf2_web_republisher/goal', '/tf2_web_republisher/result',
"/fibonacci/feedback",
"/fibonacci/status",
"/fibonacci/result",
];
Comment on lines -4 to -15
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test data is ROS-1-only and wasn't even sensical.. it didn't check for the one thing unique to our test suites, the /listener topic 🤦🏻‍♂️

const expectedTopics = ["/listener"];

describe("Example topics are live", function () {
const ros = new ROSLIB.Ros({
url: "ws://localhost:9090",
});

it("getTopics", () =>
new Promise((done) => {
ros.getTopics(function (result) {
expectedTopics.forEach(function (topic) {
expect(result.topics).to.contain(
topic,
"Couldn't find topic: " + topic,
);
});
done(result);
});
}));
it("getTopics", async () => {
const callback = vi.fn();
ros.getTopics(callback);
await vi.waitFor(() => {
expect(callback).toHaveBeenCalledOnce();
for (const topic of expectedTopics) {
expect(callback.mock.calls[0][0].topics).to.contain(topic);
}
});
});

const example = ros.Topic({
name: "/some_test_topic",
messageType: "std_msgs/String",
});

it("doesn't automatically advertise the topic", () =>
new Promise((done) => {
ros.getTopics(function (result) {
expect(result.topics).not.to.contain("/some_test_topic");
example.advertise();
done(result);
});
}));
it("doesn't automatically advertise the topic", async () => {
const callback = vi.fn();
ros.getTopics(callback);
await vi.waitFor(() => {
expect(callback).toHaveBeenCalledOnce();
expect(callback.mock.calls[0][0].topics).not.to.contain(
"/some_test_topic",
);
});
example.advertise();
});

it("advertise broadcasts the topic", () =>
new Promise((done) => {
ros.getTopics(function (result) {
expect(result.topics).to.contain("/some_test_topic");
example.unadvertise();
done(result);
});
}));
it("advertise broadcasts the topic", async () => {
const callback = vi.fn();
ros.getTopics(callback);
await vi.waitFor(() => {
expect(callback).toHaveBeenCalledOnce();
expect(callback.mock.calls[0][0].topics).to.contain("/some_test_topic");
});
example.unadvertise();
});

it(
"unadvertise will end the topic (if it's the last around)",
() =>
new Promise((done) => {
console.log("Unadvertisement test. Wait for 15 seconds..");
setTimeout(function () {
ros.getTopics(function (result) {
expect(result.topics).not.to.contain("/some_test_topic");
done(result);
});
}, 15000);
}),
20000,
);
it("unadvertise will end the topic (if it's the last around)", async () => {
const callback = vi.fn();
ros.getTopics(callback);
vi.waitFor(function () {
expect(callback).toHaveBeenCalledOnce();
expect(callback.mock.calls[0][0]).not.to.contain("/some_test_topic");
}, 15000);
});
});
113 changes: 58 additions & 55 deletions test/examples/fibonacci.example.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,65 @@
import { describe, it, expect } from "vitest";
import * as ROSLIB from "../../src/RosLib.js";

describe("Fibonacci Example", function () {
it(
"Fibonacci",
() =>
new Promise<void>((done) => {
const ros = new ROSLIB.Ros({
url: "ws://localhost:9090",
});
/*
* The ActionClient
* ----------------
*/
// Noetic is the only version of ROS 1 we support, so we skip based on distro name
// instead of adding extra plumbing for ROS_VERSION.
describe.skipIf(process.env.ROS_DISTRO !== "noetic")(
"ROS 1 Fibonacci Example",
function () {
it(
"Fibonacci",
() =>
new Promise<void>((done) => {
const ros = new ROSLIB.Ros({
url: "ws://localhost:9090",
});
/*
* The ActionClient
* ----------------
*/

const fibonacciClient = new ROSLIB.ActionClient({
ros: ros,
serverName: "/fibonacci",
actionName: "actionlib_tutorials/FibonacciAction",
});
const fibonacciClient = new ROSLIB.ActionClient({
ros: ros,
serverName: "/fibonacci",
actionName: "actionlib_tutorials/FibonacciAction",
});

// Create a goal.
const goal = new ROSLIB.Goal({
actionClient: fibonacciClient,
goalMessage: {
order: 7,
},
});
// Create a goal.
const goal = new ROSLIB.Goal({
actionClient: fibonacciClient,
goalMessage: {
order: 7,
},
});

// Print out their output into the terminal.
const items = [
{ sequence: [0, 1, 1] },
{ sequence: [0, 1, 1, 2] },
{ sequence: [0, 1, 1, 2, 3] },
{ sequence: [0, 1, 1, 2, 3, 5] },
{ sequence: [0, 1, 1, 2, 3, 5, 8] },
{ sequence: [0, 1, 1, 2, 3, 5, 8, 13] },
{ sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21] },
];
goal.on("feedback", function (feedback) {
console.log("Feedback:", feedback);
expect(feedback).to.eql(items.shift());
});
goal.on("result", function (result) {
console.log("Result:", result);
expect(result).to.eql({ sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21] });
done();
});
// Print out their output into the terminal.
const items = [
{ sequence: [0, 1, 1] },
{ sequence: [0, 1, 1, 2] },
{ sequence: [0, 1, 1, 2, 3] },
{ sequence: [0, 1, 1, 2, 3, 5] },
{ sequence: [0, 1, 1, 2, 3, 5, 8] },
{ sequence: [0, 1, 1, 2, 3, 5, 8, 13] },
{ sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21] },
];
goal.on("feedback", function (feedback) {
expect(feedback).to.eql(items.shift());
});
goal.on("result", function (result) {
expect(result).to.eql({ sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21] });
done();
});

/*
* Send the goal to the action server.
* The timeout is to allow rosbridge to properly subscribe all the
* Action topics - otherwise, the first feedback message might get lost
*/
setTimeout(function () {
goal.send();
}, 100);
}),
8000,
);
});
/*
* Send the goal to the action server.
* The timeout is to allow rosbridge to properly subscribe all the
* Action topics - otherwise, the first feedback message might get lost
*/
setTimeout(function () {
goal.send();
}, 100);
}),
8000,
);
},
);
Loading