Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3db2bdb
claude: add "/create-api PLUGIN_NAME" as a claude command
IonutMuthi Feb 24, 2026
cfd10e2
claude: add "/create-automated-tests PLUGIN_NAME" as a claude command
IonutMuthi Feb 24, 2026
e46e6a3
claude: moved prompts to tools folder
IonutMuthi Feb 24, 2026
65f0e90
jesd: create JESD APIs
IonutMuthi Feb 24, 2026
65b0a00
jesd: automated JS tests
IonutMuthi Feb 24, 2026
a8c3be1
rfpowermeter: js automated tests
IonutMuthi Feb 24, 2026
e78f74b
datalogger: add y/n option for visual tests
IonutMuthi Feb 24, 2026
7825e8d
generic: add plot API class
IonutMuthi Feb 25, 2026
7d99104
datalogger: add tests related to plot
IonutMuthi Feb 25, 2026
bd117d5
imuanalyzer: add API class
IonutMuthi Feb 25, 2026
b452511
imuanalyzer: atuomated tests
IonutMuthi Feb 25, 2026
0bfc600
claude: update test automations prompt to consider generic API calls
IonutMuthi Feb 25, 2026
c3d2f3d
adc: added APIs
IonutMuthi Feb 24, 2026
9ffb655
adc: add automated tests
IonutMuthi Feb 24, 2026
f8fe821
dac: add API
IonutMuthi Feb 26, 2026
d0d8f0f
dac: automated tests
IonutMuthi Feb 26, 2026
c8c4672
claude: update test automations cmd to consider other plugin API calls
IonutMuthi Feb 26, 2026
44ad566
regmap: update automated tests
IonutMuthi Feb 26, 2026
3b4b0be
core: preferences automated tests
IonutMuthi Feb 26, 2026
c821246
adc: updates to match main changes
IonutMuthi Feb 26, 2026
745d726
adc_api: Fix the getter/setter for XY Plot switch.
andreidanila1 Mar 2, 2026
343210b
adc: Update API.
andreidanila1 Mar 3, 2026
8f6c5fb
js/adc: Update doc test.
andreidanila1 Mar 3, 2026
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
19 changes: 19 additions & 0 deletions .claude/commands/create-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Create a JavaScript API class for the Scopy plugin: $ARGUMENTS

Follow the instructions in @tools/prompts/scopy_api_agent.md exactly.

## Workflow

1. **Analyze**: Read the plugin's header, source, and all instrument class headers to understand its structure. Identify tool IDs, instrument classes, and all private members that can be exposed.

2. **Design**: Build a complete method list and present it to me for review BEFORE writing any code. Also present a "Missing Functionality Report" listing anything that cannot be exposed without modifying base classes.

3. **Implement**: After I approve the design, create the API header, API source, and the minimal modifications to the plugin header/source (friend class + initApi only).

4. **Validate**: Run through the checklist from the agent prompt to verify completeness.

## Rules
- Do NOT modify any instrument or utility class — the API is a new layer on top.
- Do NOT create methods that require new functions in base classes — flag them in the missing functionality report instead.
- Always null-check instrument pointers before accessing them.
- Use the existing code patterns from the reference implementations.
31 changes: 31 additions & 0 deletions .claude/commands/create-automated-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Create automated JavaScript test scripts for the Scopy plugin: $ARGUMENTS

Follow the instructions in @tools/prompts/scopy_test_automation_agent.md exactly.
Also use @tools/prompts/scopy_test_automation_prompt.md as a reference for templates and patterns.

## Workflow

1. **Discover**: Find the plugin's API header (`*_api.h`) and its test documentation RST file (`*_tests.rst`). Read both completely. Also read the JS API object name from `js/testAutomations/common/apiUnregisterTest.js` or from the plugin source code. **Cross-plugin discovery:** Scan the RST test steps for references to other plugins (e.g., "Open the Debugger", "Check the ADC plot", "Set TX_LO frequency"). For each referenced plugin, find and read its `*_api.h` header to identify available `Q_INVOKABLE` methods that can automate those cross-plugin steps.

2. **Classify**: For every test in the RST documentation, classify it as:
- **Category A** (Fully Automatable) — steps AND validation via API
- **Category B** (Supervised/Visual) — steps via API, validation requires human observer
- **Category C** (Not Automatable) — missing API calls or requires external tools
Present the full classification report to me for review BEFORE writing any code.

3. **Implement**: After I approve the classification, create:
- `<plugin>DocTests.js` for Category A tests
- `<plugin>VisualTests.js` for Category B tests (using `TestFramework.supervisedCheck()` for user y/n input)
- A "Missing API Report" comment block for Category C tests at the top of DocTests.js

4. **Validate**: Run through the checklist from the agent prompt to verify completeness.

## Rules
- Do NOT modify any C++ source code — only create JS test files under `js/testAutomations/`.
- Do NOT invent API methods that do not exist — check the `*_api.h` header for available `Q_INVOKABLE` methods.
- ALWAYS save and restore original values in every test.
- ALWAYS use `msleep(500)` after every setter call.
- Use `TestFramework.supervisedCheck()` for visual validation instead of `msleep(VISUAL_DELAY)`.
- Use the existing test file patterns in `js/testAutomations/` as references.
- Use doc UIDs as test names in `TestFramework.runTest()`.
- When a test step references another plugin (e.g., "Open the Debugger and set TX_LO frequency"), check that plugin's `*_api.h` for `Q_INVOKABLE` methods that can automate the step. Only classify as Category C when the other plugin truly has no API for the needed operation. Use `switchToTool()` to navigate between plugins and call the other plugin's API methods directly (e.g., `iioExplorer.writeAttributeValue()`, `adc.setTimeRunning()`).
102 changes: 102 additions & 0 deletions gui/include/gui/plot_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2025 Analog Devices Inc.
*
* This file is part of Scopy
* (see https://www.github.com/analogdevicesinc/scopy).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

#ifndef PLOT_API_H
#define PLOT_API_H

#include "scopy-gui_export.h"

#include <pluginbase/apiobject.h>
#include <QStringList>

namespace scopy {

class PlotComponent;
class PlotWidget;
class PlotChannel;
class CursorController;

class SCOPY_GUI_EXPORT PlotAPI : public ApiObject
{
Q_OBJECT
public:
explicit PlotAPI(PlotComponent *component, PlotWidget *plot, CursorController *cursor = nullptr,
QObject *parent = nullptr);
~PlotAPI();

// Title & Labels
Q_INVOKABLE QString getTitle();
Q_INVOKABLE void setTitle(const QString &title);
Q_INVOKABLE bool isLabelsEnabled();
Q_INVOKABLE void setLabelsEnabled(bool enabled);

// Channels
Q_INVOKABLE QStringList getChannels();

// Curve style (per channel by name)
Q_INVOKABLE int getChannelThickness(const QString &channel);
Q_INVOKABLE void setChannelThickness(const QString &channel, int thickness);
Q_INVOKABLE int getChannelStyle(const QString &channel);
Q_INVOKABLE void setChannelStyle(const QString &channel, int style);

// X-Axis range
Q_INVOKABLE double getXMin();
Q_INVOKABLE double getXMax();
Q_INVOKABLE void setXMin(double min);
Q_INVOKABLE void setXMax(double max);

// Y-Axis range (main/global axis)
Q_INVOKABLE double getYMin();
Q_INVOKABLE double getYMax();
Q_INVOKABLE void setYMin(double min);
Q_INVOKABLE void setYMax(double max);

// Cursors
Q_INVOKABLE bool isCursorsVisible();
Q_INVOKABLE void setCursorsVisible(bool visible);
Q_INVOKABLE void setXCursorsEnabled(bool enabled);
Q_INVOKABLE void setYCursorsEnabled(bool enabled);
Q_INVOKABLE void setXCursorsLocked(bool locked);
Q_INVOKABLE void setYCursorsLocked(bool locked);
Q_INVOKABLE void setTrackingEnabled(bool enabled);
Q_INVOKABLE double getX1CursorPosition();
Q_INVOKABLE double getX2CursorPosition();
Q_INVOKABLE void setX1CursorPosition(double pos);
Q_INVOKABLE void setX2CursorPosition(double pos);
Q_INVOKABLE double getY1CursorPosition();
Q_INVOKABLE double getY2CursorPosition();
Q_INVOKABLE void setY1CursorPosition(double pos);
Q_INVOKABLE void setY2CursorPosition(double pos);

// Print/Export
Q_INVOKABLE bool printPlot(const QString &filePath);

private:
PlotComponent *m_component;
PlotWidget *m_plot;
CursorController *m_cursor;

PlotChannel *findChannel(const QString &name);
};

} // namespace scopy

#endif // PLOT_API_H
100 changes: 100 additions & 0 deletions gui/include/gui/plotwidget_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2025 Analog Devices Inc.
*
* This file is part of Scopy
* (see https://www.github.com/analogdevicesinc/scopy).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

#ifndef PLOTWIDGET_API_H
#define PLOTWIDGET_API_H

#include "scopy-gui_export.h"

#include <pluginbase/apiobject.h>
#include <QStringList>

namespace scopy {

class PlotWidget;
class PlotChannel;

class SCOPY_GUI_EXPORT PlotWidget_API : public ApiObject
{
Q_OBJECT
public:
explicit PlotWidget_API(PlotWidget *plot, QObject *parent = nullptr);
~PlotWidget_API();

// X-Axis
Q_INVOKABLE double getXMin();
Q_INVOKABLE double getXMax();
Q_INVOKABLE void setXMin(double val);
Q_INVOKABLE void setXMax(double val);
Q_INVOKABLE void setXInterval(double min, double max);
Q_INVOKABLE QString getXUnits();
Q_INVOKABLE void setXUnits(const QString &units);
Q_INVOKABLE double getXDivs();
Q_INVOKABLE void setXDivs(double divs);

// Y-Axis
Q_INVOKABLE double getYMin();
Q_INVOKABLE double getYMax();
Q_INVOKABLE void setYMin(double val);
Q_INVOKABLE void setYMax(double val);
Q_INVOKABLE void setYInterval(double min, double max);
Q_INVOKABLE QString getYUnits();
Q_INVOKABLE void setYUnits(const QString &units);
Q_INVOKABLE double getYDivs();
Q_INVOKABLE void setYDivs(double divs);

// Channels
Q_INVOKABLE QStringList getChannelNames();
Q_INVOKABLE void setChannelEnabled(const QString &name, bool enabled);
Q_INVOKABLE bool isChannelEnabled(const QString &name);
Q_INVOKABLE void setChannelThickness(const QString &name, int thickness);
Q_INVOKABLE int getChannelThickness(const QString &name);
Q_INVOKABLE void setChannelStyle(const QString &name, int style);
Q_INVOKABLE int getChannelStyle(const QString &name);
Q_INVOKABLE void selectChannel(const QString &name);

// Grid/Scales
Q_INVOKABLE void setGridEnabled(bool enabled);
Q_INVOKABLE bool isGridEnabled();
Q_INVOKABLE void setGraticuleEnabled(bool enabled);
Q_INVOKABLE bool isGraticuleEnabled();

// Labels
Q_INVOKABLE void setShowXAxisLabels(bool show);
Q_INVOKABLE void setShowYAxisLabels(bool show);

// Navigator
Q_INVOKABLE void setNavigatorEnabled(bool enabled);
Q_INVOKABLE bool isNavigatorEnabled();

// General
Q_INVOKABLE void replot();
Q_INVOKABLE QString exportCsv();

private:
PlotChannel *findChannel(const QString &name);

PlotWidget *m_plot;
};

} // namespace scopy

#endif // PLOTWIDGET_API_H
Loading
Loading