From 950bb74960d3a5a00e0b9052dffc151f7c5cf8a4 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Tue, 16 Jul 2024 15:29:57 +0200 Subject: [PATCH 01/21] Third editing round of ladybug user stories --- misc/LADYBUG_USER_STORIES.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index c6d912af..51ac51f8 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -138,16 +138,18 @@ NOTE: Story **500** is implemented in the ladybug backend because you can create NOTE: Presently, some features of Ladybug are attached to the root node of a report. -* In the old Echo2 GUI, there is an "Edit" button in the tree view that puts the report in "edit mode". In edit mode, you have an editable message when you click a node in the tree view. There are also metadata fields, some of them editable and some of them read-only. When you select the top level node, you can edit a description. This way you can add a description of a report that exists in the debug tab. +* In the old Echo2 GUI, there is an "Edit" button for the debug tree that puts the report in "edit mode". In edit mode, you have an editable message when you click a node in the tree view. There are also metadata fields, some of them editable and some of them read-only. When you select the top level node, you can edit a description. This way you can add a description of a report that exists in the debug tab. +* TODO: Do we want reports to be editable in the debug tab? If this is allowed, users cannot trust that reports in the debug tab are always original captures. If editing reports in the debug tab is prohibited, the user can still copy them to the test tab and edit these copies. A drawback is that the set of test cases in the test tab can be contaminated with reports that are there only temporarily. +* If we decide that reports can be edited in the Debug tab, then the requirements of stories **2000** - **2050** apply. * In the test tab you can "open" a report. This is the user interface for main user story [I want to turn a report into a test case](#i-want-to-turn-a-report-into-a-test-case). Doing so opens a new tab with a tree view with editable node information next to it, like "edit mode" in the debug tab's tree view. Also in this case the root node of a report is relevant in the current implementation of Ladybug. * When you click the root node of a report you see it as XML. This combines nicely with an edit field to enter an XSLT transformation (story **2010**) * When you click the root node of a report you have the option there to enter the description (story **2040**). -**1300:** Given is that I as a service manager am investigating an issue with my application. In the debug tree, I want the option to see only the checkpoints within each report report that are about communicating with external systems. This is currently known as the black box view. +**1300:** Given is that I as a service manager am investigating an issue with my application. In the debug tree, I want the option to see only the checkpoints within each report that are about communicating with external systems. This is currently known as the black box view. **1310:** Given is that I as a support engineer or Frank developer am investigating an issue. In the debug tree, I want the option to see all the checkpoints within each report. This is known as the white box view. -**1320:** Given is that I as a user am investigating an issue. In the debug tree, I want the option to see a selection of the checkpoints within each report. More checkpoints than the black box view. This is known as the gray box view. +**1320:** Given is that I as a user am investigating an issue. In the debug tree, I want the option to see a only the following checkpoints: Checkpoints about communicating with external systems plus checkpoints related to adapters calling each other (typically through `IbisLocalSender`). This is known as the gray box view. **1330:** Given is that multiple users with multiple interests use the debug tree. As a user I want that the view I select (story **510**) also determines which checkpoints of my reports are shown: **1300**, **1310** or **1320**, in other words white box, gray box or black box. @@ -163,6 +165,8 @@ NOTE: Presently, some features of Ladybug are attached to the root node of a rep **2040:** Given is that I am building an automated test from a report. As a Frank developer I want the option to add a *description* to my report. In the description I can document what the report viewed as a test case should test. +**2050:** Given is that I am building an automated test from a report. If I have done some editing and save my results, I want that all views of the report are updated automatically without the need to press a refresh button. + # I want to re-run (test) reports to test my Frank application **3000:** Given is that I am testing my application as a Frank developer. When I enter the test tab I want to see all reports that I have prepared as test cases. From 1762d7990b0d0d47c23efb8fb495d9f0b4d20f1d Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Tue, 16 Jul 2024 15:43:24 +0200 Subject: [PATCH 02/21] Issue 489 as user story 2012 --- misc/LADYBUG_USER_STORIES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 51ac51f8..d0cec768 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -159,6 +159,10 @@ NOTE: Presently, some features of Ladybug are attached to the root node of a rep **2010:** Given is that I am building an automated test from a report. As a Frank developer I want the option to configure an XSLT transformation that is applied to each message inside each checkpoint. When a report is rerun, the XSLT transformation is applied to the produced messages and it is applied to the messages inside the checkpoints. For each checkpoint, the two transformation results are compared. This way, irrelevant differences can be ignored. Irrelevant differences are produced for example if the current time is used by a Frank application. +**2012:** Given is that I am using a report as a test case and that I did not edit an XSLT transformation as indiciated in story **2010**. This means that I am rerunning such a report. As a user, I want the following. If the inputs and the outputs and the behavior of the external systems are the same, then I want my test to succeed because I do not want false negatives. + +NOTE: Story **2012** can be implemented by giving original-capture reports a default XSLT transformation. + **2020:** Given is that I am building an automated test from a report. As a Frank developer I want the option to declare some checkpoints **stubbed**, checkpoints that correspond to calls to external systems. When the report is rerun, the Frank!Framework should not call the external systems again but it should return the results already stored in the stubbed checkpoints. This way, only the logic within the Frank configuration captured in the report is tested, not the behavior of the external systems. Stubbing allows Frank developers to work with a simpler test environment, because the test does not require access to external systems. **2030:** Given is that I am building an automated test from a report. As a Frank developer I want the option to base parameterized tests upon my report. This means that I introduce variable references in my report. I can create a new report by specifying values for the variables. I can do this for multiple possibilities to set the variables, all resulting in a new clone of the report. From f42ad924e5db798d786ca01bb0915541bd743bc8 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Tue, 16 Jul 2024 16:01:32 +0200 Subject: [PATCH 03/21] Story 3108 for issue 487 --- misc/LADYBUG_USER_STORIES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index d0cec768..c1d8197f 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -191,6 +191,8 @@ NOTE: Story **3060** is not trivial because rerunning reports happens in the bac **3100:** Given is that I have rerun a report as a Frank developer and that this test failed. I want the option to compare the original capture to the new results. I want to see the two datasets next to each other such that I can see what is the same and what is different. +**3108:** Given is that I am comparing a report in the context of story **3100**. On one side I have the checkpoints in the report and on the other side I have the checkpoints produced by the rerun. As a user, I want that the selected checkpoint is synchronized. If I select a checkpoint on one side, I want that the corresponding checkpoint on the other side is selected automatically. This helps me to do my analysis more quickly. + **3110:** Given is that I have rerun a report and that this test failed. Given is also that the number of checkpoints at both sides is different. As a user I want that Ladybug chooses intelligently what checkpoints to the left belong to what checkpoints to the right. When I look at one checkpoint I want to see the corresponding checkpoint next to it. I do not want to search on the other side for the corresponding checkpoint. **3120:** Given is the context of story **3110**. I want that checkpoints corresponding to the same inputs and outputs to external systems are matched. This statement is intended to clarify the "intelligent choice" of story **3110**. From f644bc09499a05add956c76481e6ced4c890a96a Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Tue, 16 Jul 2024 16:10:44 +0200 Subject: [PATCH 04/21] Story 1031 for issue 485 --- misc/LADYBUG_USER_STORIES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index c1d8197f..ad8b1208 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -118,6 +118,8 @@ NOTE: Story **500** is implemented in the ladybug backend because you can create **1030:** As a support engineer or Frank developer, I want to be able to collapse and to expand each parent node in the tree view. Each parent node can be *expanded* which means that the start node and its children, including the end node, are shown. A parent node can also be *collapsed* which means that its descendants are not shown. This way I can hide details of how a message was processed. +**1031:** As a user, I want to click only once to expand or collapse a node. In other words: if I click a node that was not selected yet, then I want the clicked node to become the selected one AND I want to toggle its expanded or collapsed state. + **1033:** As a support engineer or Frank developer, I want to have a checkpoint for each pipe such that I can see how each pipe transformed the incoming message. **1037:** As a support engineer or Frank developer, I want a single report when my adapter calls another adapter via a JavaListener. This way, I do not have to browse multiple reports to examine how my incoming message was processed. The sub-adapter checkpoints should have a common ancestor. When I collapse that ancestor, I want to see only one node for everything done in the sub-adapter. From 7d0de0c298a6867167b7d2cf5a4072e287c4d508 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Tue, 16 Jul 2024 16:26:10 +0200 Subject: [PATCH 05/21] Story 520 for issue 480 --- misc/LADYBUG_USER_STORIES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index ad8b1208..42837f34 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -98,6 +98,8 @@ NOTE: We implement story **120** because Frank developers can write Spring confi NOTE: Story **500** is implemented in the ladybug backend because you can create views in Spring configuration files. Story **510** is implemented because the debug tab has a dropdown box in which you can select a view from the list of available views. +**520:** Given is that I as a user am doing some analysis about my reports and that I have put some filters on the report table. Given is that I select another view during my analysis. For each metadata field that appears in the table for both views, I want that my filter on that field remains. This way I can continue my analysis without having to retype my filters unnecessarily. + # I want to understand how the message captured by a report was processed **1000:** As a support engineer or Frank developer, I want to see the name of each checkpoint that is shown in the tree view. The name is not required to be unique. From 8bf13f2e7d7aa411222900e981a357e7089bd8d2 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Wed, 17 Jul 2024 10:01:09 +0200 Subject: [PATCH 06/21] Run GitHub actions less frequently, and extra user story --- .../workflows/frank-runner-example-cited-correctly.yml | 1 - .github/workflows/no-console-warnings.js.yml | 1 - misc/LADYBUG_USER_STORIES.md | 10 +++++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/frank-runner-example-cited-correctly.yml b/.github/workflows/frank-runner-example-cited-correctly.yml index 2d78fcc8..0c36374b 100644 --- a/.github/workflows/frank-runner-example-cited-correctly.yml +++ b/.github/workflows/frank-runner-example-cited-correctly.yml @@ -3,7 +3,6 @@ on: push: branches: - master - pull_request: workflow_dispatch: jobs: testing: diff --git a/.github/workflows/no-console-warnings.js.yml b/.github/workflows/no-console-warnings.js.yml index 3ea2e986..ef3be061 100644 --- a/.github/workflows/no-console-warnings.js.yml +++ b/.github/workflows/no-console-warnings.js.yml @@ -3,7 +3,6 @@ on: push: branches: - master - pull_request: workflow_dispatch: jobs: testing: diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 42837f34..9d521825 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -116,6 +116,13 @@ NOTE: Story **500** is implemented in the ladybug backend because you can create * Thread start point. * Thread end point. +TODO: What checkpoints should be produced when a Frank adapter is executed? I guess there should a pipeline for each: +* Root node. +* Pipeline. +* Pipe. +* Sender. +* Session key. + **1020:** As a support engineer or Frank developer, I want to see a start point as the parent node of the checkpoints that come after it. This applies recursively: a start node inside a start node causes subsequent nodes to be grand children of the first start node. An end point that is a direct child of a start node is also the last child. Subsequent nodes are siblings of the ended start node. This also applies recursively. **1030:** As a support engineer or Frank developer, I want to be able to collapse and to expand each parent node in the tree view. Each parent node can be *expanded* which means that the start node and its children, including the end node, are shown. A parent node can also be *collapsed* which means that its descendants are not shown. This way I can hide details of how a message was processed. @@ -243,10 +250,11 @@ The following features should only be available with the DataAdmin role. * Upload report. * Move report. * Run report. -* TODO: Something about resetting a ReportRunner. The following features should be available with the Tester role (and not necessarily the DataAdmin role): # Miscelaneous **5000:** As a service manager I want Ladybug to be self-explanatory. The user interface should help me to understand what is going on, for example by providing mouse-over texts. + +**5010:** Given is that ladybug is not behaving as expected. As a user I want to see a version number for the ladybug frontend. It should point to a unique commit of the ladybug-frontend GitHub project. This way I can read the source code of the ladybug frontend I am not happy with. From c1e5b95e50c3998437b53c1692f3417cd94e509f Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Wed, 17 Jul 2024 10:22:18 +0200 Subject: [PATCH 07/21] Issue 439 gets story 1250 --- misc/LADYBUG_USER_STORIES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 9d521825..53ffacfa 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -156,6 +156,8 @@ NOTE: Presently, some features of Ladybug are attached to the root node of a rep * When you click the root node of a report you see it as XML. This combines nicely with an edit field to enter an XSLT transformation (story **2010**) * When you click the root node of a report you have the option there to enter the description (story **2040**). +**1250:** Given is that I am doing some analysis involving multiple reports. Given is also that I have configured the tree view to allow multiple reports (story **1200**). If the tree view is empty and if I open multiple reports simultaneously, the reports should appear in the tree view in the same sequence as they are in the report table. This way the reports in the tree view have a predictable sequence, helping me to do my analysis more efficiently. + **1300:** Given is that I as a service manager am investigating an issue with my application. In the debug tree, I want the option to see only the checkpoints within each report that are about communicating with external systems. This is currently known as the black box view. **1310:** Given is that I as a support engineer or Frank developer am investigating an issue. In the debug tree, I want the option to see all the checkpoints within each report. This is known as the white box view. From 3540ba99e2990552fc4c6d1a6fb0c9ab3cea773b Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Wed, 17 Jul 2024 10:44:45 +0200 Subject: [PATCH 08/21] Story 3005 for issue 424 --- misc/LADYBUG_USER_STORIES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 53ffacfa..9d29d25c 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -188,6 +188,8 @@ NOTE: Story **2012** can be implemented by giving original-capture reports a def **3000:** Given is that I am testing my application as a Frank developer. When I enter the test tab I want to see all reports that I have prepared as test cases. +**3005:** For each report I see in the test tab, I want to see its name and its description (story **2040**). + **3010:** Given is that I am testing my application as a Frank developer. I want the option to *rerun* reports. Rerunning a report means that the Frank adapter that produced the report is re-executed. The same input message is supplied. For each pipe, the produced output is compared with the value stored with the corresponding checkpoint. The test succeeds if the new messages are the same after applying the configured XSLT transformation (user story **2010**). **3020:** Given is that I am testing my application as a Frank developer. I want the option to rerun a single report. From 64b1e57200ba5fafcb1db89cbc6fd283bc5ce3ea Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Wed, 17 Jul 2024 12:03:41 +0200 Subject: [PATCH 09/21] Introduce FF-generated metadata and write about message truncation --- misc/LADYBUG_USER_STORIES.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 9d29d25c..8963660b 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -12,6 +12,8 @@ Ladybug is not limited to work with the Frank!Framework; it is a tool that can b When a report has been captured it is a Java object managed by Ladybug. Ladybug then extracts metadata from the report. This helps for searching and browsing reports because the amount of metadata is much less than the amount of data of all reports. The users should have options to define what information captured in reports should be treated as metadata. Ladybug should also be able to transform reports into XML format. Then users can interact with the reports through Xpath and XSLT. +Metadata extracted by ladybug should not be confused with metadata generated by the Frank!Framework. The Frank!Framework generates metadata along with each message. These metadata fields are for example the message length and the character set. For messages that come from a file, a metadata field generated by the Frank!Framework can be the file's location. And the mime type (xml/json/zip) is often available as FF!-generated metadata. FF! generated metadata is different from session keys; session keys appear as separate checkpoints within Ladybug. + Ladybug can be used as a debug tool. Ladybug provides a user interface that shows a table of all captured reports. When the user clicks a report, it is opened in a tree view. Each checkpoint is a node in the tree. Collapsing and expanding nodes is described in more detail in the user stories below. In the tree view, the user can see all intermediate results of processing each message. Each checkpoint has a meaningful name. The Frank!Framework names each checkpoint after the adapter or pipe name. Therefore the user can relate the checkpoint's message to the debugged/tested source code, or to the Frank application being tested. When you click a node in the tree, the corresponding message inside the checkpoint should be shown. Ladybug can be used as a tool for automated testing. Ladybug reports can act as test cases because they can be rerun. Rerunning a report means that the Java code that produced the report is re-executed. The messages inside the related checkpoints are compared to the messages in the original report. The test succeeds if these new messages are considered equivalent to the original ones; otherwise the test fails. Ladybug's user interface has separate tabs for new reports (Debug) and reports that are meant as test cases (Test). In the Debug tab, the user has a button to copy reports to the test tab. The user has options to edit a report to convert the raw capture to a useful testcase. @@ -131,9 +133,21 @@ TODO: What checkpoints should be produced when a Frank adapter is executed? I gu **1033:** As a support engineer or Frank developer, I want to have a checkpoint for each pipe such that I can see how each pipe transformed the incoming message. +**1035:** As a support engineer of Frank developer, I want to have a checkpoint for each session key that is input or output of a pipe. + **1037:** As a support engineer or Frank developer, I want a single report when my adapter calls another adapter via a JavaListener. This way, I do not have to browse multiple reports to examine how my incoming message was processed. The sub-adapter checkpoints should have a common ancestor. When I collapse that ancestor, I want to see only one node for everything done in the sub-adapter. -**1050:** As a support engineer or Frank developer, I want to see the message and the metadata of a checkpoint when I click on it. +**1050:** As a support engineer or Frank developer, I want to see the value of the selected node in the debug tree. + +**1052:** When I have selected the checkpoint of a session key in the tree view, the value I want to see (story **1050**) is the value of the session key. + +**1054:** When I have selected a checkpoint that is not a session key, the value I want to see is the message along with its FF!-generated metadata. + +**1056:** When I have selected the root node of a report, the value I want to see is the report in XML form, the ladybug-generated metadata, the description (story **2040**) and the XSLT transformation (story **2010**). + +**1058:** Given is that I have selected a checkpoint like described in story **1054**. If the message is too large, the message should be shown truncated and a warning should be shown. The warning should make clear that the user is not seeing the complete message. + +**1059:** As a Frank!Developer, I want to be able to configure a threshold for story **1058**. When a message is longer than the configured threshold, then the message is shown truncated. **1100:** As a support engineer or Frank developer, I want the option to remove a report from the tree view when I am done with it. This does not mean that a report is removed from persistent storage. From 3db0a24a44090d47c80628c67285f3960e6a2824 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 13:33:56 +0200 Subject: [PATCH 10/21] Add info on debug tree --- misc/LADYBUG_USER_STORIES.md | 57 ++++++++++++++++-- .../nesting-of-report-nodes.jpg | Bin 0 -> 48917 bytes 2 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 misc/ladybug-user-stories/nesting-of-report-nodes.jpg diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 8963660b..2dd0bda7 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -118,15 +118,60 @@ NOTE: Story **500** is implemented in the ladybug backend because you can create * Thread start point. * Thread end point. -TODO: What checkpoints should be produced when a Frank adapter is executed? I guess there should a pipeline for each: -* Root node. -* Pipeline. -* Pipe. -* Sender. -* Session key. +TODO: How should InputWrapper, InputValidator, OutputValidator, OutputWrapper, scheduling-related elements and monitoring related elements appear? **1020:** As a support engineer or Frank developer, I want to see a start point as the parent node of the checkpoints that come after it. This applies recursively: a start node inside a start node causes subsequent nodes to be grand children of the first start node. An end point that is a direct child of a start node is also the last child. Subsequent nodes are siblings of the ended start node. This also applies recursively. +NOTE: The figure below explains story **1020** and **1240** about the existance of a root node: + +![Nesting of nodes and root node](./ladybug-user-stories/nesting-of-report-nodes.jpg) + +**1025:** The following table shows how the elements of a Frank configuration should be shown in a Ladybug report: + +Frank type | Item | Ladybug type | Comment +---------- | ---- | ------------ | ------- +- | Root node | - | Shown as folder, see story **1056** +Pipeline | message | Start point | Message read by listener +Pipeline | message | End point | Output message of pipeline +Pipeline | error | Abort point | +Pipeline | session key | input point | Additional information like timestamp received or URL on which a http request was received. +Pipeline | session key | output point | Session key related to pipeline output +Receiver | - | not shown | +Listener | - | not shown | Additional information in Pipeline session keys +Sender | message | Start point | Message sent +Sender | message | End point | Response message +Sender | error | Abort point | +Sender | session key | input point | +Sender | session key | output point | +Pipe | message | Start point | Message received +Pipe | message | End point | Output message +Pipe | error | Abort point | +Pipe | session key | Input point | +Pipe | parameter | Input point | TODO: Is this correct? +Pipe | session key | Output point | +Pipe | source code, loaded config syntax (*) | Info point | + +NOTE: About (*). There is a difference between "loaded config syntax", or syntax 1, and "original syntax", or syntax 2. Here is an example of "loaded config syntax": + +``` + + + + +``` + +And here is the same in original config syntax, or syntax 2: + +``` + + + + + +``` + +For completeness, it should be noted that Frank configurations can also be written in syntax 1 directly; mixed syntax 1 and syntax 2 is also allowed. + **1030:** As a support engineer or Frank developer, I want to be able to collapse and to expand each parent node in the tree view. Each parent node can be *expanded* which means that the start node and its children, including the end node, are shown. A parent node can also be *collapsed* which means that its descendants are not shown. This way I can hide details of how a message was processed. **1031:** As a user, I want to click only once to expand or collapse a node. In other words: if I click a node that was not selected yet, then I want the clicked node to become the selected one AND I want to toggle its expanded or collapsed state. diff --git a/misc/ladybug-user-stories/nesting-of-report-nodes.jpg b/misc/ladybug-user-stories/nesting-of-report-nodes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0eb09c7ff153574d8ddf8b224b9059a0aa0a9d2 GIT binary patch literal 48917 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 M{-6B*v41B29~w3eGynhq literal 0 HcmV?d00001 From 2407b96729915e2a071d312780f17e36f8c9af5d Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 13:39:36 +0200 Subject: [PATCH 11/21] Fix table --- misc/LADYBUG_USER_STORIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 2dd0bda7..9408c51d 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -130,7 +130,7 @@ NOTE: The figure below explains story **1020** and **1240** about the existance Frank type | Item | Ladybug type | Comment ---------- | ---- | ------------ | ------- -- | Root node | - | Shown as folder, see story **1056** +\- | Root node | - | Shown as folder, see story **1056** Pipeline | message | Start point | Message read by listener Pipeline | message | End point | Output message of pipeline Pipeline | error | Abort point | From be8fa02cab0289efd1ad14c5d95ce91e78a2e6ea Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 13:46:30 +0200 Subject: [PATCH 12/21] Fix table formatting --- misc/LADYBUG_USER_STORIES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 9408c51d..69562f44 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -128,9 +128,9 @@ NOTE: The figure below explains story **1020** and **1240** about the existance **1025:** The following table shows how the elements of a Frank configuration should be shown in a Ladybug report: -Frank type | Item | Ladybug type | Comment ----------- | ---- | ------------ | ------- -\- | Root node | - | Shown as folder, see story **1056** +:Frank type | :Item | :Ladybug type | :Comment +----------- | ----- | ------------- | -------- +\- | root node | - | Shown as folder, see story **1056** Pipeline | message | Start point | Message read by listener Pipeline | message | End point | Output message of pipeline Pipeline | error | Abort point | From a6a7d47417a9ecf4f6d2806787cb07595c4c2113 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 13:48:15 +0200 Subject: [PATCH 13/21] Fix table formatting --- misc/LADYBUG_USER_STORIES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 69562f44..588c96c9 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -128,8 +128,8 @@ NOTE: The figure below explains story **1020** and **1240** about the existance **1025:** The following table shows how the elements of a Frank configuration should be shown in a Ladybug report: -:Frank type | :Item | :Ladybug type | :Comment ------------ | ----- | ------------- | -------- +Frank type | Item | Ladybug type | Comment +:--------- | :--- | :----------- | :------ \- | root node | - | Shown as folder, see story **1056** Pipeline | message | Start point | Message read by listener Pipeline | message | End point | Output message of pipeline From ffef88676c09797c88cf5c0660fbcdc2ccc57eee Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 13:54:19 +0200 Subject: [PATCH 14/21] Improve story 1031 --- misc/LADYBUG_USER_STORIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 588c96c9..8cf246b3 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -174,7 +174,7 @@ For completeness, it should be noted that Frank configurations can also be writt **1030:** As a support engineer or Frank developer, I want to be able to collapse and to expand each parent node in the tree view. Each parent node can be *expanded* which means that the start node and its children, including the end node, are shown. A parent node can also be *collapsed* which means that its descendants are not shown. This way I can hide details of how a message was processed. -**1031:** As a user, I want to click only once to expand or collapse a node. In other words: if I click a node that was not selected yet, then I want the clicked node to become the selected one AND I want to toggle its expanded or collapsed state. +**1031:** As a user, I want to click only once to expand or collapse a node. In other words: if I click on the `>` or `v` sign to the left of an expandable node that was not selected yet, then I want the node to become the selected one AND I want to toggle its expanded or collapsed state. **1033:** As a support engineer or Frank developer, I want to have a checkpoint for each pipe such that I can see how each pipe transformed the incoming message. From dbe7042dd183e2060bd8bcef4a49ad02c08c3503 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 15:17:25 +0200 Subject: [PATCH 15/21] Be more precise about what checkpoints we should have --- misc/LADYBUG_USER_STORIES.md | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 8cf246b3..583be623 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -176,17 +176,33 @@ For completeness, it should be noted that Frank configurations can also be writt **1031:** As a user, I want to click only once to expand or collapse a node. In other words: if I click on the `>` or `v` sign to the left of an expandable node that was not selected yet, then I want the node to become the selected one AND I want to toggle its expanded or collapsed state. -**1033:** As a support engineer or Frank developer, I want to have a checkpoint for each pipe such that I can see how each pipe transformed the incoming message. +**1032:** Given is that I am looking at the white box view (story **1310**). As a user, I want to see a start checkpoint and an end checkpoint for each pipeline so that I can see how the pipeline transformed the message. If an error occurred in the pipeline, I do not want an end point but an abort point that shows me information about the error. -**1035:** As a support engineer of Frank developer, I want to have a checkpoint for each session key that is input or output of a pipe. +**1033:** Given is that I am looking at the white box view (story **1310**). As a user, I want to have a start checkpoint and an end checkpoint for each pipe so that I can see how each pipe transformed the incoming message. If an error occurred, I do not want to see and end point but an abort point that shows me information about the error. -**1037:** As a support engineer or Frank developer, I want a single report when my adapter calls another adapter via a JavaListener. This way, I do not have to browse multiple reports to examine how my incoming message was processed. The sub-adapter checkpoints should have a common ancestor. When I collapse that ancestor, I want to see only one node for everything done in the sub-adapter. +**1034:** Given is that I am looking at the white box view (story **1310**). As a user I want to have a checkpoint for each session key that is input or output of a pipeline. + +**1035:** Given is that I am looking at the white box view (story **1310**). As a user I want to have a checkpoint for each parameter of a pipe. + +**1036:** Given is that I am looking at the white box view (story **1310**). As a user I want that pipe checkpoints have child checkpoints for session keys. There should be an input point for each session key that is used by the pipe. There should be an output point for each session key that is generated or changed by the pipe. + +**1037:** Given is that I am looking at the white box view (story **1310**). As a user I want to have a start point and an end point for each sender so that I can see the sent message and the response. If an error occurred, I do not want an end point but an abort point that shows me information about the error. + +**1038:** Given is that I am looking at the white box view (story **1310**). If there are session keys that contain additional information about the message sent by a sender, then I want the start point of the sender to contain child checkpoints (input points) for these session keys. + +**1039:** Given is that I am looking at the white box view (story **1310**). If a there are sessions keys related to the response returned to a sender, then I want the start point of the sender to contain child checkpoints (output points) for these session keys. + +**1040:** Given is that I am looking at the white box view (story **1310**). If a sender has parameters, then I want the start point of the sender to contain child nodes (input points) for these parameters. + +**1041:** Given is that I am looking at the white box view (story **1310**). For each pipe, I want to see an info checkpoint with the source code of that pipe. + +**1048:** As a support engineer or Frank developer, I want a single report when my adapter calls another adapter via a JavaListener. This way, I do not have to browse multiple reports to examine how my incoming message was processed. The sub-adapter checkpoints should have a common ancestor. When I collapse that ancestor, I want to see only one node for everything done in the sub-adapter. **1050:** As a support engineer or Frank developer, I want to see the value of the selected node in the debug tree. -**1052:** When I have selected the checkpoint of a session key in the tree view, the value I want to see (story **1050**) is the value of the session key. +**1052:** When I have selected the checkpoint of a session key or a parameter in the tree view, the value I want to see (story **1050**) is the value of the session key or the parameter value. -**1054:** When I have selected a checkpoint that is not a session key, the value I want to see is the message along with its FF!-generated metadata. +**1054:** When I have selected a start point / end point of a pipeline / pipe / sender, I want to see the incoming / outcoming message. Along with that message, FF!-generated metadata should be shown. **1056:** When I have selected the root node of a report, the value I want to see is the report in XML form, the ladybug-generated metadata, the description (story **2040**) and the XSLT transformation (story **2010**). @@ -221,7 +237,7 @@ NOTE: Presently, some features of Ladybug are attached to the root node of a rep **1310:** Given is that I as a support engineer or Frank developer am investigating an issue. In the debug tree, I want the option to see all the checkpoints within each report. This is known as the white box view. -**1320:** Given is that I as a user am investigating an issue. In the debug tree, I want the option to see a only the following checkpoints: Checkpoints about communicating with external systems plus checkpoints related to adapters calling each other (typically through `IbisLocalSender`). This is known as the gray box view. +**1320:** Given is that I as a user am investigating an issue. In the debug tree, I want the option to see a only the following checkpoints: Checkpoints about communicating with external systems plus checkpoints related to adapters calling each other (typically through `IbisLocalSender`). When adapters call each other, the flow of the message should appear in one report as stated in story **1048**. This is known as the gray box view. **1330:** Given is that multiple users with multiple interests use the debug tree. As a user I want that the view I select (story **510**) also determines which checkpoints of my reports are shown: **1300**, **1310** or **1320**, in other words white box, gray box or black box. From c98c93588d236f1766d7783078a22fe6184ec606 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 15:22:51 +0200 Subject: [PATCH 16/21] Be more precise about what checkpoints we should have - sender parameters --- misc/LADYBUG_USER_STORIES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 583be623..c3c794ad 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -142,6 +142,7 @@ Sender | message | Start point | Message sent Sender | message | End point | Response message Sender | error | Abort point | Sender | session key | input point | +Sender | parameter | input point | Sender | session key | output point | Pipe | message | Start point | Message received Pipe | message | End point | Output message From 3c52919dc81d653a3994358f1086dfc50805d4d1 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 15:27:28 +0200 Subject: [PATCH 17/21] Typo --- misc/LADYBUG_USER_STORIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index c3c794ad..3f91a725 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -203,7 +203,7 @@ For completeness, it should be noted that Frank configurations can also be writt **1052:** When I have selected the checkpoint of a session key or a parameter in the tree view, the value I want to see (story **1050**) is the value of the session key or the parameter value. -**1054:** When I have selected a start point / end point of a pipeline / pipe / sender, I want to see the incoming / outcoming message. Along with that message, FF!-generated metadata should be shown. +**1054:** When I have selected a start point / end point of a pipeline / pipe / sender, I want to see the incoming / outgoing message. Along with that message, FF!-generated metadata should be shown. **1056:** When I have selected the root node of a report, the value I want to see is the report in XML form, the ladybug-generated metadata, the description (story **2040**) and the XSLT transformation (story **2010**). From 0956e85939f007ff20778f71fe4384d1b697c188 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 15:28:09 +0200 Subject: [PATCH 18/21] Typo --- misc/LADYBUG_USER_STORIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 3f91a725..dd741a2e 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -203,7 +203,7 @@ For completeness, it should be noted that Frank configurations can also be writt **1052:** When I have selected the checkpoint of a session key or a parameter in the tree view, the value I want to see (story **1050**) is the value of the session key or the parameter value. -**1054:** When I have selected a start point / end point of a pipeline / pipe / sender, I want to see the incoming / outgoing message. Along with that message, FF!-generated metadata should be shown. +**1054:** When I have selected a start point / end point of a pipeline / pipe / sender, I want to see the incoming / outgoing message. Along with that message, the FF!-generated metadata should be shown. **1056:** When I have selected the root node of a report, the value I want to see is the report in XML form, the ladybug-generated metadata, the description (story **2040**) and the XSLT transformation (story **2010**). From 758a46abc65845271e68dfd07d5c0d17bececc14 Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 15:29:28 +0200 Subject: [PATCH 19/21] Typo --- misc/LADYBUG_USER_STORIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index dd741a2e..0055a099 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -209,7 +209,7 @@ For completeness, it should be noted that Frank configurations can also be writt **1058:** Given is that I have selected a checkpoint like described in story **1054**. If the message is too large, the message should be shown truncated and a warning should be shown. The warning should make clear that the user is not seeing the complete message. -**1059:** As a Frank!Developer, I want to be able to configure a threshold for story **1058**. When a message is longer than the configured threshold, then the message is shown truncated. +**1059:** As a Frank developer, I want to be able to configure a threshold for story **1058**. When a message is longer than the configured threshold, then the message is shown truncated. **1100:** As a support engineer or Frank developer, I want the option to remove a report from the tree view when I am done with it. This does not mean that a report is removed from persistent storage. From 5eba82cc56ecbb075453588a0996fcbc472844df Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 16:24:53 +0200 Subject: [PATCH 20/21] Rerunning reports in the debug tab --- misc/LADYBUG_USER_STORIES.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index 0055a099..de78c61c 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -102,6 +102,8 @@ NOTE: Story **500** is implemented in the ladybug backend because you can create **520:** Given is that I as a user am doing some analysis about my reports and that I have put some filters on the report table. Given is that I select another view during my analysis. For each metadata field that appears in the table for both views, I want that my filter on that field remains. This way I can continue my analysis without having to retype my filters unnecessarily. +**600:** As a service manager, I want that all reports I see in the report table are original captures. I do not want to see reports that were edited after capture (as can be done according to story **2060**) so that I can be sure about the integrity of my data. + # I want to understand how the message captured by a report was processed **1000:** As a support engineer or Frank developer, I want to see the name of each checkpoint that is shown in the tree view. The name is not required to be unique. @@ -226,7 +228,6 @@ For completeness, it should be noted that Frank configurations can also be writt NOTE: Presently, some features of Ladybug are attached to the root node of a report. * In the old Echo2 GUI, there is an "Edit" button for the debug tree that puts the report in "edit mode". In edit mode, you have an editable message when you click a node in the tree view. There are also metadata fields, some of them editable and some of them read-only. When you select the top level node, you can edit a description. This way you can add a description of a report that exists in the debug tab. -* TODO: Do we want reports to be editable in the debug tab? If this is allowed, users cannot trust that reports in the debug tab are always original captures. If editing reports in the debug tab is prohibited, the user can still copy them to the test tab and edit these copies. A drawback is that the set of test cases in the test tab can be contaminated with reports that are there only temporarily. * If we decide that reports can be edited in the Debug tab, then the requirements of stories **2000** - **2050** apply. * In the test tab you can "open" a report. This is the user interface for main user story [I want to turn a report into a test case](#i-want-to-turn-a-report-into-a-test-case). Doing so opens a new tab with a tree view with editable node information next to it, like "edit mode" in the debug tab's tree view. Also in this case the root node of a report is relevant in the current implementation of Ladybug. * When you click the root node of a report you see it as XML. This combines nicely with an edit field to enter an XSLT transformation (story **2010**) @@ -260,6 +261,12 @@ NOTE: Story **2012** can be implemented by giving original-capture reports a def **2050:** Given is that I am building an automated test from a report. If I have done some editing and save my results, I want that all views of the report are updated automatically without the need to press a refresh button. +**2060:** Given is that I as a Frank developer am testing my application in the DTAP test environment. When I have a report in the debug tab for which I do not like the results, I want the option to edit the report there, similar to stories **2000** - **2050**. I do this with the aim of rerunning the report. If the edited report behaves as I want, I can download it and send to my collleague Frank developer so that my colleague can fix our app. + +**2070:** Given is that I as a Frank developer have edited a report in the debug tab (story **2060**). After saving my edits, a report with my edits should be open in the debug tree so that I still have access to it, even though it is not in the report table as is required by story **600**. + +TODO: Should we allow stories **2060** and **2070** when only one report is allowed in the debug tree? We could allow that. The implication is that when you edit a report in the debug tree, that the original report is removed from the debug tree when the edits are saved. + # I want to re-run (test) reports to test my Frank application **3000:** Given is that I am testing my application as a Frank developer. When I enter the test tab I want to see all reports that I have prepared as test cases. @@ -268,18 +275,20 @@ NOTE: Story **2012** can be implemented by giving original-capture reports a def **3010:** Given is that I am testing my application as a Frank developer. I want the option to *rerun* reports. Rerunning a report means that the Frank adapter that produced the report is re-executed. The same input message is supplied. For each pipe, the produced output is compared with the value stored with the corresponding checkpoint. The test succeeds if the new messages are the same after applying the configured XSLT transformation (user story **2010**). -**3020:** Given is that I am testing my application as a Frank developer. I want the option to rerun a single report. +**3020:** Given is that I am testing my application as a Frank developer. I want the option to rerun a single report in the test tab. **3030:** Given is that I am testing my application as a Frank developer. I want the option to organize the reports in the Test tab. I want to create groups of tests that can have sub-groups. A tree structure in which the composite nodes are test groups and the leaf nodes are reports. This structure gives me an overview of the tests I have. -**3040:** Given is that I am testing my application as a Frank developer. I want the option to select test cases and groups of test cases. I want the option to rerun the tests I selected. This gives me fine-grained control over my test runs when I want to test parts of my Frank application. +**3040:** Given is that I am testing my application as a Frank developer. I want the option to select test cases and groups of test cases in the test tab. I want the option to rerun the tests I selected. This gives me fine-grained control over my test runs when I want to test parts of my Frank application. **3050:** Given is that I am testing my application as a Frank developer. I want the option to rerun all reports that are in the Test tab, allowing me to test my Frank application with a single click. -**3060:** Given is that I have reran a few reports and that I want to do new tests. As a user I want the option to reset the report generator, which means that all shown test results are cleared. When I rerun my tests after resetting the report generator, I want that all test results I see come from test started after the moment of resetting. +**3060:** Given is that I have reran a few reports in the test tab and that I want to do new tests. As a user I want the option to reset the report generator, which means that all shown test results are cleared. When I rerun my tests after resetting the report generator, I want that all test results I see come from tests started after the moment of resetting. NOTE: Story **3060** is not trivial because rerunning reports happens in the background. +**3070:** Given is that I as a Frank developer are testing my app in the DTAP test environment. I want the option to rerun a single report in the debug tab. This is relevant in the context of story **2060**. + **3100:** Given is that I have rerun a report as a Frank developer and that this test failed. I want the option to compare the original capture to the new results. I want to see the two datasets next to each other such that I can see what is the same and what is different. **3108:** Given is that I am comparing a report in the context of story **3100**. On one side I have the checkpoints in the report and on the other side I have the checkpoints produced by the rerun. As a user, I want that the selected checkpoint is synchronized. If I select a checkpoint on one side, I want that the corresponding checkpoint on the other side is selected automatically. This helps me to do my analysis more quickly. @@ -294,9 +303,7 @@ NOTE: Details of the algorithm implied in **3110** and **3120** are not needed h **3210:** As a Frank developer I want to use reports as a means to communicate with my colleagues. I want to construct a report and send it to someone else, asking him to update our application such that the test will pass. -NOTE: Jaco suggested that there should be an edit button in the debug tab. A disadvantage is that if reports can be edited in the debug tab, then you cannot be sure that all reports in the debug tab are original captures. Jaco is also satisfied if there is a disabled edit button in the debug tab. This button can have a mouse-over text that suggests copying to the test tab first. - -TODO: Discuss whether we want that reports can be downloaded and uploaded in the debug tab. It may be better to only have this in the test tab. +**3220:** Because of the context of story **2060**, downloading and uploading reports should be possible both in the debug tab and in the test tab. # I want to configure whether my Frank application does produce reports From a5cd87b6099b385bb548574b2422a6f7106a1bca Mon Sep 17 00:00:00 2001 From: Martijn Dirkse Date: Thu, 18 Jul 2024 16:28:36 +0200 Subject: [PATCH 21/21] Clean up old notes that are now in stories --- misc/LADYBUG_USER_STORIES.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/misc/LADYBUG_USER_STORIES.md b/misc/LADYBUG_USER_STORIES.md index de78c61c..a59d2131 100644 --- a/misc/LADYBUG_USER_STORIES.md +++ b/misc/LADYBUG_USER_STORIES.md @@ -225,14 +225,6 @@ For completeness, it should be noted that Frank configurations can also be writt **1240:** Story **1200** has as a consequence that each report in the tree view should have a single root node, otherwise you could not see which node belonged to each report. -NOTE: Presently, some features of Ladybug are attached to the root node of a report. - -* In the old Echo2 GUI, there is an "Edit" button for the debug tree that puts the report in "edit mode". In edit mode, you have an editable message when you click a node in the tree view. There are also metadata fields, some of them editable and some of them read-only. When you select the top level node, you can edit a description. This way you can add a description of a report that exists in the debug tab. -* If we decide that reports can be edited in the Debug tab, then the requirements of stories **2000** - **2050** apply. -* In the test tab you can "open" a report. This is the user interface for main user story [I want to turn a report into a test case](#i-want-to-turn-a-report-into-a-test-case). Doing so opens a new tab with a tree view with editable node information next to it, like "edit mode" in the debug tab's tree view. Also in this case the root node of a report is relevant in the current implementation of Ladybug. -* When you click the root node of a report you see it as XML. This combines nicely with an edit field to enter an XSLT transformation (story **2010**) -* When you click the root node of a report you have the option there to enter the description (story **2040**). - **1250:** Given is that I am doing some analysis involving multiple reports. Given is also that I have configured the tree view to allow multiple reports (story **1200**). If the tree view is empty and if I open multiple reports simultaneously, the reports should appear in the tree view in the same sequence as they are in the report table. This way the reports in the tree view have a predictable sequence, helping me to do my analysis more efficiently. **1300:** Given is that I as a service manager am investigating an issue with my application. In the debug tree, I want the option to see only the checkpoints within each report that are about communicating with external systems. This is currently known as the black box view.