diff --git a/.babelrc b/.babelrc
index 220c557b..0b86a087 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,4 +1,5 @@
{
- "presets": ["env", "react"],
- "plugins": ["transform-class-properties", "babel-root-slash-import", "babel-plugin-transform-object-rest-spread"]
+ "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
+ // this plugin add support for async/await
+ "plugins": ["@babel/plugin-transform-runtime"]
}
diff --git a/.esdoc.json b/.esdoc.json
deleted file mode 100644
index 7eeba9e3..00000000
--- a/.esdoc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "source": "./src",
- "destination": "./docs",
- "excludes": ["demo*", "demo\\/.*"],
- "plugins": [
- {"name": "esdoc-standard-plugin"},
- {"name": "esdoc-jsx-plugin", "option": {"enable": true}},
- {"name": "esdoc-ecmascript-proposal-plugin", "option": {"all": true}}
- ]
-}
diff --git a/.gitignore b/.gitignore
index c3e2b13c..5a381dd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Build dir
dist/
lib/
+types/
# Docs
docs/
@@ -22,3 +23,5 @@ node_modules/
.lvimrc
.DS_Store
/.idea
+# Storybook
+storybook-static/
diff --git a/.storybook/.babelrc b/.storybook/.babelrc
deleted file mode 100644
index b35ca240..00000000
--- a/.storybook/.babelrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "presets": ["@babel/preset-env", "@babel/preset-react"],
-}
-
\ No newline at end of file
diff --git a/.storybook/main.js b/.storybook/main.js
deleted file mode 100644
index 26dfeaf6..00000000
--- a/.storybook/main.js
+++ /dev/null
@@ -1,10 +0,0 @@
-module.exports = {
- "stories": [
- "../src/**/*.stories.mdx",
- "../src/**/*.stories.@(js|jsx|ts|tsx)"
- ],
- "addons": [
- "@storybook/addon-links",
- "@storybook/addon-essentials"
- ]
-}
\ No newline at end of file
diff --git a/.storybook/preview.js b/.storybook/preview.js
deleted file mode 100644
index 48afd568..00000000
--- a/.storybook/preview.js
+++ /dev/null
@@ -1,9 +0,0 @@
-export const parameters = {
- actions: { argTypesRegex: "^on[A-Z].*" },
- controls: {
- matchers: {
- color: /(background|color)$/i,
- date: /Date$/,
- },
- },
-}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8660128a..940f07d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,208 @@
-# Change Log
-
## Unreleased
+
+## v2.12.0
+
+* [Fix exception when zooming or resizing window due to undefined grid reference](https://github.com/flower-platform/react-timeline-10000/pull/107)
+* [Add public api for zoom in/out](https://github.com/flower-platform/react-timeline-10000/pull/106)
+
+## v2.11.0
+
+* [Prevented wrong segments on empty rows by giving them IDs with a special prefix](https://github.com/flower-platform/react-timeline-10000/pull/102)
+* [Fix to avoid rendering of the context menu and scrollbar at every mouse move](https://github.com/flower-platform/react-timeline-10000/pull/99)
+* [Add `scrollToItem` feature](https://github.com/flower-platform/react-timeline-10000/pull/100)
+* [Fix `onItemHover` and `onItemLeave` firing too often on items with children](https://github.com/flower-platform/react-timeline-10000/pull/98)
+* [Change color used for BackgroundGradient](https://github.com/flower-platform/react-timeline-10000/pull/96)
+* [Add `verticalGapBetweenOverlappingItems` and `rowTopBottomPadding` properties](https://github.com/flower-platform/react-timeline-10000/pull/97)
+
+## v2.10.0
+
+* [Default split size](https://github.com/flower-platform/react-timeline-10000/pull/94/files)
+
+## v2.9.0
+
+* [Fix to allow variable row heights + programmatic scroll](https://github.com/flower-platform/react-timeline-10000/pull/69/files)
+* [Small fix for resize cursor size](https://github.com/flower-platform/react-timeline-10000/pull/89/files)
+
+## v2.8.0, v2.8.1
+
+* [Add `zoomEnabled` flag](https://github.com/flower-platform/react-timeline-10000/pull/90/files)
+* [Small fix for context menu on mobile and item leave event](https://github.com/flower-platform/react-timeline-10000/pull/86/files)
+* [Update comment for rct9k-items-inner style class](https://github.com/flower-platform/react-timeline-10000/pull/88/files)
+
+## v2.7.5
+
+* [Allow group.id to be any number (remove the "consecutive numbers starting from 0" restriction)](https://github.com/flower-platform/react-timeline-10000/pull/74/files)
+
+## v2.7.4
+
+* Updated `@famiprog-foundation/tests-are-demo` @ v1.0.1.
+
+## v2.7.3
+
+* [Improved API for Context Menu](https://github.com/flower-platform/react-timeline-10000/pull/79)
+* [Add z-index to now marker to show on top of items, layers](https://github.com/flower-platform/react-timeline-10000/pull/82)
+* [Small fix for zoom when have multiple instances, catch the event only if mouse is on our instance body](https://github.com/flower-platform/react-timeline-10000/pull/81)
+* [Small issue at update when useMoment props is true](https://github.com/flower-platform/react-timeline-10000/pull/83)
+
+## v2.7.1
+
+* Updated `@famiprog-foundation/scriptable-ui` @ v1.0.0.
+
+## v2.7.0
+
+* [Zoom](https://github.com/flower-platform/react-timeline-10000/pull/58) and [small fix for Firefox](https://github.com/flower-platform/react-timeline-10000/pull/80)
+
+## v2.6.1
+
+* [Error when moving the mouse and the grid inside the gantt in not yet rendered](https://github.com/flower-platform/react-timeline-10000/pull/77)
+
+## v2.6.0
+
+* Internal: for `demo-app`, upgraded storybook version to v7.5. It also uses vite now.
+* Small issue: on props changed, the width of the table was reset to the original value.
+* [Highlighted interval positioned at the beginning of the gantt was not displayed](https://github.com/flower-platform/react-timeline-10000/pull/70)
+* [Controlled/uncontrolled split + rename `onTableResize` into `onSplitChange`](https://github.com/flower-platform/react-timeline-10000/pull/75)
+* [Add `displayItemOnSeparateRowIfOverlap` property](https://github.com/flower-platform/react-timeline-10000/pull/72/files)
+
+## v2.5.0
+
+* [Separated lib and demo-app](https://github.com/flower-platform/react-timeline-10000/commit/b5936969f7ffe67a52139c04b2275849e9c5b078)
+* [Upgraded to TAD v0.11.0](https://github.com/flower-platform/react-timeline-10000/commit/a87a58b74898e3a5017b8e4d5028e9e5a4c0f325), generated screenshots, .md reports, and first .md docs
+
+## v2.4.1
+
+### Fixed
+
+* [Reseting start/end date didn't work](https://github.com/flower-platform/react-timeline-10000/pull/65)
+
+## v2.4.0
+
+### Added
+
+* [Horizontal scrollbar](https://github.com/flower-platform/react-timeline-10000/pull/57)
+* [Added `onTableResize` property](https://github.com/flower-platform/react-timeline-10000/pull/62)
+
+### Fixed
+
+* [External drag and drop doesn't work](https://github.com/flower-platform/react-timeline-10000/pull/60)
+* [Changing the `width` property of the table didn't updated of the UI](https://github.com/flower-platform/react-timeline-10000/pull/59)
+* [Various small isues](https://github.com/flower-platform/react-timeline-10000/pull/63)
+ * Problem with the scroll after reseting the `groups`
+ * `SplitPanel` has `absolute` position instead of `relative`position
+ * Exception when dragging above the timeline
+ * Exception when reseting the `groups` of a gantt that was scrolled
+ * Gantt surface was not receiving events because of the `backgroundLayers`
+ * Background layers were overlapping the vertical scrollbar
+
+## v2.3.0
+
+### Added
+
+* [A `
` is used for displaying rows](https://github.com/flower-platform/react-timeline-10000/pull/52), i.e. in the left part of the Gantt. `
` comes from the [FixedDataTable lib](https://schrodinger.github.io/fixed-data-table-2/). This addition is **not backwards compatible**.
+
+## v2.2.4
+
+### Added
+
+* `forceDragToCreateMode` example in storybook
+* `forceDragToCreateMode` test case
+
+### Changed
+
+* [Modify selection trigger: from `click` to `mouseDown`](https://github.com/flower-platform/react-timeline-10000/pull/50)
+
+### Fixed
+
+* Drag to create rectangle was blue instead of green when `forceDragToCreateMode = true`
+* [Parameter `selectedItems` of `onSelectionChange` handler was `number[]` instead of `(number|string)[]`](https://github.com/flower-platform/react-timeline-10000/pull/51)
+
+## v2.2.3
+
+### Fixed
+
+Right click selection didn't worked on custom segments with a complex children hierarchy
+
+## v2.2.2
+
+### Fixed
+
+* [Various small issues](https://github.com/flower-platform/react-timeline-10000/pull/47)
+ * drag to create popup auto-closing
+ * visual improvements of the selected and hovered segments style
+ * Error in console when running an action without `run` property defined
+ * Right clicking on one segments caused drag to select on the entire row
+ * A semantic-ui `Icon` can be passed to IAction.icon
+ * On Firefox a thin blue line appeared on top of segments
+ * Improve storybook documentation for "drag to create" feature
+
+## v2.2.1
+
+### Added
+
+* [In some places, key of type string was not supported](https://github.com/flower-platform/react-timeline-10000/pull/40). Now keys of type `number | string` are supported.
+
+### Fixed
+
+* [Bug related to `key of type string was not supported`](https://github.com/flower-platform/react-timeline-10000/pull/45)
+
+## v2.2.0
+
+### Added
+
+* [Click and double click handler for a group](https://github.com/flower-platform/react-timeline-10000/pull/11)
+* [Drag to create](https://github.com/flower-platform/react-timeline-10000/pull/25)
+* [Context menu and selection](https://github.com/flower-platform/react-timeline-10000/pull/37)
+
+### Fixed
+
+* [Various small isues](https://github.com/flower-platform/react-timeline-10000/pull/29)
+ * style was considered mandatory in HighlightedInterval
+ * align BackgroundLayer with TimelineBody
+ * rowLayers were not rendererd correctly after update
+ * typo
+ * weekends calculation depended on moment.locale
+ * remove margin and border from selection box
+* [Drag to create issues](https://github.com/flower-platform/react-timeline-10000/pull/32)
+ * selection was going up on mouse move on different browsers
+ * right click was prevented even if it was not in `drag to create` mode
+* Item click was not working for complex renderers. A special css class was searched only 2 levels. Now there is a loop, so deeper nesting is possible.
+
+## v2.1.1
+
+### Fixed
+
+* [In some cases, depending on the parent DomElem, scrollbars appear/disappear in an infinite loop](https://github.com/flower-platform/react-timeline-10000/issues/26)
+
+## v2.1.0
+
+### Added
+
+* [Background layer: vertical grid, highlight weekends, highlighted intervals, now marker, markers](https://github.com/flower-platform/react-timeline-10000/pull/19)
+
+## v2.0.2
+
+### Fixed
+
+* [Upgraded color lib and code updated](https://github.com/flower-platform/react-timeline-10000/pull/20)
+
+## v2.0.1
+
+The first official version published since the project was forked from `react-timeline-9000` to `@famiprog-foundation/react-gantt`.
+
+### Added
+
+| Short description | Issue | Pull request #19|
+| - | - | - |
+| Multiple columns / table mode. | React9k/react-timeline-9000#190 | React9k/react-timeline-9000#243 |
+| Support for milliseconds. | React9k/react-timeline-9000#196 | React9k/react-timeline-9000#239 |
+| Use of date/millis for compatibility w/ Redux. Moment.js support is still kept. | React9k/react-timeline-9000#221 | React9k/react-timeline-9000#241 |
+| Storybook | React9k/react-timeline-9000#234 | React9k/react-timeline-9000#237 |
+| Improved ItemRenderer and nice default styles | | [commit](https://github.com/flower-platform/react-timeline-10000/commit/e005eab4b4fbee1c737c2ebf323ad65304cdc26f)
+| Generate TypeScript `.d.ts` files. Storybook uses TS | | [commit](https://github.com/flower-platform/react-timeline-10000/commit/a6bb813fe2c229c97aff306d3bf9c79ce23e6503)
+| minor | | React9k/react-timeline-9000#257 |
+| minor | | React9k/react-timeline-9000#260 |
+| minor | React9k/react-timeline-9000#271 | React9k/react-timeline-9000#272 |
+
## v1.1.2
### Added
- Pass resolution props to timeline
diff --git a/Makefile b/Makefile
index e6538614..fd2afaad 100644
--- a/Makefile
+++ b/Makefile
@@ -17,10 +17,10 @@ run: install
yarn start
test: install
- env NODE_PATH=$$NODE_PATH:$$PWD/src/ $(mocha) --require babel-core/register --require ignore-styles "./src/**/*.test.js"
+ env NODE_PATH=$$NODE_PATH:$$PWD/src/ $(mocha) --require @babel/register --require ignore-styles "./src/**/*.test.js"
test-watch: install
- env NODE_PATH=$$NODE_PATH:$$PWD/src/ $(mocha) -w --require babel-core/register --require ignore-styles "./src/**/*.test.js"
+ env NODE_PATH=$$NODE_PATH:$$PWD/src/ $(mocha) -w --require @babel/register --require ignore-styles "./src/**/*.test.js"
install:
yarn
@@ -28,3 +28,4 @@ install:
clean:
rm -rf dist
rm -rf lib
+ rm -rf types
diff --git a/README.md b/README.md
index 2f4b5d75..41f66d06 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,87 @@
-# React Timeline 9000
+# React Timeline 10000 (forked by the Flower Platform team)
+
+## About `demo-app`
+
+Previously, there was a single project containing the lib + demo app. Now, the demo, scenarios, tests are demo: exist in the `demo-app` subproject. This way, `demo-app` can depend on `foundation`, which itself depends on this lib. Thanks to the separation, we don't have a dependency cycle.
+
+Currently the dependency towards `foundation` is done by using its source dir. Hence 1/ `foundation` needs to be cloned from git, next to this repo. And 2/ one should run from `foundation-react`: `yarn install`. `foundation` can be also be used as a lib. This is experimental. Look in `demo-app/vite.config.ts` for info.
+
+In `demo-app/tsconfig.json` and `demo-app/vite.config.ts`, we created the `@famiprog-foundation/react-gantt` alias. This means that from `demo-app` source files:
+
+```ts
+// we can do this
+import { Timeline, ItemRenderer } from "@famiprog-foundation/react-gantt";
+
+// instead of this
+import { ItemRenderer } from "../../src";
+```
+
+---
+
+## Intro
+
+This fork is developed and maintained by the "Flower Platform" team (which FYI has authored in the past [Gantt4Flex](http://gantt4flex.crispico.com/), a popular (at that time) commercial Gantt diagramming component during the [Adobe Flex](http://flex.apache.org/) era). The motivation of our contributions is driven by the fact that we use "react-timeline-9000" in some of our industrial projects. The intention is to develop new features that we can use ASAP in our software. ALL our contributions are meant to be integrated in the upstream repo, so they are developed having this constraint in mind. The upstream repo is the **official** one (for releases, clone, adding issues, etc.). And this is to be considered as an internal repo for us = the Flower Platform team.
+
+Admin discussions w/ the upstream repo team are held in [this discussion](https://github.com/React9k/react-timeline-9000/discussions/255).
+
+## Process and versioning
+
+`package.json` on the **upstream repo** / `master` branch looks like this:
+
+```
+{
+ "name": "react-timeline-9000",
+ "version": "1.1.3",
+ ...
+```
+
+But in **this repo** / `master-flower-platform` branch (which is considered to be the main branch of this repo) we have:
+
+```
+{
+ "name": "@crispico/react-timeline-10000",
+ "version": "1.1.3-fp-ver-3",
+ ...
+```
+
+The `name` is changed so that we can publish it in our local NPM repo. We append to the original `version` the suffix `-fp-ver-N`. Where N is the version from Flower Platform. E.g. 3 means we added 3 commits compared to the original upstream. When a new contribution is added to our main branch = `master-flower-platform`, we increment this number. So we'll have e.g.: *1.1.3-fp-ver-**4***, *1.1.3-fp-ver-**5***, *1.1.**4**-fp-ver-**5***, *1.1.**4**-fp-ver-**6***, etc.
+
+Before we begin new work, we should first create an issue in the upstream repo:
+* we prefix it w/ *[rt10000]*, like in this [example](https://github.com/React9k/react-timeline-9000/issues/190);
+* we explain what we want to do and ask for advice if needed.
+
+New work is always done on new branches. E.g. `my-new-branch`. At the end of the work we **squash everything into a single commit** and perform a pull request towards upstream (mentioning the original issue cf. above). If we need the commit ASAP into our main branch:
+* we don't need to wait for their approval of the PR;
+* we make a PR and/or merge it into `master-flower-platform`;
+* then, we increment *fp-ver-N* to *fp-ver-N+1* cf. above.
+
+## Working with linked libraries in development
+
+Sometimes even if I ```yarn link``` a library, when running storybook it doesn't take into account the linked library.
+This was noticed working with the ```fixed-data-table-2``` libray as a linked library.
+
+The solution for this problem was mentioned here: https://dev.to/hontas/using-vite-with-linked-dependencies-37n7: it should be added in the ```vite.config.ts``` file, on the ```optimizeDeps``` section: ```exclude: ["fixed-data-table-2"]```
+
+Even the above solution worked for our case, we don't understand very good from were the old library version was taken from. Because in our case, even if we removed the ```node_modules/.cached```, an old version of the library was used (could be that it was requested from the npm registry, because in ```package.json``` the old version was referenced).
+
+## Tracking of the pull requests submitted to the upstream repo
+
+We prefix our issues in the upstream repo w/ `[rt10000]`.
+
+| Issue (mouse hover for title) | Pull request | Merged |
+| - | - | - |
+| React9k/react-timeline-9000#190 | React9k/react-timeline-9000#243 | yes |
+| React9k/react-timeline-9000#196 | React9k/react-timeline-9000#239 | yes |
+| React9k/react-timeline-9000#221 | React9k/react-timeline-9000#241 | yes |
+| React9k/react-timeline-9000#234 | React9k/react-timeline-9000#237 | yes |
+| minor | React9k/react-timeline-9000#257 | yes |
+| minor | React9k/react-timeline-9000#260 | yes |
+| React9k/react-timeline-9000#271 | React9k/react-timeline-9000#272 | |
+
+## Original `README.md` of the upstream repo is below
+
+---
+
A performance focused timeline component in react
## Build Status
[](https://travis-ci.org/BHP-DevHub/react-timeline-9000)
@@ -60,6 +143,7 @@ See http://react-timeline-9000.s3-website-ap-southeast-2.amazonaws.com/docs/ for
| timelineMode | | |
| timebarFormat | | |
| itemRenderer | | |
+| itemClassName | | Class name applied to all items |
| groupRenderer | | |
| shallowUpdateCheck | False | If true timeline will try to minimize re-renders . Set to false if items don't show up/update on prop change |
| forceRedrawFunc | () => False | Function called when `shallowUpdateCheck`==true. If returns true the timeline will be redrawn. If false the library will decide if redrawing is required |
@@ -72,18 +156,30 @@ See http://react-timeline-9000.s3-website-ap-southeast-2.amazonaws.com/docs/ for
| groups |
| selectedItems |
+### Items
+
+Required props:
+* key - number or string
+
+### Groups
+
+Required props:
+* id - number - needs to be consecutive
+
## Callbacks
-| Name |
-| ---------------- |
-| onItemClick |
-| onItemDoubleClick |
-| onItemContext |
-| onInteraction |
-| onRowClick |
-| onRowContext |
-| onRowDoubleClick |
-| onItemHover |
-| onItemLeave |
+| Name |
+| ---------------- |
+| onItemClick |
+| onItemDoubleClick |
+| onItemContext |
+| onInteraction |
+| onRowClick |
+| onRowContext |
+| onRowDoubleClick |
+| onItemHover |
+| onItemLeave |
+| onGroupRowClick |
+| onGroupRowDoubleClick |
# Styling
* View `src/style.css` for styling examples.
@@ -97,5 +193,4 @@ See http://react-timeline-9000.s3-website-ap-southeast-2.amazonaws.com/docs/ for
| Timeline items | 3 |
| Timeline items when dragging/resizing | 4 |
| Selection box (for multi-select) | 5 |
-| Group column | 6 |
diff --git a/demo-app/.eslintrc.cjs b/demo-app/.eslintrc.cjs
new file mode 100644
index 00000000..29cb6d5a
--- /dev/null
+++ b/demo-app/.eslintrc.cjs
@@ -0,0 +1,14 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'plugin:storybook/recommended'],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/demo-app/.storybook/main.ts b/demo-app/.storybook/main.ts
new file mode 100644
index 00000000..3b8e2fe6
--- /dev/null
+++ b/demo-app/.storybook/main.ts
@@ -0,0 +1,35 @@
+import { mergeConfig } from 'vite';
+
+export default {
+ "stories": [
+ "../src/**/*.stories.mdx",
+ "../src/**/*.stories.@(js|jsx|ts|tsx)"
+ ],
+
+ "addons": [
+ "@storybook/addon-links",
+ "@storybook/addon-essentials",
+ "@storybook/addon-storysource",
+ "@storybook/addon-mdx-gfm"
+ ],
+
+ "staticDirs": [
+ '../docs'
+ ],
+
+ framework: {
+ name: "@storybook/react-vite",
+ options: {}
+ },
+
+ async viteFinal(config) {
+ return mergeConfig(config, {
+ server: {
+ fs: {
+ // idem cf. demo-app/vite.config.ts; apparently some settings (such as this one) are not inherited
+ allow: ['..'],
+ },
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/demo-app/.storybook/preview.jsx b/demo-app/.storybook/preview.jsx
new file mode 100644
index 00000000..47f0b14d
--- /dev/null
+++ b/demo-app/.storybook/preview.jsx
@@ -0,0 +1,47 @@
+import "semantic-ui-css/semantic.min.css";
+import { Label, Segment } from "semantic-ui-react";
+
+import '../src/stories/storybook.css';
+import '../../src/style.css';
+
+export const parameters = {
+ // actions: { argTypesRegex: "^on[A-Z].*" },
+ previewTabs: {
+ 'storybook/docs/panel': { hidden: true }
+ },
+ viewMode: 'story',
+ controls: {
+ disable: true,
+ // matchers: {
+ // color: /(background|color)$/i,
+ // date: /Date$/,
+ // },
+ },
+ actions: {
+ disable: true
+ },
+ options: {
+ storySort: {
+ method: 'configure',
+ includeNames: true,
+ order: [
+ 'Features',
+ ['Basic', 'Item Renderer', 'Background Layer', '*']
+ ]
+ }
+ }
+}
+
+export const decorators = [
+ (Story, context) => <>
+ {context.parameters.scenarios && }
+
+
+
+ >
+];
+
+const ScenariosList = (props) =>
+ Illustrated scenarios:
+ {props.scenarios.map((scenario, i) => )}
+
\ No newline at end of file
diff --git a/demo-app/index.html b/demo-app/index.html
new file mode 100644
index 00000000..77742933
--- /dev/null
+++ b/demo-app/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/demo-app/package.json b/demo-app/package.json
new file mode 100644
index 00000000..771ea392
--- /dev/null
+++ b/demo-app/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "demo-app",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview",
+ "docs": "typedoc && mv docs/index.html docs/index-docs.html",
+ "storybook": "yarn docs && storybook dev -p 6006",
+ "storybook-build": "yarn docs && cross-env NODE_OPTIONS=--max-old-space-size=3096 storybook build",
+ "storybook-move": "rm -r ../../flower-platform.github.io/foundation-react-gantt; mv storybook-static ../../flower-platform.github.io/foundation-react-gantt",
+ "storybook-build-move": "yarn storybook-build && yarn storybook-move",
+ "tad-puppeteer-3000": "node ../node_modules/@famiprog-foundation/tests-are-demo/src/node/tad-puppeteer.mjs \"http://localhost:3000/?TestsAreDemo&puppeteer\"",
+ "tad-puppeteer-3000-screenshots": "node ../node_modules/@famiprog-foundation/tests-are-demo/src/node/tad-puppeteer.mjs \"http://localhost:3000/?TestsAreDemo&puppeteer&forceStepByStep\"",
+ "tad-gen-doc": "node ../node_modules/@famiprog-foundation/tests-are-demo/src/node/tad-gen-doc.mjs"
+ },
+ "// COMMENT regarding dependencies": "For this app, the parent app is practically not a lib. It has a/ source files and b/ `node_modules` w/ deps. So we don't define a dep towards the parent project. And the parent proj also has `node_modules` w/ deps needed by the files in src. And node will look there as well. Node 'climbs' dirs to look for `node_modules`/deps.",
+ "devDependencies": {
+ "@storybook/addon-actions": "^7.5.0",
+ "@storybook/addon-essentials": "^7.5.0",
+ "@storybook/addon-links": "^7.5.0",
+ "@storybook/addon-mdx-gfm": "^7.5.0",
+ "@storybook/addon-storysource": "^7.5.0",
+ "@storybook/react": "^7.5.0",
+ "@storybook/react-vite": "^7.5.0",
+ "@types/react": "17.0.69",
+ "@vitejs/plugin-react": "^4.2.1",
+ "cross-env": "^7.0.3",
+ "eslint-plugin-storybook": "^0.6.15",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
+ "storybook": "^7.5.0",
+ "vite": "^5.2.0",
+ "vite-plugin-node-polyfills": "^0.17.0"
+ },
+ "// COMMENT devDependencies": {
+ "vite-plugin-node-polyfills": "^0.17.0: in after upgrading to vite 5, I also upgraded this to latest = 0.21. In found: works w/o issues. Here I have this non-blocking error: https://github.com/davidmyersdev/vite-plugin-node-polyfills/issues/81. Hence I downgrade to 0.17"
+ },
+ "dependencies": {
+ "antd": "^4.15.1",
+ "typedoc": "^0.24.8"
+ },
+ "peerDependencies": {
+ "react": "^16.4.1 || ^17.0.0",
+ "react-dom": "^16.4.1 || ^17.0.0"
+ },
+ "resolutions": {
+ "// @types/react": "Needed, because a lot of packages import this w/ *. And yarn resolves + hoists this as the latest available version.",
+ "// @types/react 2": "UPDATE: @see in foundation",
+ "@types/react": "17.0.69",
+ "// jackspeak": "Appeared after migrating storybook to v7.5.0. The program detected it automatically and proposed this link: https://github.com/storybookjs/storybook/issues/22431#issuecomment-1630086092",
+ "jackspeak": "2.1.1"
+ }
+}
diff --git a/demo-app/public/README.md b/demo-app/public/README.md
new file mode 100644
index 00000000..44fa6d6b
--- /dev/null
+++ b/demo-app/public/README.md
@@ -0,0 +1,4 @@
+1/ By default, vite projects have such a `public` dir, containing the entry point/html file.
+2/ Here, we removed this dir, because the entry point is under `src`.
+3/ To use the beta of TAD + Markdown reports, we recreated this dir, because TAD has `public` hardcoded.
+4/ But in the future, maybe 2 is a better approach. I.e. to have all under `src`. And an adaptation will be made for 3/.
\ No newline at end of file
diff --git a/demo-app/public/contextMenu.md b/demo-app/public/contextMenu.md
new file mode 100644
index 00000000..a26f2d1c
--- /dev/null
+++ b/demo-app/public/contextMenu.md
@@ -0,0 +1,82 @@
+
+
+
Fig. 1
+
Fig. 2
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+On right click, a context menu appears. Each line of the context menu is an **action**. An action has a **label**, **icon**, and a **run** callback (called when the user clicks on it).
+
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+If label and icon is not enough, a custom renderer can be provided. It can be a normal renderer w/ some additional customizations (e.g. color). Or it can be any arbitrary component.
+
+
+
+
+
+
+
+
Fig. 3
+
Fig. 4
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+Before the actions are displayed, they are 'asked' is they want to be visible or not. They usually decide this based on the **current selection**. E.g. here, the *Edit* action is not shown, because it needs exactly one element is selected (and 2 are currently selected).
+
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+The menu can also be opened from the **hamburger button**. Particular useful on mobile.
+
+ Based on the selection, an action can perform any logic, not only decide its visibility. E.g. here it changes its label, complaining that there is no current row. True: when the context menu is opened from the hamburger button, we have selection, but we don't have mouse info (x, y, current row).
+
+
+
+
+
diff --git a/demo-app/public/docDescriptors/contextMenu.json b/demo-app/public/docDescriptors/contextMenu.json
new file mode 100644
index 00000000..0db624b6
--- /dev/null
+++ b/demo-app/public/docDescriptors/contextMenu.json
@@ -0,0 +1,21 @@
+{
+ "cells": [
+ {
+ "image": "ContextMenuTestsAreDemo.whenRightClickOnASegment/ContextMenu_popup.png",
+ "text": "On right click, a context menu appears. Each line of the context menu is an **action**. An action has a **label**, **icon**, and a **run** callback (called when the user clicks on it)."
+ },
+ {
+ "image": "ContextMenuTestsAreDemo.whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2.png",
+ "text": "If label and icon is not enough, a custom renderer can be provided. It can be a normal renderer w/ some additional customizations (e.g. color). Or it can be any arbitrary component.",
+ "newLineAfter": true
+ },
+ {
+ "image": "ContextMenuTestsAreDemo.whenCTRLRightClickOnAnotherSegment/ContextMenu_popup.png",
+ "text": "Before the actions are displayed, they are 'asked' is they want to be visible or not. They usually decide this based on the **current selection**. E.g. here, the *Edit* action is not shown, because it needs exactly one element is selected (and 2 are currently selected)."
+ },
+ {
+ "image": "ContextMenuTestsAreDemo.whenClickTheHamburgerButton/ContextMenu_popup.png",
+ "text": "The menu can also be opened from the **hamburger button**. Particular useful on mobile.\n\n Based on the selection, an action can perform any logic, not only decide its visibility. E.g. here it changes its label, complaining that there is no current row. True: when the context menu is opened from the hamburger button, we have selection, but we don't have mouse info (x, y, current row)."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/demo-app/public/docDescriptors/dragToCreate.json b/demo-app/public/docDescriptors/dragToCreate.json
new file mode 100644
index 00000000..afb409f9
--- /dev/null
+++ b/demo-app/public/docDescriptors/dragToCreate.json
@@ -0,0 +1,21 @@
+{
+ "cells": [
+ {
+ "image": "DragToCreateTestsAreDemo.whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0.png",
+ "text": "Open the context menu (right click or click on the hamburger button from the top/left corner. Click ..."
+ },
+ {
+ "image": "DragToCreateTestsAreDemo.whenClickAddMenuEntry/Timeline_dragToCreatePopup.png",
+ "text": "... and you enter in the 'drag to create' mode. The popup hides itself quickly, to make sure it doesn't bother the user. This mode is cancelable via button or simple click (i.e. not click and drag).",
+ "newLineAfter": true
+ },
+ {
+ "image": "DragToCreateTestsAreDemo.givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2.png",
+ "text": "Click and drag on a row. A green rectangle appears as you drag. A right drag cancels the operation and exits the 'drag to create' mode.\n\n **TODO!!!** avem acest comportament de anulare a dragului?"
+ },
+ {
+ "image": "DragToCreateTestsAreDemo.givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11.png",
+ "text": "When you do `mouse up` (to `drop`), your handler will be called, receiving useful args (e.g. row, start/end, etc.). It can e.g. create a new segment.\n\n **TODO!!!** poza nu e buna. Ar fi trebuit sa captureze segmentul nou creat"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/demo-app/public/docDescriptors/index.json b/demo-app/public/docDescriptors/index.json
new file mode 100644
index 00000000..a8a98e06
--- /dev/null
+++ b/demo-app/public/docDescriptors/index.json
@@ -0,0 +1 @@
+["dragToCreate.json", "contextMenu.json"]
\ No newline at end of file
diff --git a/demo-app/public/dragToCreate.md b/demo-app/public/dragToCreate.md
new file mode 100644
index 00000000..a44e82c0
--- /dev/null
+++ b/demo-app/public/dragToCreate.md
@@ -0,0 +1,84 @@
+
+
+
Fig. 1
+
Fig. 2
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+Open the context menu (right click or click on the hamburger button from the top/left corner. Click ...
+
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+... and you enter in the 'drag to create' mode. The popup hides itself quickly, to make sure it doesn't bother the user. This mode is cancelable via button or simple click (i.e. not click and drag).
+
+
+
+
+
+
+
+
Fig. 3
+
Fig. 4
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+Click and drag on a row. A green rectangle appears as you drag. A right drag cancels the operation and exits the 'drag to create' mode.
+
+ **TODO!!!** avem acest comportament de anulare a dragului?
+
+
+
+
+
+Click to expand full image
+
+
+
+
+
+
+
+
+
+When you do `mouse up` (to `drop`), your handler will be called, receiving useful args (e.g. row, start/end, etc.). It can e.g. create a new segment.
+
+ **TODO!!!** poza nu e buna. Ar fi trebuit sa captureze segmentul nou creat
+
+
+
+
+
diff --git a/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0.png b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0.png
new file mode 100644
index 00000000..c73380fa
Binary files /dev/null and b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0.png differ
diff --git a/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0_small.png b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0_small.png
new file mode 100644
index 00000000..4ce46b02
Binary files /dev/null and b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0_small.png differ
diff --git a/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/recordedTest.json b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/recordedTest.json
new file mode 100644
index 00000000..30296ad4
--- /dev/null
+++ b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"HighlightedInterval_interval_0","sourceFile":"BackgroundLayersTestsAreDemo.tsx","sourceLine":17}],"sourceFiles":{"BackgroundLayersTestsAreDemo.tsx":"import { Only, Scenario, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { Main } from \"../stories/backgroundLayer/BackgroundLayer.stories\";\nimport { dateAndHourOfCurrentMonth } from \"../stories/sampleData\";\nimport {PARENT_ELEMENT, Timeline, getPixelAtTime, getPixelsFromDuration, highlightedIntervalTestIds} from \"@famiprog-foundation/react-gantt\";\nimport moment from \"moment\";\n\nexport class BackgroundLayersTestsAreDemo {\n async before() {\n render();\n }\n \n @Scenario(\"The highlighted intervals are correctly displayed\")\n async highlightedIntervalsAreDisplayed() {\n const ganttLeftOffset = PARENT_ELEMENT(tad.getObjectViaCheat(Timeline).props.componentId).getBoundingClientRect().left;\n\n var interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_0\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(4)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(4), dateAndHourOfCurrentMonth(6)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_1\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(11)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(11), dateAndHourOfCurrentMonth(13)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_2\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(18)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(18), dateAndHourOfCurrentMonth(20)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_3\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(25)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(25), dateAndHourOfCurrentMonth(27)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_4\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(1)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(1), dateAndHourOfCurrentMonth(2)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_5\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(15)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(15), dateAndHourOfCurrentMonth(18)));\n\n interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + \"_6\");\n await tad.assertWaitable.exists(interval);\n await tad.assertWaitable.equal(Math.round(interval.getBoundingClientRect().x - ganttLeftOffset), this.getPixelsAtDate(dateAndHourOfCurrentMonth(20, 19)));\n await tad.assertWaitable.equal(interval.getBoundingClientRect().width, this.getPixelsFromDuration(dateAndHourOfCurrentMonth(20, 19), dateAndHourOfCurrentMonth(21, 10)));\n }\n\n getPixelsAtDate(date) {\n const timeline = tad.getObjectViaCheat(Timeline);\n return Math.round(getPixelAtTime(moment(date), timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined)));\n }\n getPixelsFromDuration(start, end) {\n const timeline = tad.getObjectViaCheat(Timeline);\n return Math.round(getPixelsFromDuration(moment(end).diff(start, \"milliseconds\"), timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap()));\n\n }\n}"},"duration":36,"error":"Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)\n\t at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/report.md b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/report.md
new file mode 100644
index 00000000..45464350
--- /dev/null
+++ b/demo-app/public/recordedTests/BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/report.md
@@ -0,0 +1,119 @@
+
+# BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)
+ at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)
+```
+
+---
+
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## BackgroundLayersTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { Main } from "../stories/backgroundLayer/BackgroundLayer.stories";
+/* 3*/import { dateAndHourOfCurrentMonth } from "../stories/sampleData";
+/* 4*/import {PARENT_ELEMENT, Timeline, getPixelAtTime, getPixelsFromDuration, highlightedIntervalTestIds} from "@famiprog-foundation/react-gantt";
+/* 5*/import moment from "moment";
+/* 6*/
+/* 7*/export class BackgroundLayersTestsAreDemo {
+```
+
+
+
+```tsx
+/* 8*/ async before() {
+/* 9*/ render();
+/*10*/ }
+/*11*/
+/*12*/ @Scenario("The highlighted intervals are correctly displayed")
+/*13*/ async highlightedIntervalsAreDisplayed() {
+/*14*/ const ganttLeftOffset = PARENT_ELEMENT(tad.getObjectViaCheat(Timeline).props.componentId).getBoundingClientRect().left;
+/*15*/
+/*16*/ var interval = tad.screenCapturing.getByTestId(highlightedIntervalTestIds.interval + "_0");
+/*17*/ await tad.assertWaitable.exists(interval);
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed/HighlightedInterval_interval_0.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*122*/ }
+/*123*/
+/*124*/ @Scenario("WHEN I click the hamburger button, THEN the context menu is shown besides that button")
+/*125*/ async whenClickTheHamburgerButton() {
+/*126*/ // GIVEN I select one segment
+/*127*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/*128*/
+/*129*/ // WHEN
+/*130*/ const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);
+/*131*/ tad.cc("Click on the menu button");
+/*132*/ await tad.userEventWaitable.click(menuButton);
+/*133*/
+/*134*/ // THEN the context menu is opened and positioned near the center of the hamburger button");
+/*135*/ tad.demoForEndUserHide();
+/*136*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*137*/ await tad.assertWaitable.exists(popup);
+/*138*/ const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };
+/*139*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);
+/*140*/ tad.demoForEndUserShow();
+/*141*/
+/*142*/ // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions
+/*143*/ tad.cc("The context menu contains an 'Add task not possible' action");
+/*144*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskNotPossibleAction);
+/*145*/ tad.cc("And an 'Edit' action");
+/*146*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, editActionLabel);
+/*147*/ tad.cc("And a 'Delete' action");
+/*148*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_2").textContent, deleteActionLabel);
+/*149*/
+/*150*/ // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close
+/*151*/ // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial
+/*152*/ tad.demoForEndUserHide();
+/*153*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1"));
+/*154*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/*155*/ tad.demoForEndUserShow();
+/*156*/ }
+/*157*/
+/*158*/ async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {
+/*159*/ const popupEndX = Math.round(popupX + popupWidth);
+/*160*/ const popupEndY = Math.round(popupY + popupHeight);
+/*161*/ popupX = Math.floor(popupX);
+/*162*/ popupY = Math.round(popupY);
+/*163*/
+/*164*/ // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position.
+/*165*/ // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen
+/*166*/ // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)
+/*167*/ await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));
+/*168*/ // semantic ui popup is displayed 10 px below or 10 px above the mouse position
+/*169*/ await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));
+/*170*/ }
+/*171*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/recordedTest.json b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/recordedTest.json
new file mode 100644
index 00000000..6eac770b
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[],"sourceFiles":{},"duration":2,"error":"Error: Unable to find an element by: [data-testid=\"ContextMenu_popup\"]\n\t at Object.getElementError [return new Error(message || \"n/a\"); // I observed that message is null (at least) for the case where multiple elements are found, and only one was expected] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/reactTestingLibraryCustomized.tsx:24:12)\n\t [throw getConfig().getElementError(getMissingError(container, ...args), container);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1149:25)\n\t [const els = allQuery(container, ...args);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1128:17)\n\t [const element = query(container, ...args);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1171:19)\n\t at Object.getByTestId [const result: any = oldFunction.apply(null, args);] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/TestsAreDemoFunctions.tsx:203:49)\n\t at ContextMenuTestsAreDemo.whenClickAnAction [const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);] (http://localhost:3000ContextMenuTestsAreDemo.tsx:44:43)\n\t at callFn [var result = fn.call(ctx);] (http://localhost:3000/node_modules/mocha/lib/runnable.js:366:21)\n\t at Runnable.run [callFn(this.fn);] (http://localhost:3000/node_modules/mocha/lib/runnable.js:354:5)\n\t at Runner.runTest [test.run(fn);] (http://localhost:3000/node_modules/mocha/lib/runner.js:666:10)\n\t [self.runTest(function (err) {] (http://localhost:3000/node_modules/mocha/lib/runner.js:789:12)\n\t at next [return fn();] (http://localhost:3000/node_modules/mocha/lib/runner.js:581:14)\n\t [next(suites.pop());] (http://localhost:3000/node_modules/mocha/lib/runner.js:591:7)\n\t at next [return fn();] (http://localhost:3000/node_modules/mocha/lib/runner.js:474:14)\n\t [next(0);] (http://localhost:3000/node_modules/mocha/lib/runner.js:559:5)\n\t at timeslice [immediateQueue.shift()();] (http://localhost:3000/node_modules/mocha/browser-entry.js:100:28)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/report.md b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/report.md
new file mode 100644
index 00000000..53588fa9
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickAnAction/report.md
@@ -0,0 +1,32 @@
+
+# ContextMenuTestsAreDemo/whenClickAnAction()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+Error: Unable to find an element by: [data-testid="ContextMenu_popup"]
+ at Object.getElementError [return new Error(message || "n/a"); // I observed that message is null (at least) for the case where multiple elements are found, and only one was expected] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/reactTestingLibraryCustomized.tsx:24:12)
+ [throw getConfig().getElementError(getMissingError(container, ...args), container);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1149:25)
+ [const els = allQuery(container, ...args);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1128:17)
+ [const element = query(container, ...args);] (http://localhost:3000/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1171:19)
+ at Object.getByTestId [const result: any = oldFunction.apply(null, args);] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/TestsAreDemoFunctions.tsx:203:49)
+ at ContextMenuTestsAreDemo.whenClickAnAction [const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);] (http://localhost:3000ContextMenuTestsAreDemo.tsx:44:43)
+ at callFn [var result = fn.call(ctx);] (http://localhost:3000/node_modules/mocha/lib/runnable.js:366:21)
+ at Runnable.run [callFn(this.fn);] (http://localhost:3000/node_modules/mocha/lib/runnable.js:354:5)
+ at Runner.runTest [test.run(fn);] (http://localhost:3000/node_modules/mocha/lib/runner.js:666:10)
+ [self.runTest(function (err) {] (http://localhost:3000/node_modules/mocha/lib/runner.js:789:12)
+ at next [return fn();] (http://localhost:3000/node_modules/mocha/lib/runner.js:581:14)
+ [next(suites.pop());] (http://localhost:3000/node_modules/mocha/lib/runner.js:591:7)
+ at next [return fn();] (http://localhost:3000/node_modules/mocha/lib/runner.js:474:14)
+ [next(0);] (http://localhost:3000/node_modules/mocha/lib/runner.js:559:5)
+ at timeslice [immediateQueue.shift()();] (http://localhost:3000/node_modules/mocha/browser-entry.js:100:28)
+```
+
+---
+
+
+There are 0 screenshots. [Go to first](#screenshot-1)
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup.png
new file mode 100644
index 00000000..268bcbcf
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0.png
new file mode 100644
index 00000000..b9fcfaa8
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png
new file mode 100644
index 00000000..db85215c
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1.png
new file mode 100644
index 00000000..8e958ec7
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1.png
new file mode 100644
index 00000000..374de5b6
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1_small.png
new file mode 100644
index 00000000..f48c2f49
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_small.png
new file mode 100644
index 00000000..f48c2f49
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2.png
new file mode 100644
index 00000000..30491058
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2_small.png
new file mode 100644
index 00000000..c824c03b
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_2_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1.png
new file mode 100644
index 00000000..a36aa93c
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1_small.png
new file mode 100644
index 00000000..2eb39816
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2.png
new file mode 100644
index 00000000..b388b179
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2_small.png
new file mode 100644
index 00000000..2eb39816
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3.png
new file mode 100644
index 00000000..b9ff0d5d
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3_small.png
new file mode 100644
index 00000000..bbae136f
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_small.png
new file mode 100644
index 00000000..2eb39816
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png
new file mode 100644
index 00000000..dac87edf
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png
new file mode 100644
index 00000000..2cddbabb
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton.png
new file mode 100644
index 00000000..b6e98c85
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton_small.png
new file mode 100644
index 00000000..b79b0e7a
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/recordedTest.json b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/recordedTest.json
new file mode 100644
index 00000000..64d0a9b8
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":127},{"screenshot":"Timeline_menuButton","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":132},{"screenshot":"ContextMenu_popup","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":137},{"screenshot":"ContextMenu_popup_REP1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":167},{"screenshot":"ContextMenu_popup_REP2","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":169},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_0","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":144},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":146},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_2","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":148},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_1_REP1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":153},{"screenshot":"ContextMenu_popup_REP3","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":154}],"sourceFiles":{"ContextMenuTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someHumanResources, someTasks } from \"../stories/sampleData\";\nimport Timeline, { PARENT_ELEMENT, timelineTestids as testids } from \"../../../src/timeline\";\nimport { getPixelAtTime, getTimeAtPixel } from \"../../../src/utils/timeUtils\";\nimport { rightClick } from \"./testUtils\";\n\nconst CLICK_X =30;\nexport class ContextMenuTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN I right click on a row, THEN a context menu with one action opens\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnARow() {\n // WHEN right click on a row\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };\n await tad.showSpotlight({ message: \"I right click on a row\", focusOnLastElementCaptured: true });\n rightClick(firstRow, clickPosition);\n\n // THEN CM is opened at the clicked position\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });\n tad.demoForEndUserShow();\n\n // AND it has an 'Add task' actions\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\");\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, addTaskActionIcon);\n }\n\n @Scenario(\"WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenClickAnAction() {\n // WHEN I click on \"Add\"\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n // THEN a new task is added\n let newSegment = tad.screenCapturing.getByTestId(testids.item + \"_\" + someTasks.length);\n await tad.assertWaitable.exists(newSegment);\n\n tad.demoForEndUserHide();\n // AND the CM is closed\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));\n\n // AND the new task is position correctly on x axes\n // Gantt works with times \"snapped to grid\" so the position for the new task should be snapped to grid \n const timeline = tad.getObjectViaCheat(Timeline);\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;\n const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;\n const clickedXInGantt = clickedX - ganttLeftOffset;\n const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());\n const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))\n + ganttLeftOffset; \n await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));\n \n // AND is correctly added to the clicked row\n await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN I right click on a segment, THEN a context menu with 3 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnASegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_0\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n\n // WHEN right click on a segment\n await tad.showSpotlight({ message: \"I right click on a segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n \n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add', 'Edit' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[0].title);\n \n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n \n tad.cc(\"And a 'Delete' action\");\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\");\n await tad.assertWaitable.equal(menuEntry.textContent, deleteActionLabel);\n tad.cc(\"With a custom red renderer\");\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIcon);\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIconColor);\n }\n\n @Scenario(\"WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenCTRLRightClickOnAnotherSegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_3\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n await tad.showSpotlight({ message: \"WHEN I CTRL + right click another segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n\n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[1].title);\n \n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, deleteActionLabel);\n }\n\n @Scenario(\"WHEN I click the hamburger button, THEN the context menu is shown besides that button\")\n async whenClickTheHamburgerButton() {\n // GIVEN I select one segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n\n // WHEN\n const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(menuButton);\n\n // THEN the context menu is opened and positioned near the center of the hamburger button\");\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);\n tad.demoForEndUserShow();\n\n // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions\n tad.cc(\"The context menu contains an 'Add task not possible' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskNotPossibleAction);\n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\").textContent, deleteActionLabel);\n\n // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close \n // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial \n tad.demoForEndUserHide();\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\"));\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n tad.demoForEndUserShow();\n }\n\n async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {\n const popupEndX = Math.round(popupX + popupWidth);\n const popupEndY = Math.round(popupY + popupHeight);\n popupX = Math.floor(popupX);\n popupY = Math.round(popupY);\n\n // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position. \n // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen\n // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)\n await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));\n // semantic ui popup is displayed 10 px below or 10 px above the mouse position\n await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));\n }\n}"},"duration":1387}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/report.md b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/report.md
new file mode 100644
index 00000000..bdf89a6d
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenClickTheHamburgerButton/report.md
@@ -0,0 +1,435 @@
+
+# ContextMenuTestsAreDemo/whenClickTheHamburgerButton()
+
+### undefined
+
+---
+
+There are 10 screenshots. [Go to first](#screenshot-1)
+
+## ContextMenuTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someHumanResources, someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { PARENT_ELEMENT, timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { getPixelAtTime, getTimeAtPixel } from "../../../src/utils/timeUtils";
+/* 7*/import { rightClick } from "./testUtils";
+/* 8*/
+/* 9*/const CLICK_X =30;
+/* 10*/export class ContextMenuTestsAreDemo {
+/* 11*/
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN I right click on a row, THEN a context menu with one action opens")
+/* 17*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 18*/ async whenRightClickOnARow() {
+/* 19*/ // WHEN right click on a row
+/* 20*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 21*/ const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };
+/* 22*/ await tad.showSpotlight({ message: "I right click on a row", focusOnLastElementCaptured: true });
+/* 23*/ rightClick(firstRow, clickPosition);
+/* 24*/
+/* 25*/ // THEN CM is opened at the clicked position
+/* 26*/ tad.demoForEndUserHide();
+/* 27*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 28*/ await tad.assertWaitable.exists(popup);
+/* 29*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });
+/* 30*/ tad.demoForEndUserShow();
+/* 31*/
+/* 32*/ // AND it has an 'Add task' actions
+/* 33*/ let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0");
+/* 34*/ tad.cc("The context menu contains an 'Add' action");
+/* 35*/ await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);
+/* 36*/ tad.demoForEndUserHideNext();
+/* 37*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, addTaskActionIcon);
+/* 38*/ }
+/* 39*/
+/* 40*/ @Scenario("WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)")
+/* 41*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 42*/ async whenClickAnAction() {
+/* 43*/ // WHEN I click on "Add"
+/* 44*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 45*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 46*/
+/* 47*/ // THEN a new task is added
+/* 48*/ let newSegment = tad.screenCapturing.getByTestId(testids.item + "_" + someTasks.length);
+/* 49*/ await tad.assertWaitable.exists(newSegment);
+/* 50*/
+/* 51*/ tad.demoForEndUserHide();
+/* 52*/ // AND the CM is closed
+/* 53*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));
+/* 54*/
+/* 55*/ // AND the new task is position correctly on x axes
+/* 56*/ // Gantt works with times "snapped to grid" so the position for the new task should be snapped to grid
+/* 57*/ const timeline = tad.getObjectViaCheat(Timeline);
+/* 58*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 59*/ const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;
+/* 60*/ const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;
+/* 61*/ const clickedXInGantt = clickedX - ganttLeftOffset;
+/* 62*/ const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());
+/* 63*/ const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))
+/* 64*/ + ganttLeftOffset;
+/* 65*/ await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));
+/* 66*/
+/* 67*/ // AND is correctly added to the clicked row
+/* 68*/ await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);
+/* 69*/ tad.demoForEndUserShow();
+/* 70*/ }
+/* 71*/
+/* 72*/ @Scenario("WHEN I right click on a segment, THEN a context menu with 3 actions is shown")
+/* 73*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 74*/ async whenRightClickOnASegment() {
+/* 75*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_0");
+/* 76*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/* 77*/
+/* 78*/ // WHEN right click on a segment
+/* 79*/ await tad.showSpotlight({ message: "I right click on a segment", focusOnLastElementCaptured: true });
+/* 80*/ rightClick(segment, { clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });
+/* 81*/
+/* 82*/ // THEN the CM opens
+/* 83*/ tad.demoForEndUserHideNext();
+/* 84*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 85*/ await tad.assertWaitable.exists(popup);
+/* 86*/
+/* 87*/ // AND it has: 'Add', 'Edit' and 'Delete' actions
+/* 88*/ tad.cc("The context menu contains an 'Add' action");
+/* 89*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskActionLabel + someHumanResources[0].title);
+/* 90*/
+/* 91*/ tad.cc("And an 'Edit' action");
+/* 92*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, editActionLabel);
+/* 93*/
+/* 94*/ tad.cc("And a 'Delete' action");
+/* 95*/ let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_2");
+/* 96*/ await tad.assertWaitable.equal(menuEntry.textContent, deleteActionLabel);
+/* 97*/ tad.cc("With a custom red renderer");
+/* 98*/ tad.demoForEndUserHideNext();
+/* 99*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, deleteActionIcon);
+/*100*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, deleteActionIconColor);
+/*101*/ }
+/*102*/
+/*103*/ @Scenario("WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown")
+/*104*/ @ScenarioOptions({ linkWithNextScenario: true })
+/*105*/ async whenCTRLRightClickOnAnotherSegment() {
+/*106*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_3");
+/*107*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/*108*/ await tad.showSpotlight({ message: "WHEN I CTRL + right click another segment", focusOnLastElementCaptured: true });
+/*109*/ rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });
+/*110*/
+/*111*/ // THEN the CM opens
+/*112*/ tad.demoForEndUserHideNext();
+/*113*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*114*/ await tad.assertWaitable.exists(popup);
+/*115*/
+/*116*/ // AND it has: 'Add' and 'Delete' actions
+/*117*/ tad.cc("The context menu contains an 'Add' action");
+```
+
+
+
+```tsx
+/*118*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskActionLabel + someHumanResources[1].title);
+/*119*/
+/*120*/ tad.cc("And a 'Delete' action");
+/*121*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, deleteActionLabel);
+/*122*/ }
+/*123*/
+/*124*/ @Scenario("WHEN I click the hamburger button, THEN the context menu is shown besides that button")
+/*125*/ async whenClickTheHamburgerButton() {
+/*126*/ // GIVEN I select one segment
+/*127*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png
+
+
+
+
+
+```tsx
+/*128*/
+/*129*/ // WHEN
+/*130*/ const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);
+/*131*/ tad.cc("Click on the menu button");
+/*132*/ await tad.userEventWaitable.click(menuButton);
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/Timeline_menuButton.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*133*/
+/*134*/ // THEN the context menu is opened and positioned near the center of the hamburger button");
+/*135*/ tad.demoForEndUserHide();
+/*136*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*137*/ await tad.assertWaitable.exists(popup);
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*138*/ const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };
+/*139*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);
+/*140*/ tad.demoForEndUserShow();
+/*141*/
+/*142*/ // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions
+/*143*/ tad.cc("The context menu contains an 'Add task not possible' action");
+/*144*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskNotPossibleAction);
+```
+
+
+
+
+### Screenshot 6
+
+[Go to previous](#screenshot-5) | [Go to next](#screenshot-7)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_0.png
+
+
+
+
+
+```tsx
+/*149*/
+/*150*/ // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close
+/*151*/ // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial
+/*152*/ tad.demoForEndUserHide();
+/*153*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1"));
+```
+
+
+
+
+### Screenshot 9
+
+[Go to previous](#screenshot-8) | [Go to next](#screenshot-10)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_ContextMenu_menuItem_1_REP1.png
+
+
+
+
+
+### Screenshot 10
+
+[Go to previous](#screenshot-9)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP3.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*155*/ tad.demoForEndUserShow();
+/*156*/ }
+/*157*/
+/*158*/ async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {
+/*159*/ const popupEndX = Math.round(popupX + popupWidth);
+/*160*/ const popupEndY = Math.round(popupY + popupHeight);
+/*161*/ popupX = Math.floor(popupX);
+/*162*/ popupY = Math.round(popupY);
+/*163*/
+/*164*/ // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position.
+/*165*/ // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen
+/*166*/ // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)
+/*167*/ await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3) | [Go to next](#screenshot-5)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP1.png
+
+
+
+
+
+### Screenshot 5
+
+[Go to previous](#screenshot-4) | [Go to next](#screenshot-6)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenClickTheHamburgerButton/ContextMenu_popup_REP2.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*170*/ }
+/*171*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0.png
new file mode 100644
index 00000000..6a906ab9
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0_small.png
new file mode 100644
index 00000000..6d1389fd
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/recordedTest.json b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/recordedTest.json
new file mode 100644
index 00000000..64ff45a0
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_0","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":22}],"sourceFiles":{"ContextMenuTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someHumanResources, someTasks } from \"../stories/sampleData\";\nimport Timeline, { PARENT_ELEMENT, timelineTestids as testids } from \"../../../src/timeline\";\nimport { getPixelAtTime, getTimeAtPixel } from \"../../../src/utils/timeUtils\";\nimport { rightClick } from \"./testUtils\";\n\nconst CLICK_X =30;\nexport class ContextMenuTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN I right click on a row, THEN a context menu with one action opens\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnARow() {\n // WHEN right click on a row\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };\n await tad.showSpotlight({ message: \"I right click on a row\", focusOnLastElementCaptured: true });\n rightClick(firstRow, clickPosition);\n\n // THEN CM is opened at the clicked position\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });\n tad.demoForEndUserShow();\n\n // AND it has an 'Add task' actions\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\");\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, addTaskActionIcon);\n }\n\n @Scenario(\"WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenClickAnAction() {\n // WHEN I click on \"Add\"\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n // THEN a new task is added\n let newSegment = tad.screenCapturing.getByTestId(testids.item + \"_\" + someTasks.length);\n await tad.assertWaitable.exists(newSegment);\n\n tad.demoForEndUserHide();\n // AND the CM is closed\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));\n\n // AND the new task is position correctly on x axes\n // Gantt works with times \"snapped to grid\" so the position for the new task should be snapped to grid \n const timeline = tad.getObjectViaCheat(Timeline);\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;\n const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;\n const clickedXInGantt = clickedX - ganttLeftOffset;\n const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());\n const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))\n + ganttLeftOffset; \n await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));\n \n // AND is correctly added to the clicked row\n await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN I right click on a segment, THEN a context menu with 3 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnASegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_0\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n\n // WHEN right click on a segment\n await tad.showSpotlight({ message: \"I right click on a segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n \n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add', 'Edit' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[0].title);\n \n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n \n tad.cc(\"And a 'Delete' action\");\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\");\n await tad.assertWaitable.equal(menuEntry.textContent, deleteActionLabel);\n tad.cc(\"With a custom red renderer\");\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIcon);\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIconColor);\n }\n\n @Scenario(\"WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenCTRLRightClickOnAnotherSegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_3\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n await tad.showSpotlight({ message: \"WHEN I CTRL + right click another segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n\n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[1].title);\n \n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, deleteActionLabel);\n }\n\n @Scenario(\"WHEN I click the hamburger button, THEN the context menu is shown besides that button\")\n async whenClickTheHamburgerButton() {\n // GIVEN I select one segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n\n // WHEN\n const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(menuButton);\n\n // THEN the context menu is opened and positioned near the center of the hamburger button\");\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);\n tad.demoForEndUserShow();\n\n // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions\n tad.cc(\"The context menu contains an 'Add task not possible' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskNotPossibleAction);\n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\").textContent, deleteActionLabel);\n\n // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close \n // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial \n tad.demoForEndUserHide();\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\"));\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n tad.demoForEndUserShow();\n }\n\n async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {\n const popupEndX = Math.round(popupX + popupWidth);\n const popupEndY = Math.round(popupY + popupHeight);\n popupX = Math.floor(popupX);\n popupY = Math.round(popupY);\n\n // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position. \n // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen\n // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)\n await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));\n // semantic ui popup is displayed 10 px below or 10 px above the mouse position\n await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));\n }\n}"},"duration":35,"error":"Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)\n\t at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/report.md b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/report.md
new file mode 100644
index 00000000..755bf50f
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnARow/report.md
@@ -0,0 +1,229 @@
+
+# ContextMenuTestsAreDemo/whenRightClickOnARow()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)
+ at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)
+```
+
+---
+
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## ContextMenuTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someHumanResources, someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { PARENT_ELEMENT, timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { getPixelAtTime, getTimeAtPixel } from "../../../src/utils/timeUtils";
+/* 7*/import { rightClick } from "./testUtils";
+/* 8*/
+/* 9*/const CLICK_X =30;
+/* 10*/export class ContextMenuTestsAreDemo {
+/* 11*/
+/* 12*/ async before() {
+```
+
+
+
+```tsx
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN I right click on a row, THEN a context menu with one action opens")
+/* 17*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 18*/ async whenRightClickOnARow() {
+/* 19*/ // WHEN right click on a row
+/* 20*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 21*/ const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };
+/* 22*/ await tad.showSpotlight({ message: "I right click on a row", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenRightClickOnARow/Timeline_ganttBody_Timeline_row_0.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 23*/ rightClick(firstRow, clickPosition);
+/* 24*/
+/* 25*/ // THEN CM is opened at the clicked position
+/* 26*/ tad.demoForEndUserHide();
+/* 27*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 28*/ await tad.assertWaitable.exists(popup);
+/* 29*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });
+/* 30*/ tad.demoForEndUserShow();
+/* 31*/
+/* 32*/ // AND it has an 'Add task' actions
+/* 33*/ let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0");
+/* 34*/ tad.cc("The context menu contains an 'Add' action");
+/* 35*/ await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);
+/* 36*/ tad.demoForEndUserHideNext();
+/* 37*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, addTaskActionIcon);
+/* 38*/ }
+/* 39*/
+/* 40*/ @Scenario("WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)")
+/* 41*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 42*/ async whenClickAnAction() {
+/* 43*/ // WHEN I click on "Add"
+/* 44*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 45*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 46*/
+/* 47*/ // THEN a new task is added
+/* 48*/ let newSegment = tad.screenCapturing.getByTestId(testids.item + "_" + someTasks.length);
+/* 49*/ await tad.assertWaitable.exists(newSegment);
+/* 50*/
+/* 51*/ tad.demoForEndUserHide();
+/* 52*/ // AND the CM is closed
+/* 53*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));
+/* 54*/
+/* 55*/ // AND the new task is position correctly on x axes
+/* 56*/ // Gantt works with times "snapped to grid" so the position for the new task should be snapped to grid
+/* 57*/ const timeline = tad.getObjectViaCheat(Timeline);
+/* 58*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 59*/ const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;
+/* 60*/ const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;
+/* 61*/ const clickedXInGantt = clickedX - ganttLeftOffset;
+/* 62*/ const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());
+/* 63*/ const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))
+/* 64*/ + ganttLeftOffset;
+/* 65*/ await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));
+/* 66*/
+/* 67*/ // AND is correctly added to the clicked row
+/* 68*/ await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);
+/* 69*/ tad.demoForEndUserShow();
+/* 70*/ }
+/* 71*/
+/* 72*/ @Scenario("WHEN I right click on a segment, THEN a context menu with 3 actions is shown")
+/* 73*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 74*/ async whenRightClickOnASegment() {
+/* 75*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_0");
+/* 76*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/* 77*/
+/* 78*/ // WHEN right click on a segment
+/* 79*/ await tad.showSpotlight({ message: "I right click on a segment", focusOnLastElementCaptured: true });
+/* 80*/ rightClick(segment, { clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });
+/* 81*/
+/* 82*/ // THEN the CM opens
+/* 83*/ tad.demoForEndUserHideNext();
+/* 84*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 85*/ await tad.assertWaitable.exists(popup);
+/* 86*/
+/* 87*/ // AND it has: 'Add', 'Edit' and 'Delete' actions
+/* 88*/ tad.cc("The context menu contains an 'Add' action");
+/* 89*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskActionLabel + someHumanResources[0].title);
+/* 90*/
+/* 91*/ tad.cc("And an 'Edit' action");
+/* 92*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, editActionLabel);
+/* 93*/
+/* 94*/ tad.cc("And a 'Delete' action");
+/* 95*/ let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_2");
+/* 96*/ await tad.assertWaitable.equal(menuEntry.textContent, deleteActionLabel);
+/* 97*/ tad.cc("With a custom red renderer");
+/* 98*/ tad.demoForEndUserHideNext();
+/* 99*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, deleteActionIcon);
+/*100*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, deleteActionIconColor);
+/*101*/ }
+/*102*/
+/*103*/ @Scenario("WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown")
+/*104*/ @ScenarioOptions({ linkWithNextScenario: true })
+/*105*/ async whenCTRLRightClickOnAnotherSegment() {
+/*106*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_3");
+/*107*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/*108*/ await tad.showSpotlight({ message: "WHEN I CTRL + right click another segment", focusOnLastElementCaptured: true });
+/*109*/ rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });
+/*110*/
+/*111*/ // THEN the CM opens
+/*112*/ tad.demoForEndUserHideNext();
+/*113*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*114*/ await tad.assertWaitable.exists(popup);
+/*115*/
+/*116*/ // AND it has: 'Add' and 'Delete' actions
+/*117*/ tad.cc("The context menu contains an 'Add' action");
+/*118*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskActionLabel + someHumanResources[1].title);
+/*119*/
+/*120*/ tad.cc("And a 'Delete' action");
+/*121*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, deleteActionLabel);
+/*122*/ }
+/*123*/
+/*124*/ @Scenario("WHEN I click the hamburger button, THEN the context menu is shown besides that button")
+/*125*/ async whenClickTheHamburgerButton() {
+/*126*/ // GIVEN I select one segment
+/*127*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/*128*/
+/*129*/ // WHEN
+/*130*/ const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);
+/*131*/ tad.cc("Click on the menu button");
+/*132*/ await tad.userEventWaitable.click(menuButton);
+/*133*/
+/*134*/ // THEN the context menu is opened and positioned near the center of the hamburger button");
+/*135*/ tad.demoForEndUserHide();
+/*136*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*137*/ await tad.assertWaitable.exists(popup);
+/*138*/ const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };
+/*139*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);
+/*140*/ tad.demoForEndUserShow();
+/*141*/
+/*142*/ // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions
+/*143*/ tad.cc("The context menu contains an 'Add task not possible' action");
+/*144*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskNotPossibleAction);
+/*145*/ tad.cc("And an 'Edit' action");
+/*146*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, editActionLabel);
+/*147*/ tad.cc("And a 'Delete' action");
+/*148*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_2").textContent, deleteActionLabel);
+/*149*/
+/*150*/ // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close
+/*151*/ // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial
+/*152*/ tad.demoForEndUserHide();
+/*153*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1"));
+/*154*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/*155*/ tad.demoForEndUserShow();
+/*156*/ }
+/*157*/
+/*158*/ async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {
+/*159*/ const popupEndX = Math.round(popupX + popupWidth);
+/*160*/ const popupEndY = Math.round(popupY + popupHeight);
+/*161*/ popupX = Math.floor(popupX);
+/*162*/ popupY = Math.round(popupY);
+/*163*/
+/*164*/ // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position.
+/*165*/ // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen
+/*166*/ // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)
+/*167*/ await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));
+/*168*/ // semantic ui popup is displayed 10 px below or 10 px above the mouse position
+/*169*/ await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));
+/*170*/ }
+/*171*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup.png
new file mode 100644
index 00000000..bdd1a99f
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0.png
new file mode 100644
index 00000000..51918fbb
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0_small.png
new file mode 100644
index 00000000..b8ba2803
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_0_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1.png
new file mode 100644
index 00000000..4960905c
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1_small.png
new file mode 100644
index 00000000..f1587b08
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2.png
new file mode 100644
index 00000000..a6fcbbba
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1.png
new file mode 100644
index 00000000..35165119
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1_small.png
new file mode 100644
index 00000000..16bf44a8
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2.png
new file mode 100644
index 00000000..7ee53c11
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2_small.png
new file mode 100644
index 00000000..16bf44a8
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_small.png
new file mode 100644
index 00000000..16bf44a8
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_ContextMenu_menuItem_2_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_small.png
new file mode 100644
index 00000000..be6c655d
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/ContextMenu_popup_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png
new file mode 100644
index 00000000..ec47dad6
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png
new file mode 100644
index 00000000..775edcbf
Binary files /dev/null and b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png differ
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/recordedTest.json b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/recordedTest.json
new file mode 100644
index 00000000..1051b486
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_0","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":79},{"screenshot":"ContextMenu_popup","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":85},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_0","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":89},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":92},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_2","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":96},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_2_REP1","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":99},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_2_REP2","sourceFile":"ContextMenuTestsAreDemo.tsx","sourceLine":100}],"sourceFiles":{"ContextMenuTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someHumanResources, someTasks } from \"../stories/sampleData\";\nimport Timeline, { PARENT_ELEMENT, timelineTestids as testids } from \"../../../src/timeline\";\nimport { getPixelAtTime, getTimeAtPixel } from \"../../../src/utils/timeUtils\";\nimport { rightClick } from \"./testUtils\";\n\nconst CLICK_X =30;\nexport class ContextMenuTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN I right click on a row, THEN a context menu with one action opens\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnARow() {\n // WHEN right click on a row\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };\n await tad.showSpotlight({ message: \"I right click on a row\", focusOnLastElementCaptured: true });\n rightClick(firstRow, clickPosition);\n\n // THEN CM is opened at the clicked position\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });\n tad.demoForEndUserShow();\n\n // AND it has an 'Add task' actions\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\");\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, addTaskActionIcon);\n }\n\n @Scenario(\"WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenClickAnAction() {\n // WHEN I click on \"Add\"\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n // THEN a new task is added\n let newSegment = tad.screenCapturing.getByTestId(testids.item + \"_\" + someTasks.length);\n await tad.assertWaitable.exists(newSegment);\n\n tad.demoForEndUserHide();\n // AND the CM is closed\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));\n\n // AND the new task is position correctly on x axes\n // Gantt works with times \"snapped to grid\" so the position for the new task should be snapped to grid \n const timeline = tad.getObjectViaCheat(Timeline);\n const firstRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;\n const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;\n const clickedXInGantt = clickedX - ganttLeftOffset;\n const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());\n const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))\n + ganttLeftOffset; \n await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));\n \n // AND is correctly added to the clicked row\n await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN I right click on a segment, THEN a context menu with 3 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenRightClickOnASegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_0\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n\n // WHEN right click on a segment\n await tad.showSpotlight({ message: \"I right click on a segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n \n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add', 'Edit' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[0].title);\n \n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n \n tad.cc(\"And a 'Delete' action\");\n let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\");\n await tad.assertWaitable.equal(menuEntry.textContent, deleteActionLabel);\n tad.cc(\"With a custom red renderer\");\n tad.demoForEndUserHideNext();\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIcon);\n await tad.assertWaitable.include(menuEntry.querySelector(\"i\").className, deleteActionIconColor);\n }\n\n @Scenario(\"WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown\")\n @ScenarioOptions({ linkWithNextScenario: true })\n async whenCTRLRightClickOnAnotherSegment() {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_3\");\n const segmentBoundingRect = segment.getBoundingClientRect();\n await tad.showSpotlight({ message: \"WHEN I CTRL + right click another segment\", focusOnLastElementCaptured: true });\n rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });\n\n // THEN the CM opens\n tad.demoForEndUserHideNext();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n\n // AND it has: 'Add' and 'Delete' actions\n tad.cc(\"The context menu contains an 'Add' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskActionLabel + someHumanResources[1].title);\n \n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, deleteActionLabel);\n }\n\n @Scenario(\"WHEN I click the hamburger button, THEN the context menu is shown besides that button\")\n async whenClickTheHamburgerButton() {\n // GIVEN I select one segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n\n // WHEN\n const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(menuButton);\n\n // THEN the context menu is opened and positioned near the center of the hamburger button\");\n tad.demoForEndUserHide();\n const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);\n await tad.assertWaitable.exists(popup);\n const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };\n await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);\n tad.demoForEndUserShow();\n\n // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions\n tad.cc(\"The context menu contains an 'Add task not possible' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, addTaskNotPossibleAction);\n tad.cc(\"And an 'Edit' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\").textContent, editActionLabel);\n tad.cc(\"And a 'Delete' action\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_2\").textContent, deleteActionLabel);\n\n // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close \n // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial \n tad.demoForEndUserHide();\n await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + \"_1\"));\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n tad.demoForEndUserShow();\n }\n\n async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {\n const popupEndX = Math.round(popupX + popupWidth);\n const popupEndY = Math.round(popupY + popupHeight);\n popupX = Math.floor(popupX);\n popupY = Math.round(popupY);\n\n // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position. \n // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen\n // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)\n await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));\n // semantic ui popup is displayed 10 px below or 10 px above the mouse position\n await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));\n }\n}"},"duration":988}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/report.md b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/report.md
new file mode 100644
index 00000000..673c40dc
--- /dev/null
+++ b/demo-app/public/recordedTests/ContextMenuTestsAreDemo/whenRightClickOnASegment/report.md
@@ -0,0 +1,363 @@
+
+# ContextMenuTestsAreDemo/whenRightClickOnASegment()
+
+### undefined
+
+---
+
+There are 7 screenshots. [Go to first](#screenshot-1)
+
+## ContextMenuTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { ContextMenu, addTaskActionIcon, addTaskActionLabel, addTaskNotPossibleAction, deleteActionIcon, deleteActionIconColor, deleteActionLabel, editActionLabel } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someHumanResources, someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { PARENT_ELEMENT, timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { getPixelAtTime, getTimeAtPixel } from "../../../src/utils/timeUtils";
+/* 7*/import { rightClick } from "./testUtils";
+/* 8*/
+/* 9*/const CLICK_X =30;
+/* 10*/export class ContextMenuTestsAreDemo {
+/* 11*/
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN I right click on a row, THEN a context menu with one action opens")
+/* 17*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 18*/ async whenRightClickOnARow() {
+/* 19*/ // WHEN right click on a row
+/* 20*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 21*/ const clickPosition = { clientX: Math.round(firstRow.getBoundingClientRect().x) + CLICK_X, clientY: Math.round(firstRow.getBoundingClientRect().y) + 20 };
+/* 22*/ await tad.showSpotlight({ message: "I right click on a row", focusOnLastElementCaptured: true });
+/* 23*/ rightClick(firstRow, clickPosition);
+/* 24*/
+/* 25*/ // THEN CM is opened at the clicked position
+/* 26*/ tad.demoForEndUserHide();
+/* 27*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 28*/ await tad.assertWaitable.exists(popup);
+/* 29*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), { x: clickPosition.clientX, y: clickPosition.clientY });
+/* 30*/ tad.demoForEndUserShow();
+/* 31*/
+/* 32*/ // AND it has an 'Add task' actions
+/* 33*/ let menuEntry = tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0");
+/* 34*/ tad.cc("The context menu contains an 'Add' action");
+/* 35*/ await tad.assertWaitable.equal(menuEntry.textContent, addTaskActionLabel + someHumanResources[0].title);
+/* 36*/ tad.demoForEndUserHideNext();
+/* 37*/ await tad.assertWaitable.include(menuEntry.querySelector("i").className, addTaskActionIcon);
+/* 38*/ }
+/* 39*/
+/* 40*/ @Scenario("WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)")
+/* 41*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 42*/ async whenClickAnAction() {
+/* 43*/ // WHEN I click on "Add"
+/* 44*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/* 45*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 46*/
+/* 47*/ // THEN a new task is added
+/* 48*/ let newSegment = tad.screenCapturing.getByTestId(testids.item + "_" + someTasks.length);
+/* 49*/ await tad.assertWaitable.exists(newSegment);
+/* 50*/
+/* 51*/ tad.demoForEndUserHide();
+/* 52*/ // AND the CM is closed
+/* 53*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup));
+/* 54*/
+/* 55*/ // AND the new task is position correctly on x axes
+/* 56*/ // Gantt works with times "snapped to grid" so the position for the new task should be snapped to grid
+/* 57*/ const timeline = tad.getObjectViaCheat(Timeline);
+/* 58*/ const firstRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/* 59*/ const ganttLeftOffset = PARENT_ELEMENT(timeline.props.componentId).getBoundingClientRect().left;
+/* 60*/ const clickedX = firstRow.getBoundingClientRect().x + CLICK_X;
+/* 61*/ const clickedXInGantt = clickedX - ganttLeftOffset;
+/* 62*/ const clickedTime = getTimeAtPixel(clickedXInGantt, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined), timeline.getTimelineSnap());
+/* 63*/ const clickedXSnappedToGrid = getPixelAtTime(clickedTime, timeline.getStartDate(), timeline.getEndDate(), timeline.getTimelineWidth(undefined))
+/* 64*/ + ganttLeftOffset;
+/* 65*/ await tad.assertWaitable.equal(Math.round(newSegment.getBoundingClientRect().x), Math.round(clickedXSnappedToGrid));
+/* 66*/
+/* 67*/ // AND is correctly added to the clicked row
+/* 68*/ await tad.assertWaitable.equal(newSegment.getBoundingClientRect().y, firstRow.getBoundingClientRect().y);
+/* 69*/ tad.demoForEndUserShow();
+```
+
+
+
+```tsx
+/* 70*/ }
+/* 71*/
+/* 72*/ @Scenario("WHEN I right click on a segment, THEN a context menu with 3 actions is shown")
+/* 73*/ @ScenarioOptions({ linkWithNextScenario: true })
+/* 74*/ async whenRightClickOnASegment() {
+/* 75*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_0");
+/* 76*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/* 77*/
+/* 78*/ // WHEN right click on a segment
+/* 79*/ await tad.showSpotlight({ message: "I right click on a segment", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+ContextMenuTestsAreDemo/whenRightClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*101*/ }
+/*102*/
+/*103*/ @Scenario("WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown")
+/*104*/ @ScenarioOptions({ linkWithNextScenario: true })
+/*105*/ async whenCTRLRightClickOnAnotherSegment() {
+/*106*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_3");
+/*107*/ const segmentBoundingRect = segment.getBoundingClientRect();
+/*108*/ await tad.showSpotlight({ message: "WHEN I CTRL + right click another segment", focusOnLastElementCaptured: true });
+/*109*/ rightClick(segment, { ctrlKey: true, clientX: segmentBoundingRect.x + segmentBoundingRect.width / 2, clientY: segmentBoundingRect.y + segmentBoundingRect.height / 2 });
+/*110*/
+/*111*/ // THEN the CM opens
+/*112*/ tad.demoForEndUserHideNext();
+/*113*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*114*/ await tad.assertWaitable.exists(popup);
+/*115*/
+/*116*/ // AND it has: 'Add' and 'Delete' actions
+/*117*/ tad.cc("The context menu contains an 'Add' action");
+/*118*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskActionLabel + someHumanResources[1].title);
+/*119*/
+/*120*/ tad.cc("And a 'Delete' action");
+/*121*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, deleteActionLabel);
+/*122*/ }
+/*123*/
+/*124*/ @Scenario("WHEN I click the hamburger button, THEN the context menu is shown besides that button")
+/*125*/ async whenClickTheHamburgerButton() {
+/*126*/ // GIVEN I select one segment
+/*127*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/*128*/
+/*129*/ // WHEN
+/*130*/ const menuButton = tad.screenCapturing.getByTestId(testids.menuButton);
+/*131*/ tad.cc("Click on the menu button");
+/*132*/ await tad.userEventWaitable.click(menuButton);
+/*133*/
+/*134*/ // THEN the context menu is opened and positioned near the center of the hamburger button");
+/*135*/ tad.demoForEndUserHide();
+/*136*/ const popup = tad.screenCapturing.getByTestId(contextMenuTestIds.popup);
+/*137*/ await tad.assertWaitable.exists(popup);
+/*138*/ const menuButtonCenter = { x: menuButton.getBoundingClientRect().x + menuButton.getBoundingClientRect().width / 2, y: menuButton.getBoundingClientRect().y + menuButton.getBoundingClientRect().height / 2 };
+/*139*/ await this.isPopupPositionedNearPoint(popup.getBoundingClientRect(), menuButtonCenter);
+/*140*/ tad.demoForEndUserShow();
+/*141*/
+/*142*/ // AND it has: 'Add task: not possible', 'Edit' adn 'Delete' actions
+/*143*/ tad.cc("The context menu contains an 'Add task not possible' action");
+/*144*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_0").textContent, addTaskNotPossibleAction);
+/*145*/ tad.cc("And an 'Edit' action");
+/*146*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1").textContent, editActionLabel);
+/*147*/ tad.cc("And a 'Delete' action");
+/*148*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_2").textContent, deleteActionLabel);
+/*149*/
+/*150*/ // WHEN click 'Edit' (dontCloseContextMenuAfterRunAutomatically = true) THEN the CM doesn't close
+/*151*/ // We putted this verification at the end of the tests, because else we needed to close the prompt for the next scenarios, and this was not trivial
+/*152*/ tad.demoForEndUserHide();
+/*153*/ await tad.userEventWaitable.click(tad.withinCapturing(popup).getByTestId(contextMenuTestIds.menuItem + "_1"));
+/*154*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/*155*/ tad.demoForEndUserShow();
+/*156*/ }
+/*157*/
+/*158*/ async isPopupPositionedNearPoint({ x: popupX, y: popupY, width: popupWidth, height: popupHeight }, { x, y }) {
+/*159*/ const popupEndX = Math.round(popupX + popupWidth);
+/*160*/ const popupEndY = Math.round(popupY + popupHeight);
+/*161*/ popupX = Math.floor(popupX);
+/*162*/ popupY = Math.round(popupY);
+/*163*/
+/*164*/ // We didn't understood why it is a difference of some decimals (maximum 1 px) between the expected position and the actual position.
+/*165*/ // These difference in decimals is not the same every time, is variable regarding the dimension of the window and the dpi of the screen
+/*166*/ // So the only thing in common is that the actual value is near the expected one at a maximum 1 px distance (below or above)
+/*167*/ await tad.assertWaitable.include([popupX - 1, popupX, popupX + 1, popupEndX - 1, popupEndX, popupEndX + 1], Math.round(x));
+/*168*/ // semantic ui popup is displayed 10 px below or 10 px above the mouse position
+/*169*/ await tad.assertWaitable.include([popupY - 11, popupY - 10, popupY - 9, popupEndY + 9, popupEndY + 10, popupEndY + 11], Math.round(y));
+/*170*/ }
+/*171*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11.png
new file mode 100644
index 00000000..d1173293
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11_small.png
new file mode 100644
index 00000000..673ca67f
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_2_Timeline_item_11_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3.png
new file mode 100644
index 00000000..47cce864
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1.png
new file mode 100644
index 00000000..d4022086
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1_small.png
new file mode 100644
index 00000000..28c4a344
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2.png
new file mode 100644
index 00000000..6faa17c1
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2_small.png
new file mode 100644
index 00000000..4e2b8f9f
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_small.png
new file mode 100644
index 00000000..f0dc3fa0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/recordedTest.json
new file mode 100644
index 00000000..de1e47bf
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":196},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":199},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":135},{"screenshot":"Timeline_ganttBody_Timeline_row_2_Timeline_item_11","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":138}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":790}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/report.md
new file mode 100644
index 00000000..646dd1dc
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/report.md
@@ -0,0 +1,322 @@
+
+# DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp()
+
+### undefined
+
+---
+
+There are 4 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+```
+
+
+
+```tsx
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3_REP2.png
+
+
+
+
+
+```tsx
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp/Timeline_ganttBody_Timeline_row_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3.png
new file mode 100644
index 00000000..d6a67448
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1.png
new file mode 100644
index 00000000..a7b671a7
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1_small.png
new file mode 100644
index 00000000..f0dc3fa0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2.png
new file mode 100644
index 00000000..01905f21
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2_small.png
new file mode 100644
index 00000000..28c4a344
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3.png
new file mode 100644
index 00000000..fd97c06d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3_small.png
new file mode 100644
index 00000000..4e2b8f9f
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4.png
new file mode 100644
index 00000000..68f702de
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4_small.png
new file mode 100644
index 00000000..f0dc3fa0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP4_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_small.png
new file mode 100644
index 00000000..f0dc3fa0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/recordedTest.json
new file mode 100644
index 00000000..6478f71a
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":117},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":196},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":199},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":120},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP4","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":124}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":974}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/report.md
new file mode 100644
index 00000000..de429136
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/report.md
@@ -0,0 +1,346 @@
+
+# DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick()
+
+### undefined
+
+---
+
+There are 5 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+```
+
+
+
+```tsx
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3.png
+
+
+
+
+
+```tsx
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick/Timeline_ganttBody_Timeline_row_3_REP1.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2.png
new file mode 100644
index 00000000..7f17106e
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2_small.png
new file mode 100644
index 00000000..71376d5c
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3.png
new file mode 100644
index 00000000..a9925945
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1.png
new file mode 100644
index 00000000..2dbc81b0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1_small.png
new file mode 100644
index 00000000..28c4a344
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_small.png
new file mode 100644
index 00000000..751c1948
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4.png
new file mode 100644
index 00000000..9cf9cfd0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4_small.png
new file mode 100644
index 00000000..e45a9510
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector.png
new file mode 100644
index 00000000..2d27674e
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1.png
new file mode 100644
index 00000000..0255ba19
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1_small.png
new file mode 100644
index 00000000..5ee52cb2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2.png
new file mode 100644
index 00000000..a21e1e85
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2_small.png
new file mode 100644
index 00000000..5ee52cb2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_small.png
new file mode 100644
index 00000000..5ee52cb2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/recordedTest.json
new file mode 100644
index 00000000..519740bd
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":196},{"screenshot":"Timeline_ganttBody_Timeline_row_3_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":199},{"screenshot":"Timeline_selector","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":95},{"screenshot":"Timeline_ganttBody_Timeline_row_4","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":97},{"screenshot":"Timeline_selector_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":100},{"screenshot":"Timeline_ganttBody_Timeline_row_2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":102},{"screenshot":"Timeline_selector_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":105}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":1182}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/report.md
new file mode 100644
index 00000000..967e5c05
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/report.md
@@ -0,0 +1,394 @@
+
+# DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag()
+
+### undefined
+
+---
+
+There are 7 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+```
+
+
+
+```tsx
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3) | [Go to next](#screenshot-5)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_4.png
+
+
+
+
+
+### Screenshot 7
+
+[Go to previous](#screenshot-6)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_selector_REP2.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag/Timeline_ganttBody_Timeline_row_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0.png
new file mode 100644
index 00000000..0cfc7aff
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0_small.png
new file mode 100644
index 00000000..aa288fcb
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png
new file mode 100644
index 00000000..fa53588f
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png
new file mode 100644
index 00000000..6c2de42b
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton.png
new file mode 100644
index 00000000..280f87dc
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton_small.png
new file mode 100644
index 00000000..3c275751
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP.png
new file mode 100644
index 00000000..4edc60f1
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP_small.png
new file mode 100644
index 00000000..4edc60f1
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/recordedTest.json
new file mode 100644
index 00000000..2e5a8041
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_menuButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":72},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_0","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":74},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":78},{"screenshot":"_LAP","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":81}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":566}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/report.md
new file mode 100644
index 00000000..56b35d7e
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/report.md
@@ -0,0 +1,322 @@
+
+# DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel()
+
+### undefined
+
+---
+
+There are 4 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+```
+
+
+
+```tsx
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/Timeline_menuButton.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/ContextMenu_popup_ContextMenu_menuItem_0.png
+
+
+
+
+
+```tsx
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel/_LAP.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+/*197*/ tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);
+/*198*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*199*/ await tad.showSpotlight({ message: "We perform mouse move with " + x + "px on X axis", focusOnLastElementCaptured: true });
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0.png
new file mode 100644
index 00000000..a0c39c79
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0_small.png
new file mode 100644
index 00000000..aa288fcb
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup.png
new file mode 100644
index 00000000..9e912a50
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png
new file mode 100644
index 00000000..ade3c942
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1.png
new file mode 100644
index 00000000..59d0f950
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1_small.png
new file mode 100644
index 00000000..6c2de42b
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png
new file mode 100644
index 00000000..6c2de42b
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1.png
new file mode 100644
index 00000000..24dc6804
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1_small.png
new file mode 100644
index 00000000..85265ece
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2.png
new file mode 100644
index 00000000..a18eeb43
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2_small.png
new file mode 100644
index 00000000..887f372e
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3.png
new file mode 100644
index 00000000..d8f8e5f7
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3_small.png
new file mode 100644
index 00000000..dd348744
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_small.png
new file mode 100644
index 00000000..e95f1bfa
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton.png
new file mode 100644
index 00000000..cca370e1
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton_small.png
new file mode 100644
index 00000000..3c275751
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP.png
new file mode 100644
index 00000000..6384e344
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP1.png
new file mode 100644
index 00000000..a292c1b2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2.png
new file mode 100644
index 00000000..5d41761c
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2_small.png
new file mode 100644
index 00000000..5d41761c
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_small.png
new file mode 100644
index 00000000..ccf7793f
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/recordedTest.json
new file mode 100644
index 00000000..e67dea77
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_menuButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":28},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_0","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":32},{"screenshot":"_LAP","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":35},{"screenshot":"Timeline_dragToCreatePopup","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":39},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":42},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":43},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":44},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":47},{"screenshot":"Timeline_dragToCreatePopup_Timeline_dragToCreatePopupCancelButton_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":49},{"screenshot":"_LAP_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":59},{"screenshot":"_LAP_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":62}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":6651}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/report.md
new file mode 100644
index 00000000..1905979b
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickAddMenuEntry/report.md
@@ -0,0 +1,490 @@
+
+# DragToCreateTestsAreDemo/whenClickAddMenuEntry()
+
+### undefined
+
+---
+
+There are 11 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+```
+
+
+
+```tsx
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_menuButton.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickAddMenuEntry/ContextMenu_popup_ContextMenu_menuItem_0.png
+
+
+
+
+
+```tsx
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+```
+
+
+
+
+### Screenshot 7
+
+[Go to previous](#screenshot-6) | [Go to next](#screenshot-8)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickAddMenuEntry/Timeline_dragToCreatePopup_Timeline_dragToCreatePopupLabel_3.png
+
+
+
+
+
+```tsx
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+```
+
+
+
+
+### Screenshot 10
+
+[Go to previous](#screenshot-9) | [Go to next](#screenshot-11)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP1.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+```
+
+
+
+
+### Screenshot 11
+
+[Go to previous](#screenshot-10)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickAddMenuEntry/_LAP_REP2.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+/*197*/ tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);
+/*198*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*199*/ await tad.showSpotlight({ message: "We perform mouse move with " + x + "px on X axis", focusOnLastElementCaptured: true });
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup.png
new file mode 100644
index 00000000..504bd0b2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0.png
new file mode 100644
index 00000000..f28d436d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png
new file mode 100644
index 00000000..aa288fcb
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_small.png
new file mode 100644
index 00000000..aa3d91f4
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton.png
new file mode 100644
index 00000000..c5098152
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton_small.png
new file mode 100644
index 00000000..3c275751
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/recordedTest.json
new file mode 100644
index 00000000..355ade03
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_menuButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":16},{"screenshot":"ContextMenu_popup","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":18},{"screenshot":"ContextMenu_popup_ContextMenu_menuItem_0","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":21}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":621}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/report.md
new file mode 100644
index 00000000..3c70e23a
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenClickMenuButton/report.md
@@ -0,0 +1,298 @@
+
+# DragToCreateTestsAreDemo/whenClickMenuButton()
+
+### undefined
+
+---
+
+There are 3 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+```
+
+
+
+```tsx
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickMenuButton/Timeline_menuButton.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenClickMenuButton/ContextMenu_popup_ContextMenu_menuItem_0.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+/*168*/
+/*169*/ // AND
+/*170*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+/*180*/
+/*181*/ // THEN segments are not created at drag
+/*182*/ await startDragKeepInProgress(2, 100);
+/*183*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*184*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*185*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + "_13"));
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+/*197*/ tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);
+/*198*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*199*/ await tad.showSpotlight({ message: "We perform mouse move with " + x + "px on X axis", focusOnLastElementCaptured: true });
+/*200*/ await tad.getObjectViaCheat(Timeline).dragMove(x, 0);
+/*201*/}
+/*202*/
+```
+
+
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio.png
new file mode 100644
index 00000000..ed104383
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio_small.png
new file mode 100644
index 00000000..b3e8caf7
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio.png
new file mode 100644
index 00000000..6c63a433
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio_small.png
new file mode 100644
index 00000000..9ca42d35
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2.png
new file mode 100644
index 00000000..fcec5015
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1.png
new file mode 100644
index 00000000..e2650a53
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1_small.png
new file mode 100644
index 00000000..60a9ec7e
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2.png
new file mode 100644
index 00000000..8412dc0d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2_small.png
new file mode 100644
index 00000000..5ff2dc5d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3.png
new file mode 100644
index 00000000..c89e0067
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3_small.png
new file mode 100644
index 00000000..cec00182
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13.png
new file mode 100644
index 00000000..7afa54ef
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13_small.png
new file mode 100644
index 00000000..ded8dde4
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_Timeline_item_13_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_small.png
new file mode 100644
index 00000000..06eec6e0
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12.png
new file mode 100644
index 00000000..aaef0667
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12_small.png
new file mode 100644
index 00000000..ccf1b3b6
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton.png
new file mode 100644
index 00000000..1bf7aeb2
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton_small.png
new file mode 100644
index 00000000..3c275751
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector.png
new file mode 100644
index 00000000..5c6276e4
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1.png
new file mode 100644
index 00000000..92f012e4
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1_small.png
new file mode 100644
index 00000000..74c58d8d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2.png
new file mode 100644
index 00000000..80542022
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2_small.png
new file mode 100644
index 00000000..74c58d8d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_small.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_small.png
new file mode 100644
index 00000000..74c58d8d
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_small.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/_LAP.png b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/_LAP.png
new file mode 100644
index 00000000..2843a70b
Binary files /dev/null and b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/_LAP.png differ
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/recordedTest.json b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/recordedTest.json
new file mode 100644
index 00000000..38ef8f09
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"DragToCreateStory_forceDragToCreateModeTrueRadio","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":147},{"screenshot":"Timeline_ganttBody_Timeline_row_2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":196},{"screenshot":"Timeline_ganttBody_Timeline_row_2_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":199},{"screenshot":"Timeline_selector","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":157},{"screenshot":"Timeline_selector_REP1","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":159},{"screenshot":"Timeline_selector_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":162},{"screenshot":"Timeline_ganttBody_Timeline_row_3_Timeline_item_12","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":167},{"screenshot":"Timeline_menuButton","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":170},{"screenshot":"_LAP","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":171},{"screenshot":"DragToCreateStory_forceDragToCreateModeFalseRadio","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":179},{"screenshot":"Timeline_ganttBody_Timeline_row_2_REP2","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":196},{"screenshot":"Timeline_ganttBody_Timeline_row_2_REP3","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":199},{"screenshot":"Timeline_ganttBody_Timeline_row_2_Timeline_item_13","sourceFile":"DragToCreateTestsAreDemo.tsx","sourceLine":185}],"sourceFiles":{"DragToCreateTestsAreDemo.tsx":"import { Only, render, Scenario, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { contextMenuTestIds } from \"../../../src/components/ContextMenu/ContextMenu\";\nimport { Main } from \"../stories/dragToCreate/DragToCreate.stories\";\nimport Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from \"../../../src/timeline\";\nimport { dragToCreateStoriesTestIds as testIds } from \"../stories/dragToCreate/DragToCreate.stories\";\n\nexport class DragToCreateTestsAreDemo {\n\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry\")\n async whenClickMenuButton() {\n tad.cc(\"Click on the menu button\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Check if the context menu is open\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));\n\n tad.cc(\"Check if exist the 'Drag To Create' action\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\").textContent, DRAG_TO_CREATE_ACTION_LABEL);\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n }\n\n @Scenario(\"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears\")\n async whenClickAddMenuEntry() {\n // GIVEN context menu is opened by pressing the hamburger button\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n \n // WHEN\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // THEN\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Drag to create mode should be active\");\n\t\n\t const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);\n tad.cc(\"Check if drag to create popup exists\");\n await tad.assertWaitable.exists(popup);\n \n // Check the labels\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_1\").innerHTML, \"Click and drag to create a new segment\");\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_2\").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);\n await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + \"_3\").innerHTML, \"To cancel you can also click on gantt\");\n const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);\n tad.cc(\"Check if exists 'Cancel' button\");\n await tad.assertWaitable.exists(cancelButton);\n tad.cc(\"Check if the cancel button is negative\");\n await tad.assertWaitable.include(cancelButton.className, \"negative\");\n\n // Test auto closing of the popup\n tad.demoForEndUserHide();\n\n // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME \n // I tried to test also from time to time that the popup is opened but the setTimeout(time) \n // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause\n // inexact test for when the popup is still opened)\n await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));\n \n // AND still in drag to create mode\n await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);\n tad.demoForEndUserShow();\n\n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled\")\n async givenDragToCreateModeWhenClickCancel() {\n // GIVEN context menu was opened and 'Drag To Create' was pressed\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n tad.cc(\"Click 'Drag To Create' menu entry\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + \"_0\"));\n\n\t // WHEN\n tad.cc(\"Click on `Cancel 'drag to create' mode` button from the drag to create popup\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));\n \n // THEN\n await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, \"Check if the drag to create mode is cancelled\");\n \n tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears\")\n async givenDragToCreateModeWhenClickAndDrag() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n const { height } = selector.getBoundingClientRect();\n tad.cc(\"A green selection rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_4\");\n await tad.showSpotlight({ message: \"On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n await tad.showSpotlight({ message: \"Move the mouse on previous row\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);\n tad.cc(\"The height of the section regtagle isn't changed\");\n await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);\n\n tad.getObjectViaCheat(Timeline)._selectBox.end();\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN right click, THEN cancel\")\n async givenDragToCreateModeInProgressWhenRightClick() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n await startDragKeepInProgress(3, 100);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the right click\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).rightClick();\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n tad.cc(\"The segment wasn't created, the row don't have the segments\");\n await tad.assertWaitable.equal(row.children.length, 0);\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called\")\n async givenDragToCreateModeInProgressWhenMouseUp() {\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });\n\n await startDragKeepInProgress(3, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_3\");\n await tad.showSpotlight({ message: \"We perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n tad.cc(\"The segment was created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_11\"));\n\n tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });\n }\n\n @Scenario(\"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created\")\n async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {\n // WHEN forceDragToCreate = true\n await tad.cc(\"WHEN I set forceDragToCreate = true AND I drag to create\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));\n\n // AND WHEN I drag and move\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n\n tad.cc(\"AND I perform\");\n const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);\n // THEN\n tad.cc(\"THEN the drag to create rectangle appears on the row\");\n await tad.assertWaitable.exists(selector);\n tad.cc(\"AND it is green\");\n await tad.assertWaitable.include(Array.from(selector.classList), \"rct9k-selector-outer-add\");\n\n // AND WHEN I perform mouse up\n await tad.showSpotlight({ message: \"AND when I perform the mouse up\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragEnd();\n \n // THEN\n tad.cc(\"THEN A segment is created\");\n await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + \"_12\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n\n // WHEN forceDragToCreate = false \n await tad.cc(\"WHEN I set forceDragToCreate = false AND I drag and drop\");\n // TODO era uitat await; dar crapa in modul \"fast\";\n // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)\n // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam\n // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));\n\n // THEN segments are not created at drag\n await startDragKeepInProgress(2, 100);\n tad.screenCapturing.getByTestId(timelineTestids.row + \"_2\");\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.item + \"_13\"));\n\n // AND \n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));\n await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), \"AND no 'Drag to create' action is shown\");\n }\n}\n\nasync function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {\n // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost\n let row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform click for start the drag\", focusOnLastElementCaptured: true });\n tad.getObjectViaCheat(Timeline).dragStart(row, xOffset);\n row = tad.screenCapturing.getByTestId(timelineTestids.row + \"_\" + rowNumber);\n await tad.showSpotlight({ message: \"We perform mouse move with \" + x + \"px on X axis\", focusOnLastElementCaptured: true });\n await tad.getObjectViaCheat(Timeline).dragMove(x, 0);\n}\n"},"duration":2164,"error":"AssertionError: expected Task Mary Danton13 to not exist\n\t [oldFunction.apply(null, args);] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/TestsAreDemoFunctions.tsx:124:29)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/report.md b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/report.md
new file mode 100644
index 00000000..1b42defa
--- /dev/null
+++ b/demo-app/public/recordedTests/DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/report.md
@@ -0,0 +1,542 @@
+
+# DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+AssertionError: expected Task Mary Danton13 to not exist
+ [oldFunction.apply(null, args);] (http://localhost:3000/node_modules/@famiprog-foundation/tests-are-demo/src/lib/TestsAreDemoFunctions.tsx:124:29)
+```
+
+---
+
+
+There are 13 screenshots. [Go to first](#screenshot-1)
+
+## DragToCreateTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, render, Scenario, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { contextMenuTestIds } from "../../../src/components/ContextMenu/ContextMenu";
+/* 3*/import { Main } from "../stories/dragToCreate/DragToCreate.stories";
+/* 4*/import Timeline, { DRAG_TO_CREATE_ACTION_LABEL, DRAG_TO_CREATE_POPUP_CLOSE_TIME, DRAG_TO_CREATE_POPUP_LABEL_2, timelineTestids } from "../../../src/timeline";
+/* 5*/import { dragToCreateStoriesTestIds as testIds } from "../stories/dragToCreate/DragToCreate.stories";
+/* 6*/
+/* 7*/export class DragToCreateTestsAreDemo {
+/* 8*/
+/* 9*/ async before() {
+/* 10*/ render();
+/* 11*/ }
+/* 12*/
+/* 13*/ @Scenario("WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry")
+/* 14*/ async whenClickMenuButton() {
+/* 15*/ tad.cc("Click on the menu button");
+/* 16*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 17*/ tad.cc("Check if the context menu is open");
+/* 18*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(contextMenuTestIds.popup));
+/* 19*/
+/* 20*/ tad.cc("Check if exist the 'Drag To Create' action");
+/* 21*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0").textContent, DRAG_TO_CREATE_ACTION_LABEL);
+/* 22*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 23*/ }
+/* 24*/
+/* 25*/ @Scenario("WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears")
+/* 26*/ async whenClickAddMenuEntry() {
+/* 27*/ // GIVEN context menu is opened by pressing the hamburger button
+/* 28*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 29*/
+/* 30*/ // WHEN
+/* 31*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 33*/
+/* 34*/ // THEN
+/* 35*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Drag to create mode should be active");
+/* 36*/
+/* 37*/ const popup = tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopup);
+/* 38*/ tad.cc("Check if drag to create popup exists");
+/* 39*/ await tad.assertWaitable.exists(popup);
+/* 40*/
+/* 41*/ // Check the labels
+/* 42*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_1").innerHTML, "Click and drag to create a new segment");
+/* 43*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_2").textContent, DRAG_TO_CREATE_POPUP_LABEL_2);
+/* 44*/ await tad.assertWaitable.equal(tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupLabel + "_3").innerHTML, "To cancel you can also click on gantt");
+/* 45*/ const cancelButton = tad.withinCapturing(popup).getByTestId(timelineTestids.dragToCreatePopupCancelButton);
+/* 46*/ tad.cc("Check if exists 'Cancel' button");
+/* 47*/ await tad.assertWaitable.exists(cancelButton);
+/* 48*/ tad.cc("Check if the cancel button is negative");
+/* 49*/ await tad.assertWaitable.include(cancelButton.className, "negative");
+/* 50*/
+/* 51*/ // Test auto closing of the popup
+/* 52*/ tad.demoForEndUserHide();
+/* 53*/
+/* 54*/ // AND the popup closes after DRAG_TO_CREATE_POPUP_CLOSE_TIME
+/* 55*/ // I tried to test also from time to time that the popup is opened but the setTimeout(time)
+/* 56*/ // doesn't ensure that exacly `time` has passed, it could have passed a little bit more (and that little bit cause
+/* 57*/ // inexact test for when the popup is still opened)
+/* 58*/ await new Promise(resolve => setTimeout(resolve, DRAG_TO_CREATE_POPUP_CLOSE_TIME));
+/* 59*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(timelineTestids.dragToCreatePopup));
+/* 60*/
+/* 61*/ // AND still in drag to create mode
+/* 62*/ await tad.assertWaitable.isTrue(tad.getObjectViaCheat(Timeline).state.dragToCreateMode);
+/* 63*/ tad.demoForEndUserShow();
+/* 64*/
+/* 65*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 66*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 67*/ }
+/* 68*/
+/* 69*/ @Scenario("GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled")
+/* 70*/ async givenDragToCreateModeWhenClickCancel() {
+/* 71*/ // GIVEN context menu was opened and 'Drag To Create' was pressed
+/* 72*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/* 73*/ tad.cc("Click 'Drag To Create' menu entry");
+/* 74*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(contextMenuTestIds.menuItem + "_0"));
+/* 75*/
+/* 76*/ // WHEN
+/* 77*/ tad.cc("Click on `Cancel 'drag to create' mode` button from the drag to create popup");
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.dragToCreatePopupCancelButton));
+/* 79*/
+/* 80*/ // THEN
+/* 81*/ await tad.assertWaitable.isFalse(tad.getObjectViaCheat(Timeline).state.dragToCreateMode, "Check if the drag to create mode is cancelled");
+/* 82*/
+/* 83*/ tad.getObjectViaCheat(Timeline).setState({ openedContextMenuCoordinates: undefined });
+/* 84*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/* 85*/ }
+/* 86*/
+/* 87*/ @Scenario("GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears")
+/* 88*/ async givenDragToCreateModeWhenClickAndDrag() {
+/* 89*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/* 90*/
+/* 91*/ await startDragKeepInProgress(3, 100);
+/* 92*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/* 93*/ const { height } = selector.getBoundingClientRect();
+/* 94*/ tad.cc("A green selection rectangle appears on the row");
+/* 95*/ await tad.assertWaitable.exists(selector);
+/* 96*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_4");
+/* 97*/ await tad.showSpotlight({ message: "On drag to create mode in progress, when we move the mouse to the other row, selection rectangle stays only on the starting row, the mouse position is on the next row", focusOnLastElementCaptured: true });
+/* 98*/ await tad.getObjectViaCheat(Timeline).dragMove(0, height);
+/* 99*/ tad.cc("The height of the section regtagle isn't changed");
+/*100*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*101*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*102*/ await tad.showSpotlight({ message: "Move the mouse on previous row", focusOnLastElementCaptured: true });
+/*103*/ await tad.getObjectViaCheat(Timeline).dragMove(0, -2 * height);
+/*104*/ tad.cc("The height of the section regtagle isn't changed");
+/*105*/ await tad.assertWaitable.equal(tad.screenCapturing.getByTestId(timelineTestids.selector).getBoundingClientRect().height, height);
+/*106*/
+/*107*/ tad.getObjectViaCheat(Timeline)._selectBox.end();
+/*108*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*109*/ }
+/*110*/
+/*111*/ @Scenario("GIVEN drag to create in progress, WHEN right click, THEN cancel")
+/*112*/ async givenDragToCreateModeInProgressWhenRightClick() {
+/*113*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*114*/
+/*115*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*116*/ tad.cc("The row don't have the segments");
+/*117*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*118*/ await startDragKeepInProgress(3, 100);
+/*119*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*120*/ await tad.showSpotlight({ message: "We perform the right click", focusOnLastElementCaptured: true });
+/*121*/ tad.getObjectViaCheat(Timeline).rightClick();
+/*122*/ row = tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*123*/ tad.cc("The segment wasn't created, the row don't have the segments");
+/*124*/ await tad.assertWaitable.equal(row.children.length, 0);
+/*125*/
+/*126*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*127*/ }
+/*128*/
+/*129*/ @Scenario("GIVEN drag to create in progress, WHEN mouse up, THEN handler is called")
+/*130*/ async givenDragToCreateModeInProgressWhenMouseUp() {
+/*131*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: true });
+/*132*/
+/*133*/ await startDragKeepInProgress(3, 100);
+/*134*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_3");
+/*135*/ await tad.showSpotlight({ message: "We perform the mouse up", focusOnLastElementCaptured: true });
+/*136*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*137*/ tad.cc("The segment was created");
+```
+
+
+
+```tsx
+/*138*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_11"));
+/*139*/
+/*140*/ tad.getObjectViaCheat(Timeline).setState({ dragToCreateMode: false });
+/*141*/ }
+/*142*/
+/*143*/ @Scenario("WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created")
+/*144*/ async whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot() {
+/*145*/ // WHEN forceDragToCreate = true
+/*146*/ await tad.cc("WHEN I set forceDragToCreate = true AND I drag to create");
+/*147*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeTrueRadio));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeTrueRadio.png
+
+
+
+
+
+```tsx
+/*148*/
+/*149*/ // AND WHEN I drag and move
+/*150*/ await startDragKeepInProgress(2, 100);
+/*151*/ tad.screenCapturing.getByTestId(timelineTestids.row + "_2");
+/*152*/
+/*153*/ tad.cc("AND I perform");
+/*154*/ const selector = tad.screenCapturing.getByTestId(timelineTestids.selector);
+/*155*/ // THEN
+/*156*/ tad.cc("THEN the drag to create rectangle appears on the row");
+/*157*/ await tad.assertWaitable.exists(selector);
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3) | [Go to next](#screenshot-5)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*158*/ tad.cc("AND it is green");
+/*159*/ await tad.assertWaitable.include(Array.from(selector.classList), "rct9k-selector-outer-add");
+```
+
+
+
+
+### Screenshot 5
+
+[Go to previous](#screenshot-4) | [Go to next](#screenshot-6)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP1.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*160*/
+/*161*/ // AND WHEN I perform mouse up
+/*162*/ await tad.showSpotlight({ message: "AND when I perform the mouse up", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 6
+
+[Go to previous](#screenshot-5) | [Go to next](#screenshot-7)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_selector_REP2.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*163*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*164*/
+/*165*/ // THEN
+/*166*/ tad.cc("THEN A segment is created");
+/*167*/ await tad.assertWaitable.exists(tad.screenCapturing.getByTestId(timelineTestids.item + "_12"));
+```
+
+
+
+
+### Screenshot 7
+
+[Go to previous](#screenshot-6) | [Go to next](#screenshot-8)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_3_Timeline_item_12.png
+
+
+
+
+
+### Screenshot 8
+
+[Go to previous](#screenshot-7) | [Go to next](#screenshot-9)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_menuButton.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*171*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+```
+
+
+
+
+### Screenshot 9
+
+[Go to previous](#screenshot-8) | [Go to next](#screenshot-10)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/_LAP.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*172*/
+/*173*/ // WHEN forceDragToCreate = false
+/*174*/ await tad.cc("WHEN I set forceDragToCreate = false AND I drag and drop");
+/*175*/ // TODO era uitat await; dar crapa in modul "fast";
+/*176*/ // insa de evitat interactiuni de UI inutile. A simula o actiune omeneasca (e.g. apasare pe buton)
+/*177*/ // este un efort pentru noi. Ne e mult mai simplu sa apelam o functie care sa faca treaba, decat sa simulam
+/*178*/ // actiunea. In cazul asta deci, cred ca era mai bine sa setam acel mod programatic
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testIds.forceDragToCreateModeFalseRadio));
+```
+
+
+
+
+### Screenshot 10
+
+[Go to previous](#screenshot-9) | [Go to next](#screenshot-11)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/DragToCreateStory_forceDragToCreateModeFalseRadio.png
+
+
+
+
+
+```tsx
+/*186*/
+/*187*/ // AND
+/*188*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(timelineTestids.menuButton));
+/*189*/ await tad.assertWaitable.notExists(tad.screenCapturing.queryByTestId(contextMenuTestIds.popup), "AND no 'Drag to create' action is shown");
+/*190*/ }
+/*191*/}
+/*192*/
+/*193*/async function startDragKeepInProgress(rowNumber: number, x: number, xOffset: number = 10) {
+/*194*/ // we need to get the row after each showSpotlight because on click next step the lastElementCaptured was lost
+/*195*/ let row = tad.screenCapturing.getByTestId(timelineTestids.row + "_" + rowNumber);
+/*196*/ await tad.showSpotlight({ message: "We perform click for start the drag", focusOnLastElementCaptured: true });
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot/Timeline_ganttBody_Timeline_row_2.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*22*/ }
+/*23*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png
new file mode 100644
index 00000000..1c06f579
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1.png
new file mode 100644
index 00000000..a6e019de
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1_small.png
new file mode 100644
index 00000000..520ba9d5
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png
new file mode 100644
index 00000000..6ac6ba36
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..d5a295ba
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..192df6ca
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4.png
new file mode 100644
index 00000000..62d83725
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1.png
new file mode 100644
index 00000000..46337e89
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1_small.png
new file mode 100644
index 00000000..27179811
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_small.png
new file mode 100644
index 00000000..293b7b35
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/recordedTest.json
new file mode 100644
index 00000000..d6bebe4c
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_0","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":71},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_4","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":78},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":82},{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":102},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":103}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":899}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/report.md
new file mode 100644
index 00000000..01e0d208
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/report.md
@@ -0,0 +1,484 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLClickOnASegment()
+
+### undefined
+
+---
+
+There are 5 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+```
+
+
+
+```tsx
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0.png
+
+
+
+
+
+```tsx
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4.png
+
+
+
+
+
+```tsx
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_4_REP1.png
+
+
+
+
+
+```tsx
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3) | [Go to next](#screenshot-5)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_0_REP1.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..1ae35a11
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..35c42b6a
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/recordedTest.json
new file mode 100644
index 00000000..59b0a45f
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":112}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":197}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/report.md
new file mode 100644
index 00000000..dd9427b8
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/report.md
@@ -0,0 +1,388 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+```
+
+
+
+```tsx
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1.png
new file mode 100644
index 00000000..53a72d69
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png
new file mode 100644
index 00000000..583ba262
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png
new file mode 100644
index 00000000..fe633f01
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_small.png
new file mode 100644
index 00000000..9880bc0c
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/recordedTest.json
new file mode 100644
index 00000000..6b6cace9
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":121},{"screenshot":"Timeline_ganttBody_Timeline_row_1_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":128}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":387}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/report.md
new file mode 100644
index 00000000..7cdcb7eb
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLClickOutside/report.md
@@ -0,0 +1,412 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLClickOutside()
+
+### undefined
+
+---
+
+There are 2 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+```
+
+
+
+```tsx
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLClickOutside/Timeline_ganttBody_Timeline_row_1.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan.png
new file mode 100644
index 00000000..a805efc9
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan_small.png
new file mode 100644
index 00000000..bd1252a8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1.png
new file mode 100644
index 00000000..bec7d862
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1.png
new file mode 100644
index 00000000..7f2046f1
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1_small.png
new file mode 100644
index 00000000..84ed6953
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2.png
new file mode 100644
index 00000000..a49143e6
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2_small.png
new file mode 100644
index 00000000..fa811759
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3.png
new file mode 100644
index 00000000..c81c4f43
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3_small.png
new file mode 100644
index 00000000..a0b60890
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..a0039215
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png
new file mode 100644
index 00000000..0fe3fbe8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png
new file mode 100644
index 00000000..c57790eb
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2.png
new file mode 100644
index 00000000..2caaeb18
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2_small.png
new file mode 100644
index 00000000..7aa496e8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3.png
new file mode 100644
index 00000000..b4229738
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3_small.png
new file mode 100644
index 00000000..cb900e2c
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..7aa496e8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_small.png
new file mode 100644
index 00000000..771c6822
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/recordedTest.json
new file mode 100644
index 00000000..8596cb16
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"SelectionStory_selectedItemsSpan","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":201},{"screenshot":"Timeline_ganttBody_Timeline_row_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":209},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313},{"screenshot":"Timeline_ganttBody_Timeline_row_1_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":218},{"screenshot":"Timeline_ganttBody_Timeline_row_1_REP2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":227},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313},{"screenshot":"Timeline_ganttBody_Timeline_row_1_REP3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":236}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":5526}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/report.md
new file mode 100644
index 00000000..cb4034db
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/report.md
@@ -0,0 +1,571 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment()
+
+### undefined
+
+---
+
+There are 9 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+```
+
+
+
+```tsx
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/SelectionStory_selectedItemsSpan.png
+
+
+
+
+
+```tsx
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png
new file mode 100644
index 00000000..66e24fd3
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png
new file mode 100644
index 00000000..f4f819ab
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png
new file mode 100644
index 00000000..eef598ac
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png
new file mode 100644
index 00000000..c54cdac5
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png
new file mode 100644
index 00000000..eef598ac
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png
new file mode 100644
index 00000000..eef598ac
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP.png
new file mode 100644
index 00000000..eb0032f8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP_small.png
new file mode 100644
index 00000000..54054ca4
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/recordedTest.json
new file mode 100644
index 00000000..888b8d64
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"_LAP","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":246},{"screenshot":"Timeline_ganttBody_Timeline_row_0","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":257},{"screenshot":"Timeline_ganttBody_Timeline_row_0_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":258},{"screenshot":"Timeline_ganttBody_Timeline_row_0_REP2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":259}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":600}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/report.md
new file mode 100644
index 00000000..2b738b92
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/report.md
@@ -0,0 +1,460 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea()
+
+### undefined
+
+---
+
+There are 4 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+```
+
+
+
+```tsx
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/_LAP.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png
new file mode 100644
index 00000000..fc13fe89
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png
new file mode 100644
index 00000000..0258e218
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/recordedTest.json
new file mode 100644
index 00000000..4f04a2b8
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"SelectionStory_selectedItemsSpan","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":193}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":411}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/report.md
new file mode 100644
index 00000000..6669d307
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/report.md
@@ -0,0 +1,388 @@
+
+# SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+```
+
+
+
+```tsx
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..68ef3fab
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..c8ca1267
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/recordedTest.json
new file mode 100644
index 00000000..54b4e569
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":62}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":133}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/report.md
new file mode 100644
index 00000000..47b373ba
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickAnotherSegment/report.md
@@ -0,0 +1,388 @@
+
+# SelectedItemsTestsAreDemo/whenClickAnotherSegment()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+```
+
+
+
+```tsx
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png
new file mode 100644
index 00000000..52ef805c
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png
new file mode 100644
index 00000000..2c5acf1e
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2.png
new file mode 100644
index 00000000..5eda4155
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1.png
new file mode 100644
index 00000000..6761e6b6
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1_small.png
new file mode 100644
index 00000000..3c3ddb20
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2.png
new file mode 100644
index 00000000..a0f4a35d
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2_small.png
new file mode 100644
index 00000000..b4622aab
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3.png
new file mode 100644
index 00000000..8f84be82
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3_small.png
new file mode 100644
index 00000000..8e0debd4
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_small.png
new file mode 100644
index 00000000..c486e5ba
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1.png
new file mode 100644
index 00000000..c80c09ab
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1_small.png
new file mode 100644
index 00000000..8fd07c02
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/recordedTest.json
new file mode 100644
index 00000000..0e0656c9
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":20},{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":27},{"screenshot":"Timeline_ganttBody_Timeline_row_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":32},{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":47},{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":48},{"screenshot":"Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":53}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":1045}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/report.md
new file mode 100644
index 00000000..0f05b0e1
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOnASegment/report.md
@@ -0,0 +1,508 @@
+
+# SelectedItemsTestsAreDemo/whenClickOnASegment()
+
+### undefined
+
+---
+
+There are 6 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+```
+
+
+
+```tsx
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2.png
+
+
+
+
+
+```tsx
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+```
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_2_REP1.png
+
+
+
+
+
+```tsx
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_1.png
+
+
+
+
+
+```tsx
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+```
+
+
+
+
+### Screenshot 4
+
+[Go to previous](#screenshot-3) | [Go to next](#screenshot-5)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickOnASegment/Timeline_ganttBody_Timeline_row_0_Timeline_item_1.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1.png
new file mode 100644
index 00000000..c04e6224
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png
new file mode 100644
index 00000000..0c6b5b7e
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png
new file mode 100644
index 00000000..b2bf515f
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_small.png
new file mode 100644
index 00000000..fe633f01
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/recordedTest.json
new file mode 100644
index 00000000..62e4f5a0
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_ganttBody_Timeline_row_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":146},{"screenshot":"Timeline_ganttBody_Timeline_row_1_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":147}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":391}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/report.md
new file mode 100644
index 00000000..ecd9f2a1
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenClickOutside/report.md
@@ -0,0 +1,412 @@
+
+# SelectedItemsTestsAreDemo/whenClickOutside()
+
+### undefined
+
+---
+
+There are 2 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+```
+
+
+
+```tsx
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenClickOutside/Timeline_ganttBody_Timeline_row_1.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan.png
new file mode 100644
index 00000000..7b2e5664
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan_small.png
new file mode 100644
index 00000000..18c7545f
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png
new file mode 100644
index 00000000..3b90693d
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png
new file mode 100644
index 00000000..a3dbad8e
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png
new file mode 100644
index 00000000..00a9b455
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png
new file mode 100644
index 00000000..7af2e3e9
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png
new file mode 100644
index 00000000..00a9b455
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_REP2_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png
new file mode 100644
index 00000000..fe4aa1fe
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_0_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..8fd3f1f1
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..1eeb89aa
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP.png
new file mode 100644
index 00000000..9cde2029
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP_small.png
new file mode 100644
index 00000000..6e872d31
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/recordedTest.json
new file mode 100644
index 00000000..857d2990
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"SelectionStory_selectedItemsSpan","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":268},{"screenshot":"_LAP","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":273},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":280},{"screenshot":"Timeline_ganttBody_Timeline_row_0","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":283},{"screenshot":"Timeline_ganttBody_Timeline_row_0_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":284},{"screenshot":"Timeline_ganttBody_Timeline_row_0_REP2","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":285}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":897}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/report.md
new file mode 100644
index 00000000..e12c7f43
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/report.md
@@ -0,0 +1,508 @@
+
+# SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea()
+
+### undefined
+
+---
+
+There are 6 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+```
+
+
+
+```tsx
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/SelectionStory_selectedItemsSpan.png
+
+
+
+
+
+### Screenshot 2
+
+[Go to previous](#screenshot-1) | [Go to next](#screenshot-3)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/_LAP.png
+
+
+
+
+
+
+
+
+
+
+
+```tsx
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png
new file mode 100644
index 00000000..5776adb1
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png
new file mode 100644
index 00000000..bd1252a8
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1.png
new file mode 100644
index 00000000..66c66d79
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
new file mode 100644
index 00000000..3dd2c1d3
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png
new file mode 100644
index 00000000..a8408237
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png
new file mode 100644
index 00000000..cb900e2c
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png
new file mode 100644
index 00000000..f36276ce
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_small.png
new file mode 100644
index 00000000..5a36318b
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/recordedTest.json
new file mode 100644
index 00000000..6bee5105
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"SelectionStory_selectedItemsSpan","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":171},{"screenshot":"Timeline_ganttBody_Timeline_row_1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":179},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313},{"screenshot":"Timeline_ganttBody_Timeline_row_1_Timeline_item_3_REP1","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":313}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":2311}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/report.md
new file mode 100644
index 00000000..8e64fa2d
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/report.md
@@ -0,0 +1,457 @@
+
+# SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment()
+
+### undefined
+
+---
+
+There are 4 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+```
+
+
+
+```tsx
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+ [Go to next](#screenshot-2)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/SelectionStory_selectedItemsSpan.png
+
+
+
+
+
+```tsx
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+```
+
+
+
+
+### Screenshot 3
+
+[Go to previous](#screenshot-2) | [Go to next](#screenshot-4)
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment/Timeline_ganttBody_Timeline_row_1_Timeline_item_3.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan.png
new file mode 100644
index 00000000..98eb98a3
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan_small.png b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan_small.png
new file mode 100644
index 00000000..d6855188
Binary files /dev/null and b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan_small.png differ
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/recordedTest.json b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/recordedTest.json
new file mode 100644
index 00000000..ceb39096
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"SelectionStory_selectedItemsSpan","sourceFile":"SelectedItemsTestsAreDemo.tsx","sourceLine":163}],"sourceFiles":{"SelectedItemsTestsAreDemo.tsx":"import { Only, Scenario, ScenarioOptions, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Selection, selectionStoryTestIds } from \"../stories/contextMenuAndSelection/ContextMenuAndSelection.stories\";\nimport { someTasks } from \"../stories/sampleData\";\nimport Timeline, { timelineTestids as testids } from \"../../../src/timeline\";\nimport { rightClick } from \"./testUtils\";\n\n/**\n* @author Daniela Buzatu\n*/\nexport class SelectedItemsTestsAreDemo {\n async before() {\n render();\n }\n\n @Scenario(\"WHEN click on a segment, THEN only that segment is selected\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenClickOnASegment() {\n // WHEN left click, THEN element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click again on same element, THEN the same element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n await this.assertOnlyExpectedSegmentsAreSelected([2], true);\n \n // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)== \n // GIVEN nothing is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n // WHEN right click, THEN element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"));\n await this.assertOnlyExpectedSegmentsAreSelected([4], true);\n\n // WHEN right click again on another element, THEN the new element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // WHEN right click again on same element, THEN the same element is selected\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"));\n await this.assertOnlyExpectedSegmentsAreSelected([5], true);\n\n // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"), { ctrlKey: true });\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);\n \n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickAnotherSegment() {\n tad.cc(undefined);\n // WHEN left click again on another element, THEN the new element is selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n }\n\n @Scenario(\"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASegment() {\n // left click + CTRL on another element, THEN the new element is added to selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n tad.demoForEndUserHide();\n\n // WHEN left click + SHIFT on another element, THEN the new element is added to selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN left click + SHIFT on same element, THEN the element is removed from selection\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n // WHEN right click + CTRL on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + CTRL on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_4\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);\n\n // WHEN right click + SHIFT on another element, THEN the new element is added to selection\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // WHEN right click + SHIFT on same element, THEN the selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_5\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);\n\n // restore selection for the next scenario\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_0\"));\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLClickOnASelectedSegment() {\n // WHEN left click + CTRL on same element, THEN the element is removed from selection\n tad.cc(\"With CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n }\n\n @Scenario(\"WHEN CTRL + click outside segments, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true}) \n async whenCTRLClickOutside() {\n // When I click outside + Ctrl key, THEN selection doesn't change\n tad.cc(\"Click outside with CTRL Key pressed\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment\n await tad.demoForEndUserHide()\n // WHEN I click outside + Shift key, THEN selection doesn't change\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I right click outside + Ctrl key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // WHEN I click outside + Shift key, THEN selection doesn't change\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"), { shiftKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN click outside segments, THEN the selection becomes empty\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenClickOutside() {\n // WHEN left click on row, THEN no segment is selected\n tad.cc(\"Left click outside any segment\");\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // GIVEN a segment is selected\n tad.demoForEndUserHide();\n rightClick(tad.screenCapturing.getByTestId(testids.item + \"_2\"));\n // WHEN right click on row, THEN no segment is selected\n rightClick(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverTwoSegments() {\n await tad.showSpotlight({ message: \"I drag to select segment 0 and 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n \n @Scenario(\"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenDragASelectionRectangleOverAnotherSegment() {\n await tad.showSpotlight({ message: \"I drag to select segment 3 with left mouse button\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3);\n await this.assertOnlyExpectedSegmentsAreSelected([3]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // GIVEN nothing selected\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n\n await this.dragToSelect(0, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n\n await this.dragToSelect(1, 1, 3, 3, true);\n await this.assertOnlyExpectedSegmentsAreSelected([3], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnotherSegment() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0\", focusOnLastElementCaptured: false });\n await this.dragToSelect(0, 0, 0, 0, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {\n await tad.showSpotlight({ message: \"I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed\", focusOnLastElementCaptured: false });\n await this.dragToSelect(1, 1, 3, 3, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n\n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT\n tad.demoForEndUserHide();\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection\n await this.dragToSelect(0, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected \n await this.dragToSelect(1, 1, 3, 3, false, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // unselect everything\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected\n await this.dragToSelect(0, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);\n // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected\n await this.dragToSelect(1, 1, 3, 3, true, false, true);\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n\n // Select again the segment 0\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + \"_1\"));\n await this.dragToSelect(0, 0, 0, 0, false, true);\n\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\")\n @ScenarioOptions({linkWithNextScenario: true})\n async whenCTRLDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});\n await this.assertOnlyExpectedSegmentsAreSelected([0]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button + CTRL works the same\n tad.demoForEndUserHide();\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });\n await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });\n await this.assertOnlyExpectedSegmentsAreSelected([0], true);\n tad.demoForEndUserShow();\n }\n\n @Scenario(\"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty\") \n @ScenarioOptions({linkWithNextScenario: true}) \n async whenDragASelectionRectangleOverAnEmptyArea() {\n tad.cc(undefined);\n await tad.showSpotlight({ message: \"I drag to select outside any segments (using left mouse button)\", focusOnLastElementCaptured: false });\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);\n await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);\n tad.getObjectViaCheat(Timeline).dragEnd();\n await tad.showSpotlight({ message: \"No segment is selected\", focusOnLastElementCaptured: false });\n await this.assertOnlyExpectedSegmentsAreSelected([]);\n \n //=======HIDDEN TESTS (Not interesting for the user)==========\n // Using right mouse button works the same\n tad.demoForEndUserHide();\n // given a selected segment\n await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + \"_3\"));\n\n let row = tad.screenCapturing.getByTestId(testids.row + \"_0\");\n await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });\n await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });\n await tad.fireEventWaitable.mouseUp(row, { button: 2 });\n await this.assertOnlyExpectedSegmentsAreSelected([], true);\n tad.demoForEndUserShow();\n }\n\n ////////////////////////////////////////////////////////////////////////////////////////\n ////// Helper methods\n ////////////////////////////////////////////////////////////////////////////////////////\n\n async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {\n let startingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + startingRowIndex);\n let startingRowRect = startingRow.getBoundingClientRect();\n let endingRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + endingRowIndex);\n let endingRowRect = endingRow.getBoundingClientRect();\n const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + startingSegmentIndex).getBoundingClientRect();\n const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + \"_\" + endingSegmentIndex).getBoundingClientRect();\n const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;\n const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;\n\n // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting\n // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd. \n // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the \"cheat\" was needed\n // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events\n if (rightClick) {\n // There was a bug when having a large DPI of the screen e.g. 170\n // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,\n // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the\n // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem \n await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});\n } else {\n // 150 is the group offset\n // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow\n tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);\n await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);\n tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });\n }\n }\n\n async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {\n for (var i = 0; i < someTasks.length; i++) {\n const segment = tad.screenCapturing.getByTestId(testids.item + \"_\" + i);\n if (expectedSelectedSegments.indexOf(i) >= 0) {\n tad.cc(\"Segment \" + i + \" is selected (has resize anchors, brighter color and shadow effect)\");\n // await tad.assertWaitable.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.include(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n } else {\n tad.demoForEndUserHide();\n // await tad.assertWaitable.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n assert.notInclude(Array.from(segment.classList), \"rct9k-items-outer-selected\");\n !demoForEndUserHide && tad.demoForEndUserShow();\n }\n }\n\n assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(\", \"));\n }\n}"},"duration":531}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/report.md b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/report.md
new file mode 100644
index 00000000..62131f4b
--- /dev/null
+++ b/demo-app/public/recordedTests/SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/report.md
@@ -0,0 +1,388 @@
+
+# SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## SelectedItemsTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Only, Scenario, ScenarioOptions, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Selection, selectionStoryTestIds } from "../stories/contextMenuAndSelection/ContextMenuAndSelection.stories";
+/* 4*/import { someTasks } from "../stories/sampleData";
+/* 5*/import Timeline, { timelineTestids as testids } from "../../../src/timeline";
+/* 6*/import { rightClick } from "./testUtils";
+/* 7*/
+/* 8*//**
+/* 9*/* @author Daniela Buzatu
+/* 10*/*/
+/* 11*/export class SelectedItemsTestsAreDemo {
+/* 12*/ async before() {
+/* 13*/ render();
+/* 14*/ }
+/* 15*/
+/* 16*/ @Scenario("WHEN click on a segment, THEN only that segment is selected")
+/* 17*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 18*/ async whenClickOnASegment() {
+/* 19*/ // WHEN left click, THEN element is selected
+/* 20*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 21*/ await this.assertOnlyExpectedSegmentsAreSelected([2]);
+/* 22*/
+/* 23*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 24*/ tad.demoForEndUserHide();
+/* 25*/
+/* 26*/ // WHEN left click again on same element, THEN the same element is selected
+/* 27*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 28*/ await this.assertOnlyExpectedSegmentsAreSelected([2], true);
+/* 29*/
+/* 30*/ // ==Right click can be used also for selecting segments. It works the same as left click (except that right click on a selected segment doesn't change the selection)==
+/* 31*/ // GIVEN nothing is selected
+/* 32*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/* 33*/
+/* 34*/ // WHEN right click, THEN element is selected
+/* 35*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"));
+/* 36*/ await this.assertOnlyExpectedSegmentsAreSelected([4], true);
+/* 37*/
+/* 38*/ // WHEN right click again on another element, THEN the new element is selected
+/* 39*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 40*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 41*/
+/* 42*/ // WHEN right click again on same element, THEN the same element is selected
+/* 43*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"));
+/* 44*/ await this.assertOnlyExpectedSegmentsAreSelected([5], true);
+/* 45*/
+/* 46*/ // GIVEN many segments are selected, WHEN right click one of them THEN the selection doesn't change
+/* 47*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 48*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"), { ctrlKey: true });
+/* 49*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_1"));
+/* 50*/ await this.assertOnlyExpectedSegmentsAreSelected([1, 2], true);
+/* 51*/
+/* 52*/ // restore selection for the next scenario
+/* 53*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_2"));
+/* 54*/ tad.demoForEndUserShow();
+/* 55*/ }
+/* 56*/
+/* 57*/ @Scenario("WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)")
+/* 58*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 59*/ async whenClickAnotherSegment() {
+/* 60*/ tad.cc(undefined);
+/* 61*/ // WHEN left click again on another element, THEN the new element is selected
+/* 62*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/* 63*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/* 64*/ }
+/* 65*/
+/* 66*/ @Scenario("WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/* 67*/ @ScenarioOptions({linkWithNextScenario: true})
+/* 68*/ async whenCTRLClickOnASegment() {
+/* 69*/ // left click + CTRL on another element, THEN the new element is added to selection
+/* 70*/ tad.cc("With CTRL Key pressed");
+/* 71*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"), { ctrlKey: true });
+/* 72*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/* 73*/
+/* 74*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/* 75*/ tad.demoForEndUserHide();
+/* 76*/
+/* 77*/ // WHEN left click + SHIFT on another element, THEN the new element is added to selection
+/* 78*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 79*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 80*/
+/* 81*/ // WHEN left click + SHIFT on same element, THEN the element is removed from selection
+/* 82*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_4"), { shiftKey: true });
+/* 83*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/* 84*/
+/* 85*/ // WHEN right click + CTRL on another element, THEN the new element is added to selection
+/* 86*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 87*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 88*/
+/* 89*/ // WHEN right click + CTRL on same element, THEN the selection doesn't change
+/* 90*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_4"), { ctrlKey: true });
+/* 91*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4], true);
+/* 92*/
+/* 93*/ // WHEN right click + SHIFT on another element, THEN the new element is added to selection
+/* 94*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 95*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/* 96*/
+/* 97*/ // WHEN right click + SHIFT on same element, THEN the selection doesn't change
+/* 98*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_5"), { shiftKey: true });
+/* 99*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3, 4, 5], true);
+/*100*/
+/*101*/ // restore selection for the next scenario
+/*102*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_0"));
+/*103*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*104*/ tad.demoForEndUserShow();
+/*105*/ }
+/*106*/
+/*107*/ @Scenario("WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected")
+/*108*/ @ScenarioOptions({linkWithNextScenario: true})
+/*109*/ async whenCTRLClickOnASelectedSegment() {
+/*110*/ // WHEN left click + CTRL on same element, THEN the element is removed from selection
+/*111*/ tad.cc("With CTRL Key pressed");
+/*112*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"), { ctrlKey: true });
+/*113*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*114*/ }
+/*115*/
+/*116*/ @Scenario("WHEN CTRL + click outside segments, THEN the selection doesn't change")
+/*117*/ @ScenarioOptions({linkWithNextScenario: true})
+/*118*/ async whenCTRLClickOutside() {
+/*119*/ // When I click outside + Ctrl key, THEN selection doesn't change
+/*120*/ tad.cc("Click outside with CTRL Key pressed");
+/*121*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*122*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*123*/
+/*124*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*125*/ // Same as CLICK + CTRL outside any segment works: CLICK + SHIFT, RIGHT CLICK + CTRL, RIGHT CLICK + SHIFT outside any segment
+/*126*/ await tad.demoForEndUserHide()
+/*127*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*128*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*129*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*130*/
+/*131*/ // WHEN I right click outside + Ctrl key, THEN selection doesn't change
+/*132*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { ctrlKey: true });
+/*133*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*134*/
+/*135*/ // WHEN I click outside + Shift key, THEN selection doesn't change
+/*136*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"), { shiftKey: true });
+/*137*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*138*/ tad.demoForEndUserShow();
+/*139*/ }
+/*140*/
+/*141*/ @Scenario("WHEN click outside segments, THEN the selection becomes empty")
+/*142*/ @ScenarioOptions({linkWithNextScenario: true})
+/*143*/ async whenClickOutside() {
+/*144*/ // WHEN left click on row, THEN no segment is selected
+/*145*/ tad.cc("Left click outside any segment");
+/*146*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*147*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*148*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*149*/
+/*150*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*151*/ // GIVEN a segment is selected
+/*152*/ tad.demoForEndUserHide();
+/*153*/ rightClick(tad.screenCapturing.getByTestId(testids.item + "_2"));
+```
+
+
+
+```tsx
+/*154*/ // WHEN right click on row, THEN no segment is selected
+/*155*/ rightClick(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*156*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*157*/ tad.demoForEndUserShow();
+/*158*/ }
+/*159*/
+/*160*/ @Scenario("WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected")
+/*161*/ @ScenarioOptions({linkWithNextScenario: true})
+/*162*/ async whenDragASelectionRectangleOverTwoSegments() {
+/*163*/ await tad.showSpotlight({ message: "I drag to select segment 0 and 3 with left mouse button", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments/SelectionStory_selectedItemsSpan.png
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*164*/ await this.dragToSelect(0, 1, 3, 3);
+/*165*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*166*/ }
+/*167*/
+/*168*/ @Scenario("WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more")
+/*169*/ @ScenarioOptions({linkWithNextScenario: true})
+/*170*/ async whenDragASelectionRectangleOverAnotherSegment() {
+/*171*/ await tad.showSpotlight({ message: "I drag to select segment 3 with left mouse button", focusOnLastElementCaptured: false });
+/*172*/ await this.dragToSelect(1, 1, 3, 3);
+/*173*/ await this.assertOnlyExpectedSegmentsAreSelected([3]);
+/*174*/
+/*175*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*176*/ // Using right mouse button works the same
+/*177*/ tad.demoForEndUserHide();
+/*178*/ // GIVEN nothing selected
+/*179*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*180*/
+/*181*/ await this.dragToSelect(0, 1, 3, 3, true);
+/*182*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*183*/
+/*184*/ await this.dragToSelect(1, 1, 3, 3, true);
+/*185*/ await this.assertOnlyExpectedSegmentsAreSelected([3], true);
+/*186*/ tad.demoForEndUserShow();
+/*187*/ }
+/*188*/
+/*189*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected")
+/*190*/ @ScenarioOptions({linkWithNextScenario: true})
+/*191*/ async whenCTRLDragASelectionRectangleOverAnotherSegment() {
+/*192*/ tad.cc(undefined);
+/*193*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0", focusOnLastElementCaptured: false });
+/*194*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*195*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3]);
+/*196*/ }
+/*197*/
+/*198*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected")
+/*199*/ @ScenarioOptions({linkWithNextScenario: true})
+/*200*/ async whenCTRLDragASelectionRectangleOverAlreadySelectedSegment() {
+/*201*/ await tad.showSpotlight({ message: "I draw a rectangle containing segment 0 with LEFT mouse button and CTRL pressed", focusOnLastElementCaptured: false });
+/*202*/ await this.dragToSelect(1, 1, 3, 3, false, true);
+/*203*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*204*/
+/*205*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*206*/ // Same as LEFT button + CTRL works: LEFT + SHIFT, RIGHT + CTRL, RIGHT + SHIFT
+/*207*/ tad.demoForEndUserHide();
+/*208*/ // unselect everything
+/*209*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*210*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are added to selection
+/*211*/ await this.dragToSelect(0, 1, 3, 3, true, true);
+/*212*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*213*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and CTRL pressed, THEN segment 3 is unselected
+/*214*/ await this.dragToSelect(1, 1, 3, 3, true, true);
+/*215*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*216*/
+/*217*/ // unselect everything
+/*218*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*219*/ // WHEN I draw a rectangle containing segments 0, 3 with LEFT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*220*/ await this.dragToSelect(0, 1, 3, 3, false, false, true);
+/*221*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*222*/ // WHEN I draw a rectangle containing segment 3 with LEFT mouse button and SHIFT pressed, THEN segment 3 is unselected
+/*223*/ await this.dragToSelect(1, 1, 3, 3, false, false, true);
+/*224*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*225*/
+/*226*/ // unselect everything
+/*227*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*228*/ // WHEN I draw a rectangle containing segments 0, 3 with RIGHT mouse button and SHIFT pressed, THEN segments 0, 3 are selected
+/*229*/ await this.dragToSelect(0, 1, 3, 3, true, false, true);
+/*230*/ await this.assertOnlyExpectedSegmentsAreSelected([0, 3], true);
+/*231*/ // WHEN I draw a rectangle containing segment 3 with RIGHT mouse button and SHIFT pressed, , THEN segment 3 is unselected
+/*232*/ await this.dragToSelect(1, 1, 3, 3, true, false, true);
+/*233*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*234*/
+/*235*/ // Select again the segment 0
+/*236*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.row + "_1"));
+/*237*/ await this.dragToSelect(0, 0, 0, 0, false, true);
+/*238*/
+/*239*/ tad.demoForEndUserShow();
+/*240*/ }
+/*241*/
+/*242*/ @Scenario("WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change")
+/*243*/ @ScenarioOptions({linkWithNextScenario: true})
+/*244*/ async whenCTRLDragASelectionRectangleOverAnEmptyArea() {
+/*245*/ tad.cc(undefined);
+/*246*/ await tad.showSpotlight({ message: "WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change", focusOnLastElementCaptured: false });
+/*247*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*248*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*249*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*250*/ tad.getObjectViaCheat(Timeline).dragEnd({ctrlKey: true});
+/*251*/ await this.assertOnlyExpectedSegmentsAreSelected([0]);
+/*252*/
+/*253*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*254*/ // Using right mouse button + CTRL works the same
+/*255*/ tad.demoForEndUserHide();
+/*256*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*257*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2, ctrlKey: true });
+/*258*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10, ctrlKey: true });
+/*259*/ await tad.fireEventWaitable.mouseUp(row, { button: 2, ctrlKey: true });
+/*260*/ await this.assertOnlyExpectedSegmentsAreSelected([0], true);
+/*261*/ tad.demoForEndUserShow();
+/*262*/ }
+/*263*/
+/*264*/ @Scenario("WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty")
+/*265*/ @ScenarioOptions({linkWithNextScenario: true})
+/*266*/ async whenDragASelectionRectangleOverAnEmptyArea() {
+/*267*/ tad.cc(undefined);
+/*268*/ await tad.showSpotlight({ message: "I drag to select outside any segments (using left mouse button)", focusOnLastElementCaptured: false });
+/*269*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*270*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, 5);
+/*271*/ await tad.getObjectViaCheat(Timeline).dragMove(10, 10, 5);
+/*272*/ tad.getObjectViaCheat(Timeline).dragEnd();
+/*273*/ await tad.showSpotlight({ message: "No segment is selected", focusOnLastElementCaptured: false });
+/*274*/ await this.assertOnlyExpectedSegmentsAreSelected([]);
+/*275*/
+/*276*/ //=======HIDDEN TESTS (Not interesting for the user)==========
+/*277*/ // Using right mouse button works the same
+/*278*/ tad.demoForEndUserHide();
+/*279*/ // given a selected segment
+/*280*/ await tad.userEventWaitable.click(tad.screenCapturing.getByTestId(testids.item + "_3"));
+/*281*/
+/*282*/ let row = tad.screenCapturing.getByTestId(testids.row + "_0");
+/*283*/ await tad.fireEventWaitable.mouseDown(row, { clientX: row.getBoundingClientRect().x + 5, clientY: row.getBoundingClientRect().y + 5, button: 2 });
+/*284*/ await tad.fireEventWaitable.mouseMove(row, { clientX: 10, clientY: 10, pageX: 10 });
+/*285*/ await tad.fireEventWaitable.mouseUp(row, { button: 2 });
+/*286*/ await this.assertOnlyExpectedSegmentsAreSelected([], true);
+/*287*/ tad.demoForEndUserShow();
+/*288*/ }
+/*289*/
+/*290*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*291*/ ////// Helper methods
+/*292*/ ////////////////////////////////////////////////////////////////////////////////////////
+/*293*/
+/*294*/ async dragToSelect(startingRowIndex, endingRowIndex, startingSegmentIndex, endingSegmentIndex, rightClick?, ctrlKey = false, shiftKey = false) {
+/*295*/ let startingRow = tad.screenCapturing.getByTestId(testids.row + "_" + startingRowIndex);
+/*296*/ let startingRowRect = startingRow.getBoundingClientRect();
+/*297*/ let endingRow = tad.screenCapturing.getByTestId(testids.row + "_" + endingRowIndex);
+/*298*/ let endingRowRect = endingRow.getBoundingClientRect();
+/*299*/ const startingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + startingSegmentIndex).getBoundingClientRect();
+/*300*/ const endingSegmentRect = tad.screenCapturing.getByTestId(testids.item + "_" + endingSegmentIndex).getBoundingClientRect();
+/*301*/ const deltaX = endingSegmentRect.x + endingSegmentRect.width - startingSegmentRect.x;
+/*302*/ const deltaY = endingRowRect.y + endingRowRect.height - startingRowRect.y;
+/*303*/
+/*304*/ // The drag to select with right click is not a nativelly supported type of drag. So the timeline uses two implementations for supporting
+/*305*/ // 1. Drag to select on left click: based on interact js library triggered by native events dragStart, dragMove, dragEnd.
+/*306*/ // These events can not be tested using testing-library (we have tried using fireEvent.mouseDown, mouseOver, and mouseUp, but with no success). That's why the "cheat" was needed
+/*307*/ // 2. Drag to select on right click: triggered by mouseDown, mouseMove, mouseUp events
+/*308*/ if (rightClick) {
+/*309*/ // There was a bug when having a large DPI of the screen e.g. 170
+/*310*/ // Don't know why then the startingRowRect.y was not an integer (e.g. 256.789). Even if the TAD.drag() triggers the mouse event on this y floating value,
+/*311*/ // when interactjs library catched this event it sees the Y as an integer (e.g. 256). Because 256.789 was the exact begining of the
+/*312*/ // row, when timeline searches the row at position 256 it gets the previous row instead of the correct row. So applying Math.ceil fixed the problem
+/*313*/ await tad.drag(startingRow, {from: {x: startingSegmentRect.x, y: Math.ceil(startingRowRect.y)}, to: {x: endingSegmentRect.x + endingSegmentRect.width, y: endingRowRect.y + endingRowRect.height - 5}, options: {button: 2, ctrlKey: ctrlKey, shiftKey: shiftKey}});
+/*314*/ } else {
+/*315*/ // 150 is the group offset
+/*316*/ // we needed to subtract -5 because else the selection rectangle (that snapps to row) will get till the endingRow + 1, instead endingRow
+/*317*/ tad.getObjectViaCheat(Timeline).dragStart(startingRow, startingSegmentRect.x - 150);
+/*318*/ await tad.getObjectViaCheat(Timeline).dragMove(deltaX, deltaY - 5, 5);
+/*319*/ tad.getObjectViaCheat(Timeline).dragEnd({ ctrlKey: ctrlKey, shiftKey: shiftKey });
+/*320*/ }
+/*321*/ }
+/*322*/
+/*323*/ async assertOnlyExpectedSegmentsAreSelected(expectedSelectedSegments: number[], demoForEndUserHide?) {
+/*324*/ for (var i = 0; i < someTasks.length; i++) {
+/*325*/ const segment = tad.screenCapturing.getByTestId(testids.item + "_" + i);
+/*326*/ if (expectedSelectedSegments.indexOf(i) >= 0) {
+/*327*/ tad.cc("Segment " + i + " is selected (has resize anchors, brighter color and shadow effect)");
+/*328*/ // await tad.assertWaitable.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*329*/ assert.include(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*330*/ } else {
+/*331*/ tad.demoForEndUserHide();
+/*332*/ // await tad.assertWaitable.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*333*/ assert.notInclude(Array.from(segment.classList), "rct9k-items-outer-selected");
+/*334*/ !demoForEndUserHide && tad.demoForEndUserShow();
+/*335*/ }
+/*336*/ }
+/*337*/
+/*338*/ assert.equal(tad.screenCapturing.getByTestId(selectionStoryTestIds.selectedItemsSpan).textContent, expectedSelectedSegments.sort().join(", "));
+/*339*/ }
+/*340*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0.png b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0.png
new file mode 100644
index 00000000..d4d067a3
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0_small.png b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0_small.png
new file mode 100644
index 00000000..59690e93
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0_small.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/recordedTest.json b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/recordedTest.json
new file mode 100644
index 00000000..13c46f25
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Table_row_0","sourceFile":"TableTestsAreDemo.tsx","sourceLine":29}],"sourceFiles":{"TableTestsAreDemo.tsx":"import { Scenario, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Table } from \"fixed-data-table-2\";\nimport { ProvidingCustomTable } from \"../stories/table/Table.stories\";\nimport { DEMO_TABLE_WIDTH, tableTestIds } from \"../stories/table/TableScenarios\";\nimport { TABLE_OFFSET, timelineTestids as testids } from \"../../../src/timeline\";\n\nexport class TableTestsAreDemo {\n async before() {\n render();\n // When pressing run the second time the state of the scrollbars are not reset\n // I thought that render() should reset its state, but it doesn't.\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});\n // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position\n // Maybe a general mechanism of test sate reset is needed\n }\n \n @Scenario(\"Both table and gantt diagram have same rows height\")\n async bothTableAndGanttHaveSameRowHeight() {\n // Nu le putem verifica pe toate caci gridul este virtualizat\n for (var i = 0; i < 5; i++) {\n let ganttRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + i);\n let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + \"_\" + i);\n if (i < 4) { \n tad.cc(\"Table row \" + (i + 1) + \" and gantt row \" + (i + 1) + \" have same height\");\n } else {\n tad.cc(\"And so on... \");\n }\n await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);\n }\n }\n\n @Scenario(\"When scrolling in gantt the table is scrolled\")\n async whenScrollInGanttThenTableIsScrolled() {\n // We don't focus on last element captured because its height occupies the entire page\n // And the message appears under the gantt and is hidded by the scroll mechanism \n await tad.showSpotlight({ message: \"Gantt is scrolled => Table is scrolled accordingly\", focusOnLastElementCaptured: false });\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});\n \n // This is needed in order for the scroll handler to be triggerd before the verification \n await new Promise(r => setTimeout(r, 10));\n\n // We \"cheated\" here because\n // There is no strait forward way to see the scroll position by looking at the html elements\n // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d) \n // the rows. \n // We could have looked at the position of the first row but it was offseted with the\n // height of the header in order to appear right under it. So we should have placed a data-testid on the header also\n // but being in a third library component this was not simple to implement\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);\n }\n\n @Scenario(\"When scrolling in table the gantt is scrolled\")\n async whenScrollInTableThenGanttIsScrolled() {\n await tad.showSpotlight({ message: \"Table is scrolled => Gantt is scrolled accordingly\", focusOnLastElementCaptured: false });\n (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);\n assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);\n }\n\n @Scenario(\"When drag the split pane the table is resized accordingly\")\n async whenDragTheSplitPaneTheTableIsResizedAccordingly() {\n tad.cc(\"Split pane resizer is dragged\");\n await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);\n }\n}"},"duration":52,"error":"Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)\n\t at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/report.md b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/report.md
new file mode 100644
index 00000000..026b1c91
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/report.md
@@ -0,0 +1,124 @@
+
+# TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+Error: Uncaught TypeError: Cannot read properties of null (reading 'recomputeGridSize') (http://localhost:3000/@fs/home/poweruser/git/react-timeline-10000/src/timeline.js:433)
+ at _global.onerror [fn(new Error(err + ' (' + url + ':' + line + ')'));] (http://localhost:3000/node_modules/mocha/browser-entry.js:75:10)
+```
+
+---
+
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## TableTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Scenario, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Table } from "fixed-data-table-2";
+/* 4*/import { ProvidingCustomTable } from "../stories/table/Table.stories";
+/* 5*/import { DEMO_TABLE_WIDTH, tableTestIds } from "../stories/table/TableScenarios";
+/* 6*/import { TABLE_OFFSET, timelineTestids as testids } from "../../../src/timeline";
+/* 7*/
+/* 8*/export class TableTestsAreDemo {
+/* 9*/ async before() {
+/*10*/ render();
+/*11*/ // When pressing run the second time the state of the scrollbars are not reset
+/*12*/ // I thought that render() should reset its state, but it doesn't.
+/*13*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});
+/*14*/ // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position
+/*15*/ // Maybe a general mechanism of test sate reset is needed
+/*16*/ }
+/*17*/
+/*18*/ @Scenario("Both table and gantt diagram have same rows height")
+/*19*/ async bothTableAndGanttHaveSameRowHeight() {
+```
+
+
+
+```tsx
+/*20*/ // Nu le putem verifica pe toate caci gridul este virtualizat
+/*21*/ for (var i = 0; i < 5; i++) {
+/*22*/ let ganttRow = tad.screenCapturing.getByTestId(testids.row + "_" + i);
+/*23*/ let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + "_" + i);
+/*24*/ if (i < 4) {
+/*25*/ tad.cc("Table row " + (i + 1) + " and gantt row " + (i + 1) + " have same height");
+/*26*/ } else {
+/*27*/ tad.cc("And so on... ");
+/*28*/ }
+/*29*/ await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight/Table_row_0.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*30*/ }
+/*31*/ }
+/*32*/
+/*33*/ @Scenario("When scrolling in gantt the table is scrolled")
+/*34*/ async whenScrollInGanttThenTableIsScrolled() {
+/*35*/ // We don't focus on last element captured because its height occupies the entire page
+/*36*/ // And the message appears under the gantt and is hidded by the scroll mechanism
+/*37*/ await tad.showSpotlight({ message: "Gantt is scrolled => Table is scrolled accordingly", focusOnLastElementCaptured: false });
+/*38*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});
+/*39*/
+/*40*/ // This is needed in order for the scroll handler to be triggerd before the verification
+/*41*/ await new Promise(r => setTimeout(r, 10));
+/*42*/
+/*43*/ // We "cheated" here because
+/*44*/ // There is no strait forward way to see the scroll position by looking at the html elements
+/*45*/ // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d)
+/*46*/ // the rows.
+/*47*/ // We could have looked at the position of the first row but it was offseted with the
+/*48*/ // height of the header in order to appear right under it. So we should have placed a data-testid on the header also
+/*49*/ // but being in a third library component this was not simple to implement
+/*50*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);
+/*51*/ }
+/*52*/
+/*53*/ @Scenario("When scrolling in table the gantt is scrolled")
+/*54*/ async whenScrollInTableThenGanttIsScrolled() {
+/*55*/ await tad.showSpotlight({ message: "Table is scrolled => Gantt is scrolled accordingly", focusOnLastElementCaptured: false });
+/*56*/ (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);
+/*57*/ assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);
+/*58*/ }
+/*59*/
+/*60*/ @Scenario("When drag the split pane the table is resized accordingly")
+/*61*/ async whenDragTheSplitPaneTheTableIsResizedAccordingly() {
+/*62*/ tad.cc("Split pane resizer is dragged");
+/*63*/ await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});
+/*64*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);
+/*65*/ }
+/*66*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer.png
new file mode 100644
index 00000000..e5e3cf71
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer_small.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer_small.png
new file mode 100644
index 00000000..0c17f381
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer_small.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/recordedTest.json b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/recordedTest.json
new file mode 100644
index 00000000..9b68372e
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Timeline_splitPaneResizer","sourceFile":"TableTestsAreDemo.tsx","sourceLine":63}],"sourceFiles":{"TableTestsAreDemo.tsx":"import { Scenario, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Table } from \"fixed-data-table-2\";\nimport { ProvidingCustomTable } from \"../stories/table/Table.stories\";\nimport { DEMO_TABLE_WIDTH, tableTestIds } from \"../stories/table/TableScenarios\";\nimport { TABLE_OFFSET, timelineTestids as testids } from \"../../../src/timeline\";\n\nexport class TableTestsAreDemo {\n async before() {\n render();\n // When pressing run the second time the state of the scrollbars are not reset\n // I thought that render() should reset its state, but it doesn't.\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});\n // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position\n // Maybe a general mechanism of test sate reset is needed\n }\n \n @Scenario(\"Both table and gantt diagram have same rows height\")\n async bothTableAndGanttHaveSameRowHeight() {\n // Nu le putem verifica pe toate caci gridul este virtualizat\n for (var i = 0; i < 5; i++) {\n let ganttRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + i);\n let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + \"_\" + i);\n if (i < 4) { \n tad.cc(\"Table row \" + (i + 1) + \" and gantt row \" + (i + 1) + \" have same height\");\n } else {\n tad.cc(\"And so on... \");\n }\n await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);\n }\n }\n\n @Scenario(\"When scrolling in gantt the table is scrolled\")\n async whenScrollInGanttThenTableIsScrolled() {\n // We don't focus on last element captured because its height occupies the entire page\n // And the message appears under the gantt and is hidded by the scroll mechanism \n await tad.showSpotlight({ message: \"Gantt is scrolled => Table is scrolled accordingly\", focusOnLastElementCaptured: false });\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});\n \n // This is needed in order for the scroll handler to be triggerd before the verification \n await new Promise(r => setTimeout(r, 10));\n\n // We \"cheated\" here because\n // There is no strait forward way to see the scroll position by looking at the html elements\n // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d) \n // the rows. \n // We could have looked at the position of the first row but it was offseted with the\n // height of the header in order to appear right under it. So we should have placed a data-testid on the header also\n // but being in a third library component this was not simple to implement\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);\n }\n\n @Scenario(\"When scrolling in table the gantt is scrolled\")\n async whenScrollInTableThenGanttIsScrolled() {\n await tad.showSpotlight({ message: \"Table is scrolled => Gantt is scrolled accordingly\", focusOnLastElementCaptured: false });\n (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);\n assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);\n }\n\n @Scenario(\"When drag the split pane the table is resized accordingly\")\n async whenDragTheSplitPaneTheTableIsResizedAccordingly() {\n tad.cc(\"Split pane resizer is dragged\");\n await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);\n }\n}"},"duration":1320,"error":"AssertionError: expected 725 to equal 425\n\t at TableTestsAreDemo.whenDragTheSplitPaneTheTableIsResizedAccordingly [assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);] (http://localhost:3000TableTestsAreDemo.tsx:64:16)"}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/report.md b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/report.md
new file mode 100644
index 00000000..564bbd35
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/report.md
@@ -0,0 +1,124 @@
+
+# TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly()
+
+### undefined
+
+---
+
+## The following error was caught while running the test:
+
+```
+AssertionError: expected 725 to equal 425
+ at TableTestsAreDemo.whenDragTheSplitPaneTheTableIsResizedAccordingly [assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);] (http://localhost:3000TableTestsAreDemo.tsx:64:16)
+```
+
+---
+
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## TableTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Scenario, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Table } from "fixed-data-table-2";
+/* 4*/import { ProvidingCustomTable } from "../stories/table/Table.stories";
+/* 5*/import { DEMO_TABLE_WIDTH, tableTestIds } from "../stories/table/TableScenarios";
+/* 6*/import { TABLE_OFFSET, timelineTestids as testids } from "../../../src/timeline";
+/* 7*/
+/* 8*/export class TableTestsAreDemo {
+/* 9*/ async before() {
+/*10*/ render();
+/*11*/ // When pressing run the second time the state of the scrollbars are not reset
+/*12*/ // I thought that render() should reset its state, but it doesn't.
+/*13*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});
+/*14*/ // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position
+/*15*/ // Maybe a general mechanism of test sate reset is needed
+/*16*/ }
+/*17*/
+/*18*/ @Scenario("Both table and gantt diagram have same rows height")
+/*19*/ async bothTableAndGanttHaveSameRowHeight() {
+/*20*/ // Nu le putem verifica pe toate caci gridul este virtualizat
+/*21*/ for (var i = 0; i < 5; i++) {
+/*22*/ let ganttRow = tad.screenCapturing.getByTestId(testids.row + "_" + i);
+/*23*/ let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + "_" + i);
+/*24*/ if (i < 4) {
+/*25*/ tad.cc("Table row " + (i + 1) + " and gantt row " + (i + 1) + " have same height");
+/*26*/ } else {
+/*27*/ tad.cc("And so on... ");
+/*28*/ }
+/*29*/ await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);
+/*30*/ }
+/*31*/ }
+/*32*/
+/*33*/ @Scenario("When scrolling in gantt the table is scrolled")
+/*34*/ async whenScrollInGanttThenTableIsScrolled() {
+/*35*/ // We don't focus on last element captured because its height occupies the entire page
+/*36*/ // And the message appears under the gantt and is hidded by the scroll mechanism
+/*37*/ await tad.showSpotlight({ message: "Gantt is scrolled => Table is scrolled accordingly", focusOnLastElementCaptured: false });
+/*38*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});
+/*39*/
+/*40*/ // This is needed in order for the scroll handler to be triggerd before the verification
+/*41*/ await new Promise(r => setTimeout(r, 10));
+/*42*/
+/*43*/ // We "cheated" here because
+/*44*/ // There is no strait forward way to see the scroll position by looking at the html elements
+/*45*/ // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d)
+/*46*/ // the rows.
+/*47*/ // We could have looked at the position of the first row but it was offseted with the
+/*48*/ // height of the header in order to appear right under it. So we should have placed a data-testid on the header also
+/*49*/ // but being in a third library component this was not simple to implement
+/*50*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);
+/*51*/ }
+/*52*/
+/*53*/ @Scenario("When scrolling in table the gantt is scrolled")
+```
+
+
+
+```tsx
+/*54*/ async whenScrollInTableThenGanttIsScrolled() {
+/*55*/ await tad.showSpotlight({ message: "Table is scrolled => Gantt is scrolled accordingly", focusOnLastElementCaptured: false });
+/*56*/ (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);
+/*57*/ assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);
+/*58*/ }
+/*59*/
+/*60*/ @Scenario("When drag the split pane the table is resized accordingly")
+/*61*/ async whenDragTheSplitPaneTheTableIsResizedAccordingly() {
+/*62*/ tad.cc("Split pane resizer is dragged");
+/*63*/ await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly/Timeline_splitPaneResizer.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*64*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);
+/*65*/ }
+/*66*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0.png
new file mode 100644
index 00000000..af8da8e0
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0_small.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0_small.png
new file mode 100644
index 00000000..18ea2202
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0_small.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/recordedTest.json b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/recordedTest.json
new file mode 100644
index 00000000..ecf39cb1
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"Table_row_0","sourceFile":"TableTestsAreDemo.tsx","sourceLine":37}],"sourceFiles":{"TableTestsAreDemo.tsx":"import { Scenario, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Table } from \"fixed-data-table-2\";\nimport { ProvidingCustomTable } from \"../stories/table/Table.stories\";\nimport { DEMO_TABLE_WIDTH, tableTestIds } from \"../stories/table/TableScenarios\";\nimport { TABLE_OFFSET, timelineTestids as testids } from \"../../../src/timeline\";\n\nexport class TableTestsAreDemo {\n async before() {\n render();\n // When pressing run the second time the state of the scrollbars are not reset\n // I thought that render() should reset its state, but it doesn't.\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});\n // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position\n // Maybe a general mechanism of test sate reset is needed\n }\n \n @Scenario(\"Both table and gantt diagram have same rows height\")\n async bothTableAndGanttHaveSameRowHeight() {\n // Nu le putem verifica pe toate caci gridul este virtualizat\n for (var i = 0; i < 5; i++) {\n let ganttRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + i);\n let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + \"_\" + i);\n if (i < 4) { \n tad.cc(\"Table row \" + (i + 1) + \" and gantt row \" + (i + 1) + \" have same height\");\n } else {\n tad.cc(\"And so on... \");\n }\n await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);\n }\n }\n\n @Scenario(\"When scrolling in gantt the table is scrolled\")\n async whenScrollInGanttThenTableIsScrolled() {\n // We don't focus on last element captured because its height occupies the entire page\n // And the message appears under the gantt and is hidded by the scroll mechanism \n await tad.showSpotlight({ message: \"Gantt is scrolled => Table is scrolled accordingly\", focusOnLastElementCaptured: false });\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});\n \n // This is needed in order for the scroll handler to be triggerd before the verification \n await new Promise(r => setTimeout(r, 10));\n\n // We \"cheated\" here because\n // There is no strait forward way to see the scroll position by looking at the html elements\n // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d) \n // the rows. \n // We could have looked at the position of the first row but it was offseted with the\n // height of the header in order to appear right under it. So we should have placed a data-testid on the header also\n // but being in a third library component this was not simple to implement\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);\n }\n\n @Scenario(\"When scrolling in table the gantt is scrolled\")\n async whenScrollInTableThenGanttIsScrolled() {\n await tad.showSpotlight({ message: \"Table is scrolled => Gantt is scrolled accordingly\", focusOnLastElementCaptured: false });\n (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);\n assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);\n }\n\n @Scenario(\"When drag the split pane the table is resized accordingly\")\n async whenDragTheSplitPaneTheTableIsResizedAccordingly() {\n tad.cc(\"Split pane resizer is dragged\");\n await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);\n }\n}"},"duration":212}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/report.md b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/report.md
new file mode 100644
index 00000000..15387d45
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/report.md
@@ -0,0 +1,114 @@
+
+# TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## TableTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Scenario, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Table } from "fixed-data-table-2";
+/* 4*/import { ProvidingCustomTable } from "../stories/table/Table.stories";
+/* 5*/import { DEMO_TABLE_WIDTH, tableTestIds } from "../stories/table/TableScenarios";
+/* 6*/import { TABLE_OFFSET, timelineTestids as testids } from "../../../src/timeline";
+/* 7*/
+/* 8*/export class TableTestsAreDemo {
+/* 9*/ async before() {
+/*10*/ render();
+/*11*/ // When pressing run the second time the state of the scrollbars are not reset
+/*12*/ // I thought that render() should reset its state, but it doesn't.
+/*13*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});
+/*14*/ // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position
+/*15*/ // Maybe a general mechanism of test sate reset is needed
+/*16*/ }
+/*17*/
+/*18*/ @Scenario("Both table and gantt diagram have same rows height")
+/*19*/ async bothTableAndGanttHaveSameRowHeight() {
+/*20*/ // Nu le putem verifica pe toate caci gridul este virtualizat
+/*21*/ for (var i = 0; i < 5; i++) {
+/*22*/ let ganttRow = tad.screenCapturing.getByTestId(testids.row + "_" + i);
+/*23*/ let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + "_" + i);
+/*24*/ if (i < 4) {
+/*25*/ tad.cc("Table row " + (i + 1) + " and gantt row " + (i + 1) + " have same height");
+/*26*/ } else {
+/*27*/ tad.cc("And so on... ");
+```
+
+
+
+```tsx
+/*28*/ }
+/*29*/ await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);
+/*30*/ }
+/*31*/ }
+/*32*/
+/*33*/ @Scenario("When scrolling in gantt the table is scrolled")
+/*34*/ async whenScrollInGanttThenTableIsScrolled() {
+/*35*/ // We don't focus on last element captured because its height occupies the entire page
+/*36*/ // And the message appears under the gantt and is hidded by the scroll mechanism
+/*37*/ await tad.showSpotlight({ message: "Gantt is scrolled => Table is scrolled accordingly", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled/Table_row_0.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*38*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});
+/*39*/
+/*40*/ // This is needed in order for the scroll handler to be triggerd before the verification
+/*41*/ await new Promise(r => setTimeout(r, 10));
+/*42*/
+/*43*/ // We "cheated" here because
+/*44*/ // There is no strait forward way to see the scroll position by looking at the html elements
+/*45*/ // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d)
+/*46*/ // the rows.
+/*47*/ // We could have looked at the position of the first row but it was offseted with the
+/*48*/ // height of the header in order to appear right under it. So we should have placed a data-testid on the header also
+/*49*/ // but being in a third library component this was not simple to implement
+/*50*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);
+/*51*/ }
+/*52*/
+/*53*/ @Scenario("When scrolling in table the gantt is scrolled")
+/*54*/ async whenScrollInTableThenGanttIsScrolled() {
+/*55*/ await tad.showSpotlight({ message: "Table is scrolled => Gantt is scrolled accordingly", focusOnLastElementCaptured: false });
+/*56*/ (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);
+/*57*/ assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);
+/*58*/ }
+/*59*/
+/*60*/ @Scenario("When drag the split pane the table is resized accordingly")
+/*61*/ async whenDragTheSplitPaneTheTableIsResizedAccordingly() {
+/*62*/ tad.cc("Split pane resizer is dragged");
+/*63*/ await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});
+/*64*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);
+/*65*/ }
+/*66*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP.png
new file mode 100644
index 00000000..28618fd0
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP_small.png b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP_small.png
new file mode 100644
index 00000000..28618fd0
Binary files /dev/null and b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP_small.png differ
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/recordedTest.json b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/recordedTest.json
new file mode 100644
index 00000000..cee6521c
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/recordedTest.json
@@ -0,0 +1 @@
+{"slides":[{"screenshot":"_LAP","sourceFile":"TableTestsAreDemo.tsx","sourceLine":55}],"sourceFiles":{"TableTestsAreDemo.tsx":"import { Scenario, render, tad } from \"@famiprog-foundation/tests-are-demo\";\nimport { assert } from \"chai\";\nimport { Table } from \"fixed-data-table-2\";\nimport { ProvidingCustomTable } from \"../stories/table/Table.stories\";\nimport { DEMO_TABLE_WIDTH, tableTestIds } from \"../stories/table/TableScenarios\";\nimport { TABLE_OFFSET, timelineTestids as testids } from \"../../../src/timeline\";\n\nexport class TableTestsAreDemo {\n async before() {\n render();\n // When pressing run the second time the state of the scrollbars are not reset\n // I thought that render() should reset its state, but it doesn't.\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});\n // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position\n // Maybe a general mechanism of test sate reset is needed\n }\n \n @Scenario(\"Both table and gantt diagram have same rows height\")\n async bothTableAndGanttHaveSameRowHeight() {\n // Nu le putem verifica pe toate caci gridul este virtualizat\n for (var i = 0; i < 5; i++) {\n let ganttRow = tad.screenCapturing.getByTestId(testids.row + \"_\" + i);\n let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + \"_\" + i);\n if (i < 4) { \n tad.cc(\"Table row \" + (i + 1) + \" and gantt row \" + (i + 1) + \" have same height\");\n } else {\n tad.cc(\"And so on... \");\n }\n await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);\n }\n }\n\n @Scenario(\"When scrolling in gantt the table is scrolled\")\n async whenScrollInGanttThenTableIsScrolled() {\n // We don't focus on last element captured because its height occupies the entire page\n // And the message appears under the gantt and is hidded by the scroll mechanism \n await tad.showSpotlight({ message: \"Gantt is scrolled => Table is scrolled accordingly\", focusOnLastElementCaptured: false });\n tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});\n \n // This is needed in order for the scroll handler to be triggerd before the verification \n await new Promise(r => setTimeout(r, 10));\n\n // We \"cheated\" here because\n // There is no strait forward way to see the scroll position by looking at the html elements\n // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d) \n // the rows. \n // We could have looked at the position of the first row but it was offseted with the\n // height of the header in order to appear right under it. So we should have placed a data-testid on the header also\n // but being in a third library component this was not simple to implement\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);\n }\n\n @Scenario(\"When scrolling in table the gantt is scrolled\")\n async whenScrollInTableThenGanttIsScrolled() {\n await tad.showSpotlight({ message: \"Table is scrolled => Gantt is scrolled accordingly\", focusOnLastElementCaptured: false });\n (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);\n assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);\n }\n\n @Scenario(\"When drag the split pane the table is resized accordingly\")\n async whenDragTheSplitPaneTheTableIsResizedAccordingly() {\n tad.cc(\"Split pane resizer is dragged\");\n await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});\n assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);\n }\n}"},"duration":192}
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/report.md b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/report.md
new file mode 100644
index 00000000..4dbe0afd
--- /dev/null
+++ b/demo-app/public/recordedTests/TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/report.md
@@ -0,0 +1,114 @@
+
+# TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled()
+
+### undefined
+
+---
+
+There are 1 screenshots. [Go to first](#screenshot-1)
+
+## TableTestsAreDemo.tsx
+
+Click to expand the hidden lines of code
+
+```tsx
+/* 1*/import { Scenario, render, tad } from "@famiprog-foundation/tests-are-demo";
+/* 2*/import { assert } from "chai";
+/* 3*/import { Table } from "fixed-data-table-2";
+/* 4*/import { ProvidingCustomTable } from "../stories/table/Table.stories";
+/* 5*/import { DEMO_TABLE_WIDTH, tableTestIds } from "../stories/table/TableScenarios";
+/* 6*/import { TABLE_OFFSET, timelineTestids as testids } from "../../../src/timeline";
+/* 7*/
+/* 8*/export class TableTestsAreDemo {
+/* 9*/ async before() {
+/*10*/ render();
+/*11*/ // When pressing run the second time the state of the scrollbars are not reset
+/*12*/ // I thought that render() should reset its state, but it doesn't.
+/*13*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:0});
+/*14*/ // TODO DB By running the tests second time, the SplitPane test fails because we need to reset its position
+/*15*/ // Maybe a general mechanism of test sate reset is needed
+/*16*/ }
+/*17*/
+/*18*/ @Scenario("Both table and gantt diagram have same rows height")
+/*19*/ async bothTableAndGanttHaveSameRowHeight() {
+/*20*/ // Nu le putem verifica pe toate caci gridul este virtualizat
+/*21*/ for (var i = 0; i < 5; i++) {
+/*22*/ let ganttRow = tad.screenCapturing.getByTestId(testids.row + "_" + i);
+/*23*/ let tableCell = tad.screenCapturing.getByTestId(tableTestIds.row + "_" + i);
+/*24*/ if (i < 4) {
+/*25*/ tad.cc("Table row " + (i + 1) + " and gantt row " + (i + 1) + " have same height");
+/*26*/ } else {
+/*27*/ tad.cc("And so on... ");
+/*28*/ }
+/*29*/ await tad.assertWaitable.equal(ganttRow.offsetHeight, (tableCell as HTMLElement).offsetHeight);
+/*30*/ }
+/*31*/ }
+/*32*/
+/*33*/ @Scenario("When scrolling in gantt the table is scrolled")
+/*34*/ async whenScrollInGanttThenTableIsScrolled() {
+/*35*/ // We don't focus on last element captured because its height occupies the entire page
+/*36*/ // And the message appears under the gantt and is hidded by the scroll mechanism
+/*37*/ await tad.showSpotlight({ message: "Gantt is scrolled => Table is scrolled accordingly", focusOnLastElementCaptured: false });
+/*38*/ tad.screenCapturing.getByTestId(testids.ganttBody).scroll({top:100});
+/*39*/
+/*40*/ // This is needed in order for the scroll handler to be triggerd before the verification
+/*41*/ await new Promise(r => setTimeout(r, 10));
+/*42*/
+/*43*/ // We "cheated" here because
+/*44*/ // There is no strait forward way to see the scroll position by looking at the html elements
+/*45*/ // Because the table has a special type of scrolling mechanism by absolute positioning (with translate3d)
+```
+
+
+
+```tsx
+/*46*/ // the rows.
+/*47*/ // We could have looked at the position of the first row but it was offseted with the
+/*48*/ // height of the header in order to appear right under it. So we should have placed a data-testid on the header also
+/*49*/ // but being in a third library component this was not simple to implement
+/*50*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.scrollTop, 100);
+/*51*/ }
+/*52*/
+/*53*/ @Scenario("When scrolling in table the gantt is scrolled")
+/*54*/ async whenScrollInTableThenGanttIsScrolled() {
+/*55*/ await tad.showSpotlight({ message: "Table is scrolled => Gantt is scrolled accordingly", focusOnLastElementCaptured: false });
+```
+
+
+
+
+### Screenshot 1
+
+
+
+Click to expand full image
+
+TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled/_LAP.png
+
+
+
+
+
+
+
+
+
+
+
+Click to expand the hidden lines of code
+
+```tsx
+/*56*/ (tad.getObjectViaCheat(Table) as Table).scrollActions.scrollToY(300);
+/*57*/ assert.equal(tad.screenCapturing.getByTestId(testids.ganttBody).scrollTop, 300);
+/*58*/ }
+/*59*/
+/*60*/ @Scenario("When drag the split pane the table is resized accordingly")
+/*61*/ async whenDragTheSplitPaneTheTableIsResizedAccordingly() {
+/*62*/ tad.cc("Split pane resizer is dragged");
+/*63*/ await tad.drag(tad.screenCapturing.getByTestId(testids.splitPaneResizer), { delta: { x: 150, y: 0 }});
+/*64*/ assert.equal((tad.getObjectViaCheat(Table) as Table).props.width, DEMO_TABLE_WIDTH + TABLE_OFFSET + 150);
+/*65*/ }
+/*66*/}
+```
+
+
diff --git a/demo-app/public/recordedTests/recordedTestsIndex.json b/demo-app/public/recordedTests/recordedTestsIndex.json
new file mode 100644
index 00000000..bf37837a
--- /dev/null
+++ b/demo-app/public/recordedTests/recordedTestsIndex.json
@@ -0,0 +1 @@
+["DragToCreateTestsAreDemo/whenClickMenuButton","DragToCreateTestsAreDemo/whenClickAddMenuEntry","DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickCancel","DragToCreateTestsAreDemo/givenDragToCreateModeWhenClickAndDrag","DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenRightClick","DragToCreateTestsAreDemo/givenDragToCreateModeInProgressWhenMouseUp","DragToCreateTestsAreDemo/whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot","SelectedItemsTestsAreDemo/whenClickOnASegment","SelectedItemsTestsAreDemo/whenClickAnotherSegment","SelectedItemsTestsAreDemo/whenCTRLClickOnASegment","SelectedItemsTestsAreDemo/whenCTRLClickOnASelectedSegment","SelectedItemsTestsAreDemo/whenCTRLClickOutside","SelectedItemsTestsAreDemo/whenClickOutside","SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverTwoSegments","SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnotherSegment","SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnotherSegment","SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAlreadySelectedSegment","SelectedItemsTestsAreDemo/whenCTRLDragASelectionRectangleOverAnEmptyArea","SelectedItemsTestsAreDemo/whenDragASelectionRectangleOverAnEmptyArea","ContextMenuTestsAreDemo/whenRightClickOnARow","ContextMenuTestsAreDemo/whenClickAnAction","ContextMenuTestsAreDemo/whenRightClickOnASegment","ContextMenuTestsAreDemo/whenCTRLRightClickOnAnotherSegment","ContextMenuTestsAreDemo/whenClickTheHamburgerButton","TableTestsAreDemo/bothTableAndGanttHaveSameRowHeight","TableTestsAreDemo/whenScrollInGanttThenTableIsScrolled","TableTestsAreDemo/whenScrollInTableThenGanttIsScrolled","TableTestsAreDemo/whenDragTheSplitPaneTheTableIsResizedAccordingly","DynamicConfigurationTestsAreDemo/whenStartEndDateChanges","BackgroundLayersTestsAreDemo/highlightedIntervalsAreDisplayed"]
\ No newline at end of file
diff --git a/demo-app/public/recordedTests/testClassDescriptors.json b/demo-app/public/recordedTests/testClassDescriptors.json
new file mode 100644
index 00000000..e1a07265
--- /dev/null
+++ b/demo-app/public/recordedTests/testClassDescriptors.json
@@ -0,0 +1 @@
+[{"name":"DragToCreateTestsAreDemo","functions":[{"functionName":"whenClickMenuButton","scenario":"WHEN click on the menu button, THEN the menu opens with a 'Drag To Create' menu entry","comments":[]},{"functionName":"whenClickAddMenuEntry","scenario":"WHEN click on the 'Drag To Create' menu entry, THEN the Gantt goes into the 'drag to create mode' and the drag to create popup appears","comments":[]},{"functionName":"givenDragToCreateModeWhenClickCancel","scenario":"GIVEN drag to create mode, WHEN click on cancel, THEN mode is cancelled","comments":[]},{"functionName":"givenDragToCreateModeWhenClickAndDrag","scenario":"GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears","comments":[]},{"functionName":"givenDragToCreateModeInProgressWhenRightClick","scenario":"GIVEN drag to create in progress, WHEN right click, THEN cancel","comments":[]},{"functionName":"givenDragToCreateModeInProgressWhenMouseUp","scenario":"GIVEN drag to create in progress, WHEN mouse up, THEN handler is called","comments":[]},{"functionName":"whenForceDragToCreateModeTrueFalseThenActionIsNotShownAndSegmentsCanBeCreatedOrNot","scenario":"WHEN forceDragToCreateMode = true/false, THEN action is not show and segments can/can't be created","comments":[]}],"hooks":["before"]},{"name":"SelectedItemsTestsAreDemo","functions":[{"functionName":"whenClickOnASegment","scenario":"WHEN click on a segment, THEN only that segment is selected","comments":[]},{"functionName":"whenClickAnotherSegment","scenario":"WHEN click on another segment, THEN only that segment is selected (so the previously selected segment is no more selected)","comments":[]},{"functionName":"whenCTRLClickOnASegment","scenario":"WHEN CTRL + click on a segment, THEN that segment is ADDED to the selection, AND both are now selected","comments":[]},{"functionName":"whenCTRLClickOnASelectedSegment","scenario":"WHEN CTRL + click on a selected segment, THEN that segment is REMOVED from the selection, AND only one is now selected","comments":[]},{"functionName":"whenCTRLClickOutside","scenario":"WHEN CTRL + click outside segments, THEN the selection doesn't change","comments":[]},{"functionName":"whenClickOutside","scenario":"WHEN click outside segments, THEN the selection becomes empty","comments":[]},{"functionName":"whenDragASelectionRectangleOverTwoSegments","scenario":"WHEN drag a selection rectangle over 2 segments, THEN only those 2 segments are selected","comments":[]},{"functionName":"whenDragASelectionRectangleOverAnotherSegment","scenario":"WHEN drag a selection rectangle over another segment, THEN only that segment is selected (so the previous 2 segments are not selected any more","comments":[]},{"functionName":"whenCTRLDragASelectionRectangleOverAnotherSegment","scenario":"WHEN hold CTRL + drag a selection rectangle over another segment, THEN that segment is ADDED to the selection, AND both are now selected","comments":[]},{"functionName":"whenCTRLDragASelectionRectangleOverAlreadySelectedSegment","scenario":"WHEN hold CTRL + drag a selection rectangle over an already selected segment, THEN that segment is REMOVED from the selection, AND only one is selected","comments":[]},{"functionName":"whenCTRLDragASelectionRectangleOverAnEmptyArea","scenario":"WHEN hold CTRL + drag a selection rectangle over an empty area, THEN the selection doesn't change","comments":[]},{"functionName":"whenDragASelectionRectangleOverAnEmptyArea","scenario":"WHEN drag a selection rectangle over an empty area, THEN the selection becomes empty","comments":[]}],"hooks":["before"]},{"name":"ContextMenuTestsAreDemo","functions":[{"functionName":"whenRightClickOnARow","scenario":"WHEN I right click on a row, THEN a context menu with one action opens","comments":[]},{"functionName":"whenClickAnAction","scenario":"WHEN I click on an action, THEN the action is run (w/ or w/o closing the menu)","comments":[]},{"functionName":"whenRightClickOnASegment","scenario":"WHEN I right click on a segment, THEN a context menu with 3 actions is shown","comments":[]},{"functionName":"whenCTRLRightClickOnAnotherSegment","scenario":"WHEN I CTRL + right click on another segment, THEN a context menu with 2 actions is shown","comments":[]},{"functionName":"whenClickTheHamburgerButton","scenario":"WHEN I click the hamburger button, THEN the context menu is shown besides that button","comments":[]}],"hooks":["before"]},{"name":"TableTestsAreDemo","functions":[{"functionName":"bothTableAndGanttHaveSameRowHeight","scenario":"Both table and gantt diagram have same rows height","comments":[]},{"functionName":"whenScrollInGanttThenTableIsScrolled","scenario":"When scrolling in gantt the table is scrolled","comments":[]},{"functionName":"whenScrollInTableThenGanttIsScrolled","scenario":"When scrolling in table the gantt is scrolled","comments":[]},{"functionName":"whenDragTheSplitPaneTheTableIsResizedAccordingly","scenario":"When drag the split pane the table is resized accordingly","comments":[]}],"hooks":["before"]},{"name":"DynamicConfigurationTestsAreDemo","functions":[{"functionName":"whenStartEndDateChanges","scenario":"WHEN I change the startDate/endDate properties THEN the new interval is displayed","comments":[]}],"hooks":["before"]},{"name":"BackgroundLayersTestsAreDemo","functions":[{"functionName":"highlightedIntervalsAreDisplayed","scenario":"The highlighted intervals are correctly displayed","comments":[]}],"hooks":["before"]}]
\ No newline at end of file
diff --git a/src/demo.js b/demo-app/src/demo.js
similarity index 68%
rename from src/demo.js
rename to demo-app/src/demo.js
index c829b924..4da4c9da 100644
--- a/src/demo.js
+++ b/demo-app/src/demo.js
@@ -1,20 +1,19 @@
'use strict';
-import React, {Component} from 'react';
-import moment from 'moment';
+import {Cell} from 'fixed-data-table-2';
+import React, {Fragment} from 'react';
import _ from 'lodash';
+import moment from 'moment';
+import {Component} from 'react';
-import Timeline from './timeline';
-import {
- customItemRenderer,
- customGroupRenderer,
- CustomCellRenderer,
- CustomColumnHeaderRenderer
-} from './demo/customRenderers';
+import { Timeline, ItemRenderer, ZOOM_IN, ZOOM_OUT } from "@famiprog-foundation/react-gantt";
-import {Layout, Form, InputNumber, Button, DatePicker, Checkbox, Switch, Icon} from 'antd';
+import {Button, Checkbox, DatePicker, Form, InputNumber, Switch} from 'antd';
import 'antd/dist/antd.css';
-import './style.css';
+
+import {Table, Column, DataCell} from 'fixed-data-table-2';
+import {CustomItemRenderer} from './demo/customRenderers';
+import {generateRandomRowsAndItems} from './stories/sampleData';
const {TIMELINE_MODES} = Timeline;
@@ -22,6 +21,14 @@ const ITEM_DURATIONS = [moment.duration(6, 'hours'), moment.duration(12, 'hours'
const COLORS = ['#0099cc', '#f03a36', '#06ad96', '#fce05b', '#dd5900', '#cc6699'];
+const headerStyle = {
+ color: '#000',
+ fontSize: '12px',
+ lineHeight: '1',
+ background: '#CCFFEE',
+ border: 'none'
+};
+
// Moment timezones can be enabled using the following
// import moment from 'moment-timezone';
// moment.locale('en-au');
@@ -41,11 +48,15 @@ export default class DemoTimeline extends Component {
snap: 60,
startDate,
endDate,
+ minDate: moment('2018-07-31'),
+ maxDate: moment('2018-10-30'),
message: '',
timelineMode: TIMELINE_MODES.SELECT | TIMELINE_MODES.DRAG | TIMELINE_MODES.RESIZE,
- multipleColumnsMode: false,
+ useTable: true,
+ zoomEnabled: true,
useMoment: true
};
+ this.timelineRef = React.createRef();
this.reRender = this.reRender.bind(this);
this.zoomIn = this.zoomIn.bind(this);
this.zoomOut = this.zoomOut.bind(this);
@@ -54,7 +65,9 @@ export default class DemoTimeline extends Component {
this.toggleDraggable = this.toggleDraggable.bind(this);
this.toggleResizable = this.toggleResizable.bind(this);
this.toggleUseMoment = this.toggleUseMoment.bind(this);
- this.toggleMultipleColumnsMode = this.toggleMultipleColumnsMode.bind(this);
+ this.toggleUseTable = this.toggleUseTable.bind(this);
+ this.toggleZoomEnabled = this.toggleZoomEnabled.bind(this);
+ this.scrollToRandomItem = this.scrollToRandomItem.bind(this);
}
componentWillMount() {
@@ -62,71 +75,19 @@ export default class DemoTimeline extends Component {
}
reRender(useMoment = this.state.useMoment) {
- const list = [];
- const groups = [];
const {snap} = this.state;
-
- this.key = 0;
- for (let i = 0; i < this.state.rows; i++) {
- groups.push({id: i, title: `Row ${i}`, description: `Description for row ${i}`});
- for (let j = 0; j < this.state.items_per_row; j++) {
- this.key += 1;
- const color = COLORS[(i + j) % COLORS.length];
- const duration = ITEM_DURATIONS[Math.floor(Math.random() * ITEM_DURATIONS.length)];
- // let start = last_moment;
- let start = moment(
- Math.floor(
- Math.random() * (this.state.endDate.valueOf() - this.state.startDate.valueOf()) +
- this.state.startDate.valueOf()
- )
- );
- let end = start.clone().add(duration);
-
- // Round to the nearest snap distance
- const roundedStartSeconds = Math.floor(start.second() / snap) * snap;
- const roundedEndSeconds = Math.floor(end.second() / snap) * snap;
- start.second(roundedStartSeconds);
- end.second(roundedEndSeconds);
-
- list.push({
- key: this.key,
- title: duration.humanize(),
- color,
- row: i,
- start: useMoment ? start : start.valueOf(),
- end: useMoment ? end : end.valueOf()
- });
- }
- }
-
- const tableColumns = [
- // default renderers
- {
- width: 100,
- headerLabel: 'Title',
- labelProperty: 'title'
- },
- // custom renderers: react elements
- {
- width: 250,
- cellRenderer: Checkbox,
- headerRenderer: (
-
- Custom check
-
- )
- },
- // custom renderers: class component
- {
- width: 100,
- headerRenderer: CustomColumnHeaderRenderer,
- cellRenderer: CustomCellRenderer
- }
- ];
-
+ const [groups, items] = generateRandomRowsAndItems(
+ this.state.rows,
+ this.state.items_per_row,
+ useMoment,
+ snap,
+ this.state.minDate,
+ this.state.maxDate
+ );
+
// this.state = {selectedItems: [11, 12], groups, items: list};
this.forceUpdate();
- this.setState({items: list, groups, tableColumns, useMoment});
+ this.setState({items: items, groups, useMoment});
}
handleRowClick = (e, rowNumber, clickedTime, snappedClickedTime) => {
@@ -134,14 +95,10 @@ export default class DemoTimeline extends Component {
this.setState({selectedItems: [], message});
};
zoomIn() {
- let currentMilliseconds = this.state.endDate.diff(this.state.startDate, 'milliseconds');
- let newSec = currentMilliseconds / 2;
- this.setState({endDate: this.state.startDate.clone().add(newSec, 'milliseconds')});
+ this.timelineRef.current.zoom(ZOOM_IN);
}
zoomOut() {
- let currentMilliseconds = this.state.endDate.diff(this.state.startDate, 'milliseconds');
- let newSec = currentMilliseconds * 2;
- this.setState({endDate: this.state.startDate.clone().add(newSec, 'milliseconds')});
+ this.timelineRef.current.zoom(ZOOM_OUT);
}
toggleCustomRenderers(checked) {
@@ -167,10 +124,37 @@ export default class DemoTimeline extends Component {
const {useMoment} = this.state;
this.reRender(!useMoment);
}
- toggleMultipleColumnsMode() {
- const {multipleColumnsMode} = this.state;
- this.setState({multipleColumnsMode: !multipleColumnsMode});
+
+ toggleUseTable() {
+ const {useTable} = this.state;
+ this.setState({useTable: !useTable});
}
+
+ toggleZoomEnabled() {
+ const {zoomEnabled} = this.state;
+ if (!zoomEnabled) {
+ // Here, we could directly set the `zoomEnabled` to `true`.
+ // We set it to a function only to demonstration purposes.
+ this.setState({zoomEnabled: () => true});
+ } else {
+ this.setState({zoomEnabled: false});
+ }
+ }
+
+ scrollToRandomItem() {
+ const { items } = this.state;
+ if (!items || items.length === 0) {
+ this.setState({ message: 'No items to scroll to.' });
+ return;
+ }
+
+ const randomIndex = Math.floor(Math.random() * items.length);
+ const randomItem = items[randomIndex];
+
+ this.timelineRef.current.scrollToItem(randomItem.key);
+ this.setState({ message: `Scrolled to item: ${randomItem.key} (${randomItem.title || 'No title'})` });
+ }
+
handleItemClick = (e, key) => {
const message = `Item Click ${key}`;
const {selectedItems} = this.state;
@@ -178,12 +162,11 @@ export default class DemoTimeline extends Component {
let newSelection = selectedItems.slice();
// If the item is already selected, then unselected
- const idx = selectedItems.indexOf(key);
- if (idx > -1) {
- // Splice modifies in place and returns removed elements
- newSelection.splice(idx, 1);
+ const isSelected = selectedItems.find(item => item == key);
+ if (isSelected) {
+ newSelection = newSelection.filter(item => item != key);
} else {
- newSelection.push(Number(key));
+ newSelection.push(key);
}
this.setState({selectedItems: newSelection, message});
@@ -286,22 +269,26 @@ export default class DemoTimeline extends Component {
snap,
startDate,
endDate,
+ minDate,
+ maxDate,
items,
groups,
message,
useCustomRenderers,
timelineMode,
useMoment,
- multipleColumnsMode,
- tableColumns
+ useTable,
+ zoomEnabled
} = this.state;
const rangeValue = [startDate, endDate];
+ const minMaxRangeValue = [minDate, maxDate];
const selectable = (TIMELINE_MODES.SELECT & timelineMode) === TIMELINE_MODES.SELECT;
const draggable = (TIMELINE_MODES.DRAG & timelineMode) === TIMELINE_MODES.DRAG;
const resizeable = (TIMELINE_MODES.RESIZE & timelineMode) === TIMELINE_MODES.RESIZE;
const rowLayers = [];
+
for (let i = 0; i < rows; i += 1) {
if (i % 5 === 0 && i !== 0) {
continue;
@@ -333,7 +320,6 @@ export default class DemoTimeline extends Component {
curDate.add(bandDuration, 'days');
}
}
-
return (
: undefined}
+ itemRenderer={useCustomRenderers ? CustomItemRenderer : ItemRenderer}
/>
);
diff --git a/demo-app/src/demo/customRenderers.js b/demo-app/src/demo/customRenderers.js
new file mode 100644
index 00000000..ae901525
--- /dev/null
+++ b/demo-app/src/demo/customRenderers.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { ItemRenderer } from '@famiprog-foundation/react-gantt';
+
+export class CustomItemRenderer extends ItemRenderer {
+ getBackgroundGradient() {
+ return this.getColor();
+ }
+
+ getStyle() {
+ let style = super.getStyle();
+ if (this.props.row % 5 === 0) {
+ style.border = '1px solid black';
+ }
+ return style;
+ }
+
+ getTitle() {
+ return `${this.props.item.start.format('HH:mm')} - ${this.props.item.end.format('HH:mm')}`;
+ }
+}
+export class CustomCellRenderer extends React.Component {
+ render() {
+ return {this.props.group.description};
+ }
+}
diff --git a/demo-app/src/demo_index.js b/demo-app/src/demo_index.js
new file mode 100644
index 00000000..52cb5b44
--- /dev/null
+++ b/demo-app/src/demo_index.js
@@ -0,0 +1,39 @@
+'use strict';
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import './stories/storybook.css';
+import '@famiprog-foundation/react-gantt/style.css';
+
+import DemoTimeline from './demo';
+import {TestsAreDemoAppWrapper} from '@famiprog-foundation/tests-are-demo';
+import {tad} from '@famiprog-foundation/tests-are-demo';
+import {DragToCreateTestsAreDemo} from './testsAreDemo/DragToCreateTestsAreDemo';
+import {TableTestsAreDemo} from './testsAreDemo/TableTestsAreDemo';
+import {SelectedItemsTestsAreDemo} from './testsAreDemo/SelectedItemsTestsAreDemo';
+import {ContextMenuTestsAreDemo} from './testsAreDemo/ContextMenuTestsAreDemo';
+import {DynamicConfigurationTestsAreDemo} from './testsAreDemo/DynamicConfigurationTestsAreDemo';
+import { BackgroundLayersTestsAreDemo } from './testsAreDemo/BackgroundLayersTestsAreDemo';
+import { DisplayItemOnSeparateRowIfOverlapTestsAreDemo } from './testsAreDemo/DisplayItemOnSeparateRowIfOverlapTestsAreDemo';
+import { ZoomTestsAreDemo } from './testsAreDemo/ZoomTestsAreDemo';
+
+ReactDOM.render(
+ }
+ importTestsCallback={() => {
+ tad.addTests(
+ DragToCreateTestsAreDemo,
+ SelectedItemsTestsAreDemo,
+ ContextMenuTestsAreDemo,
+ TableTestsAreDemo,
+ DynamicConfigurationTestsAreDemo,
+ BackgroundLayersTestsAreDemo,
+ DisplayItemOnSeparateRowIfOverlapTestsAreDemo,
+ ZoomTestsAreDemo
+ );
+ }}
+ />,
+ document.getElementById('root')
+);
diff --git a/demo-app/src/stories/ApiDoc.stories.mdx b/demo-app/src/stories/ApiDoc.stories.mdx
new file mode 100644
index 00000000..da292f7f
--- /dev/null
+++ b/demo-app/src/stories/ApiDoc.stories.mdx
@@ -0,0 +1,24 @@
+import { Meta } from '@storybook/addon-docs';
+
+{/* "Canvas" tab is not needed, show only "Docs" tab */}
+
+
+{/* We use parent.window because we are already inside an iframe.*/}
+
\ No newline at end of file
diff --git a/demo-app/src/stories/DemoTimeline.stories.mdx b/demo-app/src/stories/DemoTimeline.stories.mdx
new file mode 100644
index 00000000..5599b674
--- /dev/null
+++ b/demo-app/src/stories/DemoTimeline.stories.mdx
@@ -0,0 +1,22 @@
+import { Canvas, Meta, Story, ArgsTable, Description } from '@storybook/addon-docs';
+import moment from 'moment';
+import DemoTimeline from '../demo';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+
+{/* "Docs" tab is not needed, show only "Canvas" tab */}
+
+
+
\ No newline at end of file
diff --git a/demo-app/src/stories/StorybookUtils.js b/demo-app/src/stories/StorybookUtils.js
new file mode 100644
index 00000000..85029440
--- /dev/null
+++ b/demo-app/src/stories/StorybookUtils.js
@@ -0,0 +1,22 @@
+/**
+ * It returns an URI to API Doc story.
+ * Furthermore, it receives a subpath to reference a component/method from
+ * API documentation.
+ *
+ * @param {string} subpath
+ */
+export const encodeApiDocURIForSubpath = subpath => {
+ return '?path=/docs/api-doc--page&subpath=' + encodeURIComponent(subpath);
+};
+
+export const parametersDocPage = {
+ viewMode: 'docs',
+ previewTabs: {
+ 'storybook/docs/panel': {
+ hidden: false
+ },
+ canvas: {
+ hidden: true
+ }
+ }
+};
diff --git a/src/stories/Timeline.stories.jsx b/demo-app/src/stories/Timeline.stories.jsx
similarity index 96%
rename from src/stories/Timeline.stories.jsx
rename to demo-app/src/stories/Timeline.stories.jsx
index b7502b1e..831be01b 100644
--- a/src/stories/Timeline.stories.jsx
+++ b/demo-app/src/stories/Timeline.stories.jsx
@@ -2,11 +2,11 @@ import React from 'react';
import moment from 'moment';
import DemoTimeline from '../demo';
-import Timeline from '../timeline';
-import {Alert} from 'antd';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import {Alert, notification} from 'antd';
export default {
- title: 'Timeline'
+ title: 'Internal/Timeline'
};
export const OriginalDemo = () => ;
diff --git a/demo-app/src/stories/TimelineScenarios.ts b/demo-app/src/stories/TimelineScenarios.ts
new file mode 100644
index 00000000..5f5814e3
--- /dev/null
+++ b/demo-app/src/stories/TimelineScenarios.ts
@@ -0,0 +1,15 @@
+export const timelineScenarios = {
+ rendererForGroups: 'RENDERER for rows (groups)',
+ rendererForItems: 'RENDERER for segments (items)',
+ whenMouseMovesThenRedBar:
+ 'WHEN the mouse moves THEN the red bar moves also (with snapping) AND the its date is displayed',
+ propertyItemRendererDefaultProps: 'PROPERTY itemRendererDefaultProps',
+ propertyItemRenderer: 'PROPERTY itemRenderer',
+ whenClickOrDragToSelectThenItemsSelected: "WHEN click or drag to select THEN items are selected/deselected",
+ propertyRowClassName: 'PROPERTY rowClassName',
+ propertyRowEvenClassName: 'PROPERTY rowEvenClassName',
+ propertyRowOddClassName: 'PROPERTY rowOddClassName',
+ propertyMinDate: 'PROPERTY minDate',
+ propertyMaxDate: 'PROPERTY maxDate',
+ propertyShowZoomShortcuts: 'PROPERTY showZoomShortcuts',
+};
diff --git a/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.mdx b/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.mdx
new file mode 100644
index 00000000..f8b45870
--- /dev/null
+++ b/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.mdx
@@ -0,0 +1,31 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import {Timeline, BackgroundLayer, HighlightedInterval, Marker} from '@famiprog-foundation/react-gantt';
+
+
+
+## Background layer
+
+A background layer contains 2 types of elements:
+* markers (a vertical line),
+* and highlight intervals (a rectangle spanning from top to bottom).
+
+You can add as many such items as you wish. Additionnaly, there are properties that generate:
+
+* a marker for the current date/time,
+* and intervals for weekends.
+
+## `Timeline`
+
+
+
+## `BackgroundLayer`
+
+
+
+## `HighlightedInterval`
+
+
+
+## `Marker`
+
+
\ No newline at end of file
diff --git a/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.tsx b/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.tsx
new file mode 100644
index 00000000..564ead8e
--- /dev/null
+++ b/demo-app/src/stories/backgroundLayer/BackgroundLayer.stories.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { Timeline, BackgroundLayer, HighlightedInterval, Marker, Item } from '@famiprog-foundation/react-gantt';
+import { startOfCurrentMonth, endOfCurrentMonth, dateAndHourOfCurrentMonth, manyHumanResources, dateAndHourOfMonth, d } from '../sampleData';
+import { backgroundLayerScenarios } from './BackgroundLayerScenarios';
+import { Table, Column, DataCell} from 'fixed-data-table-2';
+import moment from 'moment';
+
+export default {
+ title: 'Features/Background Layer',
+ includeStories: /^[A-Z]/
+};
+
+export const month = moment("2023 11", "YYYY MM");
+
+const tasks: Item[] = [
+ {key: 11, row: 1, title: 'Task JD1', start: dateAndHourOfMonth(month, 20, 8), end: dateAndHourOfMonth(month, 28, 11)},
+ {key: 12, row: 3, title: 'Task KP1', start: dateAndHourOfMonth(month, 3, 0), end: dateAndHourOfMonth(month, 6, 23)},
+ {key: 13, row: 3, title: 'Task KP2', start: dateAndHourOfMonth(month, 11, 18), end: dateAndHourOfMonth(month, 18, 19)}
+];
+
+export const Main = () => {
+ return (
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < manyHumanResources.length ? manyHumanResources[rowIndex].title : ""}}/>
+
}
+ backgroundLayer={
+ ,
+ ,
+
+ ]}
+ markers={[
+ ,
+
+ ]}
+ />}
+ />
+ );
+};
+
+Main.parameters = {
+ scenarios: [
+ backgroundLayerScenarios.verticalGrid,
+ backgroundLayerScenarios.nowMarker,
+ backgroundLayerScenarios.highlightWeekends,
+ backgroundLayerScenarios.markers,
+ backgroundLayerScenarios.highlightedIntervals
+ ]
+}
+
+export const CustomClassNamesAndStyles = () => {
+ return (
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < manyHumanResources.length ? manyHumanResources[rowIndex].title : ""}}/>
+ }
+ backgroundLayer={
+ ,
+
+ ]}
+ markers={[
+ ,
+
+ ]}
+ />}
+ />
+ );
+};
+
+CustomClassNamesAndStyles.parameters = {
+ scenarios: [
+ backgroundLayerScenarios.verticalGridClassName,
+ backgroundLayerScenarios.nowMarkerClassName,
+ backgroundLayerScenarios.highlightWeekendsClassName,
+ backgroundLayerScenarios.classNameForMarker,
+ backgroundLayerScenarios.highlightedIntervalClassName
+ ]
+}
\ No newline at end of file
diff --git a/demo-app/src/stories/backgroundLayer/BackgroundLayerScenarios.js b/demo-app/src/stories/backgroundLayer/BackgroundLayerScenarios.js
new file mode 100644
index 00000000..96218ce8
--- /dev/null
+++ b/demo-app/src/stories/backgroundLayer/BackgroundLayerScenarios.js
@@ -0,0 +1,17 @@
+export const backgroundLayerScenarios = {
+ // BackgroundLayer
+ highlightWeekends: 'PROPERTY highlightWeekends',
+ highlightWeekendsClassName: 'PROPERTY highlightWeekendsClassName',
+ nowMarker: 'PROPERTY nowMarker',
+ nowMarkerClassName: 'PROPERTY nowMarkerClassName',
+ verticalGrid: 'PROPERTY verticalGrid',
+ verticalGridClassName: 'PROPERTY verticalGridClassName',
+ markers: 'PROPERTY markers',
+ highlightedIntervals: 'PROPERTY highlightedIntervals',
+
+ // HighlightedInterval
+ highlightedIntervalClassName: 'PROPERTY className FOR HighlightedInterval',
+
+ // Marker
+ classNameForMarker: 'PROPERTY className FOR Marker'
+};
diff --git a/demo-app/src/stories/basic/Basic.stories.mdx b/demo-app/src/stories/basic/Basic.stories.mdx
new file mode 100644
index 00000000..5bdafe1f
--- /dev/null
+++ b/demo-app/src/stories/basic/Basic.stories.mdx
@@ -0,0 +1,76 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Parent component
+
+`Timeline` is meant to have a parent w/ `display: flex`. This way, it's height adapts to the one of the parent.
+
+## `Timeline`: mandatory props
+
+
+
+## About moment.js
+
+The `Timeline` was originally designed to handle date/times w/ [Moment.js](https://momentjs.com/),
+a popular lib. However there are 2 drawbacks.
+
+**#1**: even the authors/maintainers of Moment.js don't
+quite [recommend](https://momentjs.com/docs/) it any more for use with new projects. The major
+complaint seems to be the mutability of "moment" objects.
+
+**#2**: "moment" objects are not friendly with
+[Redux](https://redux.js.org/), a popular framework for state management. Many folks use Redux for
+state management. And not being able to store the state that feeds the `Timeline` is a big drawback, since
+additional conversions are necessary.
+
+The property `useMoment` to the rescue:
+
+
+
+## Extending `Timeline` / overriding date handling
+
+The default start/end fields for an **item** (segment) and for a **row layer** are `start` and `end`. Every date manipulation (read or write) is done exclusively via these functions
+(the links point to the [API Doc](?path=/docs/api-doc--page)).
+
+* Timeline.getStartDate()
+* Timeline.getEndDate()
+* Timeline.getStartFromItem(item)
+* Timeline.getEndFromItem(item)
+* Timeline.setStartToItem(item, newDateAsMoment)
+* Timeline.setEndToItem(item, newDateAsMoment)
+* Timeline.getStartFromRowLayer(layer)
+* Timeline.getEndFromRowLayer(layer)
+* Timeline.setStartToRowLayer(layer, newDateAsMoment)
+* Timeline.setEndToRowLayer(layer, newDateAsMoment)
+* utils: convertDateToMoment(date, useMoment)
+* utils: convertMomentToDateType(dateAsMoment, useMoment)
+
+If you create your **own subclass of `Timeline`**, you may override these functions. Some possible scenarios:
+* the start/end fields are named differently for all the objects;
+* or maybe depending of the type of object, some are called in a way, and others in another way;
+* or for some objects such fields are calculated;
+* or the data type is not timestamp or moment, and an additional conversion is needed.
+
+The scenarios above are examples for the case you are constrained to adapt the `Timeline` to the shape of the data. However, this is something that you should avoid. By default,
+try to shape the data according to the defaults that `Timeline` expects.
+
+**IMPORTANT**: if you extend `Timeline` and manipulate dates, please use always use the functions above. E.g.
+
+```js
+// bad
+const start = item.start;
+
+// good
+const start = this.getStartFromItem(item);
+```
+
+## Providing a table associated with the gantt
+
+**IMPORTANT**: By default the gantt diagram displayes without any table associated.
+
+If you want to display a table (like in the majority of our examples) you should set the table property:
+
+
\ No newline at end of file
diff --git a/demo-app/src/stories/basic/Basic.stories.tsx b/demo-app/src/stories/basic/Basic.stories.tsx
new file mode 100644
index 00000000..38b1c354
--- /dev/null
+++ b/demo-app/src/stories/basic/Basic.stories.tsx
@@ -0,0 +1,139 @@
+import React from 'react';
+import { Timeline, Group, Item } from '@famiprog-foundation/react-gantt';
+
+import { timelineScenarios } from '../TimelineScenarios';
+import { d, someHumanResources, someTasks } from '../sampleData';
+import { ComponentStory } from '@storybook/react';
+import { Table, Column, DataCell } from 'fixed-data-table-2';
+
+export default {
+ title: 'Features/Basic'
+};
+
+export const Main = () => {
+ // the rows (aka groups)
+ // id is mandatory; should: be numeric, start from 0, have consecutive values
+ const humanResources: Group[] = [...someHumanResources, { id: 4, title: 'George Walsh' }];
+
+ // the segments
+ // key is mandatory; row should point to the "id" of a row/group
+ const tasks: Item[] = [
+ ...someTasks, // we split this array in 2 parts for illustration purposes, i.e. to capture the data shape in the storybook
+ { key: 11, row: 4, title: 'Task GW1', start: d('2018-09-20 7:00'), end: d('2018-09-20 8:00') },
+ { key: 12, row: 4, title: 'Task GW2', start: d('2018-09-20 17:00'), end: d('2018-09-20 19:00') }
+ ];
+
+ // NOTE: for DRY purposes, we store the sample data (e.g. humanResources, segments) in sampleData.ts.
+ // If you look at this function from within Storybook, you don't see easily sampleData.ts.
+ // That's why we added some additional records here, so that the shape of data is clear.
+
+ return (
+ <>
+ {/* This is a trivial example to illustrate how Timeline "glues" to its "flex" parent. Notes: */}
+ {/* 1/ In other stories we don't have this, because we have a Storybook decorator that wraps w/ a div + CSS class. */}
+ {/* 2/ You'll probably have a better flex-box layout, i.e. not hardcoded. 3/ Use CSS classes and not styles. */}
+
+ >
+ );
+};
+
+HorizontalScroll.parameters = {
+ scenarios: [
+ timelineScenarios.propertyMinDate,
+ timelineScenarios.propertyMaxDate
+ ]
+};
\ No newline at end of file
diff --git a/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.mdx b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.mdx
new file mode 100644
index 00000000..d5679464
--- /dev/null
+++ b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.mdx
@@ -0,0 +1,23 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Context Menu
+In order for a context menu to be displayed when right clicking the gantt, some actions should be provided by setting onContextMenuShow. The action descriptors (IGanttAction) return by this handler describe the actions that will fill in the context menu.
+
+### Timeline
+
+
+By default the context menu is closed after the you click a context menu entry (i.e after IGanttAction.run(param) is called). To avoid this you should set param.dontCloseContextMenuAfterRunAutomatically to true. You can close the context menu afterwards by manually calling closeContextMenu()
+
+## Selection
+Segments can be selected by clicking on them or by dragging to select them.
+Right click can be also used instead of left click.
+Multiple selection is available by keeping CTRL or SHIFT key pressed.
+
+Selection change listener can by added by setting the onSelectionChange property.
+
+### Timeline
+
diff --git a/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.tsx b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.tsx
new file mode 100644
index 00000000..80968740
--- /dev/null
+++ b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelection.stories.tsx
@@ -0,0 +1,145 @@
+import { createTestids } from '@famiprog-foundation/tests-are-demo';
+import { Alert } from 'antd';
+import moment from 'moment';
+import { useState } from 'react';
+import { Button, Icon, Menu } from 'semantic-ui-react';
+import { Timeline, IGanttAction, IGanttOnContextMenuShowParam, Item } from '@famiprog-foundation/react-gantt';
+import { d, someHumanResources, someTasks } from '../sampleData';
+import { contextMenuScenarios, selectionScenarios } from './ContextMenuAndSelectionScenarios';
+import { Table, Column, DataCell } from 'fixed-data-table-2';
+
+export default {
+ title: 'Features/Context Menu And Selection',
+ includeStories: /^[A-Z]/
+};
+
+export const addTaskActionLabel = "Add task for ";
+export const addTaskActionIcon = "plus";
+export const addTaskNotPossibleAction = "Add task: not possible. Please right click over a row with a person.";
+export const editActionLabel = "Edit";
+export const deleteActionLabel = "Delete";
+export const deleteActionIcon = "trash";
+export const deleteActionIconColor = "red";
+
+export const ContextMenu = () => {
+ const [tasks, setTasks] = useState([...someTasks]);
+ const [segmentHeight, setSegmentHeight] = useState(40);
+ return (
+ <>
+ Add task action is provided only for empty selection. It also has a different label depending on which row is displayed>}/>
+
+ {
+ const actions: IGanttAction[] = [
+ {
+ icon: "edit",
+ label: editActionLabel,
+ isVisible: param => param.selection.length == 1,
+ run: param => {
+ param.dontCloseContextMenuAfterRunAutomatically = true;
+ // This timeout is just for exemplify a delayed closing of the CM
+ setTimeout(() => {
+ param.closeContextMenu();
+ const selectedTask = tasks.find((task) => task.key == param.selection[0]);
+ // This timeout for the menu to actual close before the prompt is shown
+ setTimeout(() => {
+ // TODO CS: se pare ca nu e o idee buna sa folosim prompt, fiindca blocheaza testul
+ // si nu putem simula scrierea.
+ // let newTitle = prompt("Task new title:", selectedTask.title);
+ let newTitle;
+ newTitle && setTasks(tasks.map((task) => task == selectedTask ? { ...task, title: newTitle } : task));
+ }, 10);
+ }, 10);
+ }
+ },
+ {
+ isVisible: param => param.selection.length > 0 ,
+ /** This is a trivial example for customizing the content of an action renderer
+ * but this content can be replaced according to application needs with a more complex one:
+ * e.g. maybe containing a color picker (for an action that changes the color of a segment)*/
+ renderInMenu: (param) => {
+ return {
+ setTasks(tasks.filter(task => !param.selection.includes(task.key)));
+ param.closeContextMenu();
+ }}>
+ {deleteActionLabel}
+
+
+ }
+ }
+ ];
+ // We can filter the actions that will be displayed directly here in the actions provider
+ if (contextMenuShowParam.actionParam.row < someHumanResources.length) {
+ actions.splice(0, 0, {
+ icon: ,
+ label: param => addTaskActionLabel + someHumanResources[param.row].title,
+ run: param => {
+ let end = moment(param.time);
+ end.hours(end.hours() + 3);
+ const maxKey = tasks.reduce((maxKey, task) => maxKey > (task.key as number) ? maxKey : (task.key as number), 0);
+ setTasks([...tasks, { key: maxKey + 1, row: someHumanResources[param.row].id, title: 'NEW TASK', start: param.time, end: end}]);
+ }
+ });
+ } else {
+ actions.splice(0, 0, { icon: addTaskActionIcon, label: () => addTaskNotPossibleAction});
+ }
+
+ return actions;
+ }}
+ table={
+ >
+ );
+ };
+
+ Selection.parameters = {
+ scenarios: [
+ ...Object.keys(selectionScenarios).map(key => selectionScenarios[key])
+ ]
+};
\ No newline at end of file
diff --git a/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelectionScenarios.ts b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelectionScenarios.ts
new file mode 100644
index 00000000..b45b8ff7
--- /dev/null
+++ b/demo-app/src/stories/contextMenuAndSelection/ContextMenuAndSelectionScenarios.ts
@@ -0,0 +1,12 @@
+export const contextMenuScenarios = {
+ whenRightClickThenContextMenu: 'WHEN right click on gantt, THEN a context menu is shown containing actions (each having a label and an icon)',
+ whenClickActionThenRunAndCloseMenu: 'WHEN click an action, THEN a specific action is run and the context menu is closed',
+ propertyOnContextMenuShow: 'PROPERTY onContextMenuShow',
+ propertyDontCloseContextMenuAfterRunAutomatically: 'PROPERTY IActionParamForRun.dontCloseContextMenuAfterRunAutomatically'
+};
+
+export const selectionScenarios = {
+ whenClickOrDragToSelectThenItemsSelected: "WHEN click or drag to select THEN items are selected/deselected",
+ propertyOnSelectionChange: "PROPERTY onSelectionChange",
+ propertySelectedItems: "PROPERTY selectedItems"
+}
\ No newline at end of file
diff --git a/demo-app/src/stories/custom/Custom.stories.mdx b/demo-app/src/stories/custom/Custom.stories.mdx
new file mode 100644
index 00000000..e4148c98
--- /dev/null
+++ b/demo-app/src/stories/custom/Custom.stories.mdx
@@ -0,0 +1,14 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline, ItemRenderer } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Custom Timeline
+
+### Menu:
+ * We can override the Timeline.renderMenuButton() for change the default menu.
+
+## `Timeline`
+
+
diff --git a/demo-app/src/stories/custom/Custom.stories.tsx b/demo-app/src/stories/custom/Custom.stories.tsx
new file mode 100644
index 00000000..e800cb5d
--- /dev/null
+++ b/demo-app/src/stories/custom/Custom.stories.tsx
@@ -0,0 +1,39 @@
+import { useEffect, useRef, useState } from "react";
+import { Segment } from "semantic-ui-react";
+import { d, someHumanResources, someTasks } from "../sampleData";
+import { CustomTimeline } from "./CustomTimeline";
+import { customTimelineScenarios } from "./CustomTimelineScenarios";
+import { ItemRenderer } from '@famiprog-foundation/react-gantt';
+import { Table, Column, DataCell} from 'fixed-data-table-2';
+
+export default {
+ title: 'Features/Custom'
+};
+
+export const CustomMenuButtonRenderer = () => {
+
+ const divRef = useRef();
+ const [value, setValue] = useState(0);
+ // after first render when the div dom element is created for re-render
+ useEffect(() => { !value && setValue(value => value + 1) });
+
+ return (<>
+
+
+
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }
+ toolbarDomElement={divRef.current} itemRenderer={ItemRenderer}/>
+ >);
+
+};
+
+CustomMenuButtonRenderer.parameters = {
+ scenarios: Object.keys(customTimelineScenarios).map(key => customTimelineScenarios[key])
+};
diff --git a/demo-app/src/stories/custom/CustomTimeline.js b/demo-app/src/stories/custom/CustomTimeline.js
new file mode 100644
index 00000000..9bfddf4a
--- /dev/null
+++ b/demo-app/src/stories/custom/CustomTimeline.js
@@ -0,0 +1,19 @@
+import PropTypes from 'prop-types';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import ReactDOM from 'react-dom';
+
+export class CustomTimeline extends Timeline {
+ static propTypes = {
+ ...Timeline.propTypes,
+ /**
+ * @type { JSX.Element }
+ */
+ toolbarDomElement: PropTypes.object.isRequired
+ };
+
+ renderMenuButton() {
+ return this.props.toolbarDomElement
+ ? ReactDOM.createPortal(super.renderMenuButton(), this.props.toolbarDomElement)
+ : super.renderMenuButton();
+ }
+}
diff --git a/demo-app/src/stories/custom/CustomTimelineScenarios.ts b/demo-app/src/stories/custom/CustomTimelineScenarios.ts
new file mode 100644
index 00000000..2f312e05
--- /dev/null
+++ b/demo-app/src/stories/custom/CustomTimelineScenarios.ts
@@ -0,0 +1,4 @@
+export const customTimelineScenarios = {
+ renderCustomMenuButton: 'RENDERE for custom menu button',
+ rendererMenuButton: 'RENDERER for extern menu button'
+};
diff --git a/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/CustomTimeline.js b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/CustomTimeline.js
new file mode 100644
index 00000000..5284c1ba
--- /dev/null
+++ b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/CustomTimeline.js
@@ -0,0 +1,17 @@
+import PropTypes from 'prop-types';
+import Timeline, { DEFAULT_ROW_CLASS } from '../../../../src/timeline';
+
+export class CustomTimeline extends Timeline {
+
+ static propTypes = {
+ ...Timeline.propTypes,
+ /**
+ * @type { number }
+ */
+ selectedIndex: PropTypes.number
+ };
+
+ getRowClassName(rowIndex) {
+ return this.props.selectedIndex == rowIndex ? DEFAULT_ROW_CLASS + ' selected-row' : super.getRowClassName(rowIndex);
+ }
+}
diff --git a/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.mdx b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.mdx
new file mode 100644
index 00000000..a563cec7
--- /dev/null
+++ b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.mdx
@@ -0,0 +1,16 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import Timeline from '../../../../src/timeline';
+import Column from '../../../../src/timeline';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Display item on separate rows if ovelap
+
+If some items are overlapping, the gantt diagram doesn't display them overlapped. It puts them one beneath the other.
+
+This can be changed by setting the `displayItemOnSeparateRowIfOverlap` to `true`
+or to a function that decides (given an item) whether it allows to be displayed on a new row in case of overlapping or it should be displayed on the first row no matter the overlapping with other segments.
+
+## `Timeline`
+
\ No newline at end of file
diff --git a/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.tsx b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.tsx
new file mode 100644
index 00000000..d9938d83
--- /dev/null
+++ b/demo-app/src/stories/displayItemOnSeparateRowIfOverlap/DisplayItemOnSeparateRowIfOverlap.stories.tsx
@@ -0,0 +1,97 @@
+import { createTestids } from '@famiprog-foundation/tests-are-demo';
+import { Column, DataCell, Table } from 'fixed-data-table-2';
+import { useState } from "react";
+import { Dropdown, Form, FormField } from "semantic-ui-react";
+import Timeline, { DEFAULT_ROW_CLASS } from '../../../../src/timeline';
+import { Item } from '../../../../src/types';
+import { someHumanResources, someTasks2 } from "../sampleData";
+import { CustomTimeline } from './CustomTimeline';
+import moment from 'moment';
+
+export default {
+ title: "Features/Display item on separate rows if overlap",
+ includeStories: /^[A-Z][a-z].*/
+}
+
+export const displayItemOnSeparateRowIfOverlapStoryTestIds = createTestids('DisplayItemOnSeparateRowIfOverlapStory', {
+ displayItemOnSeparateRowDropdown: ''
+});
+
+export const TRUE = "True";
+export const FALSE = "False";
+export const ONLY_FOR_SELECTED = "Only for selected rows";
+
+export var selectedRow, setSelectedRow;
+
+export const Main = () => {
+ const tasks: Item[] = [
+ ...someTasks2,
+ { key: 11, row: 1, title: 'Task AR4', start: moment('2018-09-20 10:00'), end: moment('2018-09-20 11:00') },
+ { key: 12, row: 2, title: 'Task MD6', start: moment('2018-09-20 07:30'), end: moment('2018-09-20 15:00') }
+ ];
+ const [displayItemOnSeparateRowIfOverlap, setDisplayItemOnSeparateRowIfOverlap] = useState boolean)>(true);
+ [selectedRow, setSelectedRow] = useState(-1);
+ const [displayIntervalStart, displayIntervalEnd] = [moment('2018-09-20'), moment('2018-09-21')]
+ // Smaller segments are staying on top of the bigger ones
+ const zIndexFunction = (item: Item) => {
+ return Math.floor((displayIntervalEnd.valueOf() - displayIntervalStart.valueOf()) / ((item.end.valueOf() as number) - (item.start.valueOf() as number)));
+ }
+
+ var displayItemOnSeparateRowOnlyForSelectedRow = () => {
+ return (item, rowIndex) => {
+ if (rowIndex == (selectedRow)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ const onRowClick = (event, rowIndex) => {
+ setSelectedRow(Number(rowIndex));
+ if (typeof displayItemOnSeparateRowIfOverlap === 'function') {
+ setDisplayItemOnSeparateRowIfOverlap(() => displayItemOnSeparateRowOnlyForSelectedRow());
+ }
+ }
+
+ return (
+ <>
+
+
+
+ rowIndex == selectedRow ? DEFAULT_ROW_CLASS + " selected-row" : undefined}>
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }
+ />
+ >
+ );
+ };
\ No newline at end of file
diff --git a/demo-app/src/stories/dragToCreate/DragToCreate.stories.mdx b/demo-app/src/stories/dragToCreate/DragToCreate.stories.mdx
new file mode 100644
index 00000000..2b3ae4d2
--- /dev/null
+++ b/demo-app/src/stories/dragToCreate/DragToCreate.stories.mdx
@@ -0,0 +1,20 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline, ItemRenderer } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Drag to create
+
+Drag to create mechanism requires the property Timeline.onDragToCreateEnded to be set.
+## Entering the drag to create mode
+
+ It exists 2 ways for entering in ** Drag to create mode ** :
+ * ** The default one **: by clicking on "Drag to create" menu entry.
+ In this case you can exit either by pressing the `Cancel` button displayed in the opened popup or by simply clicking the gantt diagram.
+ After you finish creating a segment, it automatically exits the drag to create mode
+ * By setting Timeline.forceDragToCreateMode to true. Setting it to false it exists the drag to create mode. If this property is set, the default mechanism doesn't work anymore (so there will be no "Drag to create" menu entry, no popup and the drag to create mode will remain active when clicking on gantt diagram)
+
+## `Timeline`
+
+
diff --git a/demo-app/src/stories/dragToCreate/DragToCreate.stories.tsx b/demo-app/src/stories/dragToCreate/DragToCreate.stories.tsx
new file mode 100644
index 00000000..fdb40b4f
--- /dev/null
+++ b/demo-app/src/stories/dragToCreate/DragToCreate.stories.tsx
@@ -0,0 +1,71 @@
+import React, { useState } from 'react';
+import { Timeline, DragToCreateParam, Item } from '@famiprog-foundation/react-gantt';
+import { d, someHumanResources, someTasks } from '../sampleData';
+import { dragToCreateScenarios } from './DragToCreateScenarios';
+import { Form, Radio } from 'semantic-ui-react';
+import { createTestids } from '@famiprog-foundation/tests-are-demo';
+import { Table, Column, DataCell} from 'fixed-data-table-2';
+
+export default {
+ title: 'Features/Drag to create',
+ includeStories: /^[A-Z]/
+};
+
+export const dragToCreateStoriesTestIds = createTestids('DragToCreateStory', {forceDragToCreateModeTrueRadio:'', forceDragToCreateModeFalseRadio:''});
+
+export const Main = () => {
+ let groups = [...someHumanResources, { id: 4, title: 'Andy' }];
+ const [forceDragToCreateMode, setForceDragToCreateMode] = useState();
+ const [tasks, setTasks] = useState([...someTasks]);
+ const handleRadioChange = (e, { value }) => setForceDragToCreateMode(value);
+ return <>
+
+
+
+
+
+
+
+
+
+
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }
+ onDragToCreateEnded={(param: DragToCreateParam) => {
+ if (groups[param.groupIndex]) {
+ const task = {
+ key: param.itemIndex,
+ row: param.groupIndex, title: 'Task ' + groups[param.groupIndex].title + param.itemIndex,
+ start: param.itemStart,
+ end: param.itemEnd || param.itemStart
+ }
+ setTasks([...tasks, task]);
+ }
+ }} />
+ >
+};
+
+Main.parameters = {
+ scenarios: Object.keys(dragToCreateScenarios).map(key => dragToCreateScenarios[key])
+};
diff --git a/demo-app/src/stories/dragToCreate/DragToCreateScenarios.ts b/demo-app/src/stories/dragToCreate/DragToCreateScenarios.ts
new file mode 100644
index 00000000..cf2062da
--- /dev/null
+++ b/demo-app/src/stories/dragToCreate/DragToCreateScenarios.ts
@@ -0,0 +1,9 @@
+export const dragToCreateScenarios = {
+ whenClickMenuButton: "WHEN click on the menu button, THEN the menu opens",
+ whenClickAddMenuEntry: "WHEN click on the 'Add (drag to create)' menu entry, THEN the Gantt goes into the 'drag to create mode'",
+ givenDragToCreateModeWhenClickCancelFromMenu: "GIVEN drag to create mode, WHEN click on cancel (from the menu), THEN mode is cancelled",
+ givenDragToCreateModeWhenClickCancelFromPopup: "GIVEN drag to create mode, WHEN click on cancel (from the popup), THEN mode is cancelled",
+ givenDragToCreateModeWhenClickAndDrag: "GIVEN drag to create mode, WHEN click and drag, THEN a green selection rectangle appears",
+ givenDragToCreateModeInProgressWhenRightClick: "GIVEN drag to create in progress, WHEN right click, THEN cancel",
+ givenDragToCreateModeInProgressWhenMouseUp: "GIVEN drag to create in progress, WHEN mouse up, THEN handler is called"
+};
diff --git a/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.mdx b/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.mdx
new file mode 100644
index 00000000..ea491103
--- /dev/null
+++ b/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.mdx
@@ -0,0 +1,9 @@
+import { Meta } from '@storybook/addon-docs';
+
+
+
+## Dynamic configuration changes
+
+This story shows how Gantt diagram responds to dynamic configuration changes.
+
+Some examples of properties that can change dynamically are: `startDate`, `endDate`
diff --git a/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.tsx b/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.tsx
new file mode 100644
index 00000000..67c79fc4
--- /dev/null
+++ b/demo-app/src/stories/dynamicConfiguration/DynamicConfiguration.stories.tsx
@@ -0,0 +1,56 @@
+import { Table, Column, DataCell} from 'fixed-data-table-2';
+import { generateRandomRowsAndItems, lotsOfGroups, lotsOfItems } from "../sampleData";
+import { Group, Item, Timeline } from '@famiprog-foundation/react-gantt';
+import { Button } from 'semantic-ui-react';
+import { useState } from 'react';
+import moment from 'moment';
+import { createTestids } from '@famiprog-foundation/tests-are-demo';
+import { generateRandomRow } from '../sampleData';
+
+export default {
+ title: 'Features/Dynamic Configuration',
+ includeStories: /^[A-Z]/
+};
+
+export const testIds = createTestids('DynamicConfigurationStory', {
+ changeDisplayIntervalButton: '',
+ changeVerticalScrollPosition: ''
+});
+
+export const Main = () => {
+ const [hoursAddition, setHoursAddition] = useState(0);
+ const [verticalScrollPosition, setVerticalScrollPosition] = useState(0);
+ const [rowsAndItems, setRowsAndItems] = useState<[Group[], Item[]]>([lotsOfGroups, lotsOfItems]);
+ return <>
+
+
+
+
+
+
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < rowsAndItems[0].length ? rowsAndItems[0][rowIndex].title : ""}}/>
+ }>
+
+ >
+}
\ No newline at end of file
diff --git a/demo-app/src/stories/itemRenderer/ItemRenderer.stories.mdx b/demo-app/src/stories/itemRenderer/ItemRenderer.stories.mdx
new file mode 100644
index 00000000..b5a618f0
--- /dev/null
+++ b/demo-app/src/stories/itemRenderer/ItemRenderer.stories.mdx
@@ -0,0 +1,27 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline, ItemRenderer } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## `Timeline`
+
+
+
+## `ItemRenderer`
+
+For each item, an `ItemRenderer` component is rendered. It has the following interesting props:
+
+
+
+## Extending/overriding `ItemRenderer`
+
+If you create your **own subclass of `ItemRenderer`**, you may override its functions (see ItemRenderer API Doc). Some possible scenarios:
+* the fields are named differently for all the items;
+* or the background of the items should be a solid color, not be a gradient;
+* or maybe depending on the type of item, some should use a gradient, and some should not;
+* or the title of item is based on multiple fiels, i.e. the duration of the item should be shown in the title;
+* or maybe some items need different style or class name depending on the type of item.
+
+The scenarios above are examples for the case you are constrained to adapt the `ItemRenderer` to the shape of the data. However, this is something that you should avoid. By default,
+try to shape the data according to the properties that `ItemRenderer` expects.
\ No newline at end of file
diff --git a/demo-app/src/stories/itemRenderer/ItemRenderer.stories.tsx b/demo-app/src/stories/itemRenderer/ItemRenderer.stories.tsx
new file mode 100644
index 00000000..d7e4497b
--- /dev/null
+++ b/demo-app/src/stories/itemRenderer/ItemRenderer.stories.tsx
@@ -0,0 +1,240 @@
+import {Alert} from 'antd';
+import React from 'react';
+import { Timeline, Item, ItemRenderer } from '@famiprog-foundation/react-gantt';
+import {d, someHumanResources, someTasks} from '../sampleData';
+import {itemRendererScenarios} from './ItemRendererScenarios';
+import {timelineScenarios} from '../TimelineScenarios';
+import { ComponentStory } from '@storybook/react';
+import { Table, Column, DataCell} from 'fixed-data-table-2';
+
+export default {
+ title: 'Features/Item Renderer'
+};
+
+export const Main = () => {
+ const tasks: Item[] = [
+ ...someTasks,
+ {
+ key: 11,
+ row: 3,
+ title: 'With style',
+ start: d('2018-09-20 7:00'),
+ end: d('2018-09-20 8:00'),
+ style: {
+ opacity: 0.5,
+ border: '2px blue solid',
+ borderRadius: '7px'
+ }
+ },
+ {
+ key: 12,
+ row: 3,
+ title: 'With class',
+ start: d('2018-09-20 9:00'),
+ end: d('2018-09-20 10:00'),
+ className: 'story-custom-item-class'
+ },
+ {
+ key: 13,
+ row: 3,
+ title: 'With color and tooltip',
+ start: d('2018-09-20 10:30'),
+ end: d('2018-09-20 12:45'),
+ color: '#FFA215',
+ tooltip: 'I am tooltip'
+ },
+ {
+ key: 14,
+ row: 3,
+ title: 'With gradient, but w/o glow',
+ start: d('2018-09-20 13:00'),
+ end: d('2018-09-20 15:25'),
+ color: 'red',
+ gradientStop: 10,
+ gradientBrightness: 0.7,
+ gradientReverseDirection: true,
+ glowOnHover: false
+ }
+ ];
+ return (
+ <>
+
+ The last row has items w/ props that are rendered by ItemRenderer.
+ >
+ }
+ />
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }/>
+ >
+ );
+};
+
+Main.parameters = {
+ scenarios: [
+ itemRendererScenarios.title,
+ itemRendererScenarios.tooltip,
+ itemRendererScenarios.glowOnHover,
+ itemRendererScenarios.color,
+ itemRendererScenarios.gradientBrightness,
+ itemRendererScenarios.gradientStop,
+ itemRendererScenarios.gradientReverseDirection,
+ itemRendererScenarios.className,
+ itemRendererScenarios.style
+ ]
+};
+
+export const DefaultPropsForItemRenderer = () => {
+ return (
+ <>
+
+ All the ItemRenderers have the same (default) props.
+ >
+ }
+ />
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }
+ itemRendererDefaultProps={{
+ className: 'story-custom-item-class',
+ color: 'red'
+ }}
+ />
+ >
+ );
+};
+
+DefaultPropsForItemRenderer.parameters = {
+ scenarios: [timelineScenarios.propertyItemRendererDefaultProps]
+};
+
+type CustomTask = Item & {
+ type?: string,
+ spentHours?: number,
+ allTestsPassed?: boolean
+}
+
+export const CustomItemRenderer = () => {
+ const tasks: CustomTask[] = [...someTasks];
+ tasks[0].type = 'analysis';
+ tasks[0].spentHours = 24;
+ tasks[3].type = 'analysis';
+ tasks[3].spentHours = 4;
+
+ tasks[1].type = 'development';
+ tasks[2].type = 'testing';
+ tasks[2].allTestsPassed = true;
+ tasks[4].type = 'testing';
+ tasks[4].allTestsPassed = false;
+
+ // custom item renderer that delegates to other renders based on the type of task
+ class CustomItemRenderer extends ItemRenderer {
+ render() {
+ const {type}: CustomTask = this.props.item;
+ if (!type) {
+ return super.render();
+ }
+ if (type === 'analysis') {
+ return ;
+ } else if (type === 'development') {
+ return ;
+ } else {
+ return ;
+ }
+ }
+ }
+
+ class AnalysisItemRenderer extends ItemRenderer {
+ // we override the actual renderer of the title
+ getTitle() {
+ return (
+ <>
+ [A] {super.getTitle()} {(this.props.item as CustomTask).spentHours}
+ >
+ );
+ }
+
+ // text color depending data in the item
+ getTextColor() {
+ const { spentHours } = this.props.item as CustomTask;
+ return (spentHours && spentHours > 10) ? 'yellow' : 'black';
+ }
+ }
+
+ class DevelopmentItemRenderer extends ItemRenderer {
+ // override to return a solid color
+ getBackgroundGradient() {
+ return this.getColor();
+ }
+
+ getClassName() {
+ return super.getClassName() + ' story-custom-item-class';
+ }
+ }
+
+ class TestingItemRenderer extends ItemRenderer {
+ getColor() {
+ return (this.props.item as CustomTask).allTestsPassed ? 'green' : 'red';
+ }
+
+ getStyle() {
+ return {
+ ...super.getStyle(),
+ borderRadius: '8px'
+ };
+ }
+
+ getHeight() {
+ return '20px';
+ }
+ }
+
+ return (
+ <>
+
+ We have different custom item renderers, based on the "task type". They can modify the known props, based on
+ logic specific to each item. And they can also process new props, unknown to ItemRenderer.
+ >
+ }
+ />
+
+ Title}
+ cell={({rowIndex}) => {rowIndex < someHumanResources.length ? someHumanResources[rowIndex].title : ""}}/>
+ }
+ itemRenderer={CustomItemRenderer}
+ />
+ >
+ );
+};
+
+CustomItemRenderer.parameters = {
+ scenarios: [timelineScenarios.propertyItemRenderer]
+};
diff --git a/demo-app/src/stories/itemRenderer/ItemRendererScenarios.ts b/demo-app/src/stories/itemRenderer/ItemRendererScenarios.ts
new file mode 100644
index 00000000..3fc49b51
--- /dev/null
+++ b/demo-app/src/stories/itemRenderer/ItemRendererScenarios.ts
@@ -0,0 +1,12 @@
+export const itemRendererScenarios = {
+ title: 'PROPERTY title',
+ tooltip: 'PROPERTY tooltip',
+ height: 'PROPERTY height',
+ glowOnHover: 'PROPERTY glowOnHover',
+ color: 'PROPERTY color',
+ gradientBrightness: 'PROPERTY gradientBrightness',
+ gradientStop: 'PROPERTY gradientStop',
+ gradientReverseDirection: 'PROPERTY gradientReverseDirection',
+ style: 'PROPERTY style',
+ className: 'PROPERTY className'
+};
diff --git a/demo-app/src/stories/sampleData.ts b/demo-app/src/stories/sampleData.ts
new file mode 100644
index 00000000..163bb55b
--- /dev/null
+++ b/demo-app/src/stories/sampleData.ts
@@ -0,0 +1,150 @@
+import moment, { Moment } from 'moment';
+import { Group, Item } from '@famiprog-foundation/react-gantt';
+
+////////////////////////////////////////////////////////
+// utility functions used for hardcoding our sample data
+////////////////////////////////////////////////////////
+export const d = (str: moment.MomentInput) => moment(str).valueOf();
+
+export const endOfCurrentMonth = () => d(moment().endOf('month'));
+
+export const startOfCurrentMonth = () => d(moment().startOf('month'));
+
+export const dateAndHourOfCurrentMonth = (day, hour = 0) => d(moment().startOf('month').add('days', day-1).add('hours', hour));
+
+export const dateAndHourOfMonth = (monthBegining, day, hour = 0) => d(monthBegining.startOf('month').add('days', day-1).add('hours', hour));
+
+////////////////////////////////////////////////////////
+// sample data
+////////////////////////////////////////////////////////
+export type Employee = Group & {
+ job?: string,
+ team?: string
+}
+
+export const someHumanResources: Employee[] = [
+ {id: 0, title: 'John Doe', job: 'HR manager', team: 'Team 1'},
+ {id: 1, title: 'Alex Randal', job: 'Recruiter', team: 'Team 2'},
+ {id: 2, title: 'Mary Danton', job: 'Developer', team: 'Team 3'},
+ {id: 3, title: 'Kim Price', job: 'Developer', team: 'Team 3'}
+];
+
+// 10 rows, so it's easy to remember in stories: new tasks start from 11
+export const someTasks: Item[] = [
+ {key: 0, row: 0, title: 'Task JD1', start: d('2018-09-20 8:00'), end: d('2018-09-20 11:00')},
+ {key: 1, row: 0, title: 'Task JD2', start: d('2018-09-20 18:00'), end: d('2018-09-20 19:00')},
+ {key: 2, row: 0, title: 'Task JD3', start: d('2018-09-20 20:00'), end: d('2018-09-20 21:00')},
+ {key: 3, row: 1, title: 'Task AR1', start: d('2018-09-20 7:00'), end: d('2018-09-20 11:30')},
+ {key: 4, row: 1, title: 'Task AR2', start: d('2018-09-20 17:00'), end: d('2018-09-20 20:00')},
+ {key: 5, row: 1, title: 'Task AR3', start: d('2018-09-20 19:00'), end: d('2018-09-20 20:00')},
+ {key: 6, row: 2, title: 'Task MD1', start: d('2018-09-20 8:00'), end: d('2018-09-20 10:00')},
+ {key: 7, row: 2, title: 'Task MD2', start: d('2018-09-20 18:00'), end: d('2018-09-20 20:00')},
+ {key: 8, row: 2, title: 'Task MD3', start: d('2018-09-20 20:00'), end: d('2018-09-20 21:00')},
+ {key: 9, row: 2, title: 'Task MD4', start: d('2018-09-20 5:00'), end: d('2018-09-20 7:00')},
+ {key: 10, row: 2, title: 'Task MD5', start: d('2018-09-20 13:00'), end: d('2018-09-20 14:00')},
+ {key: 11, row: 2, title: 'Task MD6', start: d('2018-09-20 22:00'), end: d('2018-09-20 24:00')}
+];
+
+// duplicate from someTasks, changed start/end to moment
+export const someTasks2: Item[] = [
+ {key: 0, row: 0, title: 'Task JD1', start: moment('2018-09-20 8:00'), end: moment('2018-09-20 11:00')},
+ {key: 1, row: 0, title: 'Task JD2', start: moment('2018-09-20 18:00'), end: moment('2018-09-20 19:00')},
+ {key: 2, row: 0, title: 'Task JD3', start: moment('2018-09-20 20:00'), end: moment('2018-09-20 21:00')},
+ {key: 3, row: 1, title: 'Task AR1', start: moment('2018-09-20 7:00'), end: moment('2018-09-20 11:30')},
+ {key: 4, row: 1, title: 'Task AR2', start: moment('2018-09-20 17:00'), end: moment('2018-09-20 20:00')},
+ {key: 5, row: 1, title: 'Task AR3', start: moment('2018-09-20 19:00'), end: moment('2018-09-20 20:00')},
+ {key: 6, row: 2, title: 'Task MD1', start: moment('2018-09-20 8:00'), end: moment('2018-09-20 10:00')},
+ {key: 7, row: 2, title: 'Task MD2', start: moment('2018-09-20 18:00'), end: moment('2018-09-20 20:00')},
+ {key: 8, row: 2, title: 'Task MD3', start: moment('2018-09-20 20:00'), end: moment('2018-09-20 21:00')},
+ {key: 9, row: 2, title: 'Task MD4', start: moment('2018-09-20 5:00'), end: moment('2018-09-20 7:00')},
+ {key: 10, row: 2, title: 'Task MD5', start: moment('2018-09-20 13:00'), end: moment('2018-09-20 14:00')},
+ {key: 11, row: 2, title: 'Task MD6', start: moment('2018-09-20 22:00'), end: moment('2018-09-20 24:00')}
+];
+
+export const manyHumanResources: Employee[] = [...someHumanResources, { id: 4, title: 'George Walsh', job: 'Developer' },
+{ id: 5, title: 'Mary McDonald', job: 'Developer' },
+{ id: 6, title: 'Mary A. McDonald', job: 'Developer'},
+{ id: 7, title: 'John Rider', job: 'Developer'},
+{ id: 8, title: 'Tom Smith', job: 'Developer'},
+{ id: 9, title: 'David Johnson', job: 'Developer'},
+{ id: 10, title: 'James Johnson', job: 'Developer'},
+{ id: 11, title: 'Maria Garcia', job: 'Developer'},
+{ id: 12, title: 'Michael Smith', job: 'Developer'},
+{ id: 13, title: 'David Brown', job: 'Developer'},
+{ id: 14, title: 'Mary B. McDonald', job: 'Developer'},
+{ id: 15, title: 'John B. Rider', job: 'Developer'},
+{ id: 16, title: 'Tom B. Smith', job: 'Developer'},
+{ id: 17, title: 'David B. Johnson', job: 'Developer'},
+{ id: 18, title: 'James B. Johnson', job: 'Developer'},
+{ id: 19, title: 'Maria B. Garcia', job: 'Developer'},
+{ id: 20, title: 'Michael B. Smith', job: 'Developer'},
+{ id: 21, title: 'David B. Brown', job: 'Developer'},
+{ id: 22, title: 'Michael C. Smith', job: 'Developer'},
+{ id: 23, title: 'David C. Brown', job: 'Developer'},
+{ id: 24, title: 'Michael D. Smith', job: 'Developer'},
+{ id: 25, title: 'David D. Brown', job: 'Developer'},
+{ id: 26, title: 'Michael E. Smith', job: 'Developer'},
+{ id: 27, title: 'David E. Brown', job: 'Developer'}];
+
+const ITEM_DURATIONS = [moment.duration(6, 'hours'), moment.duration(12, 'hours'), moment.duration(18, 'hours')];
+const COLORS = ['#0099cc', '#f03a36', '#06ad96', '#fce05b', '#dd5900', '#cc6699'];
+
+export const [lotsOfGroups, lotsOfItems] = generateRandomRowsAndItems(100, 30, true, 60, moment('2018-07-31'), moment('2018-10-30'));
+
+export function generateRandomRowsAndItems(numberOfRows, numberOfItemsPerRow: number, useMoment: boolean, snap: number, minDate: Moment, maxDate: Moment): [Group[], Item[]] {
+ const lotsOfGroups:Group[] = [];
+ const lotsOfItems:Item[] = [];
+
+ if (lotsOfGroups.length == 0) {
+ for (let i = 0; i < numberOfRows; i++) {
+ const randomGroupWithItems = generateRandomRow(i, numberOfItemsPerRow, useMoment, snap, minDate, maxDate);
+ lotsOfGroups.push(randomGroupWithItems[0]);
+ lotsOfItems.push(...randomGroupWithItems[1]);
+ }
+ }
+ return [lotsOfGroups, lotsOfItems];
+}
+
+export function generateRandomRow(rowIndex:number, numberOfItemsPerRow: number, useMoment: boolean, snap: number, minDate: Moment, maxDate: Moment): [Group, Item[]] {
+ const row = {id: rowIndex, title: `Row ${rowIndex}`, description: `Description for row ${rowIndex}`};
+ const items = [];
+ let key = rowIndex * numberOfItemsPerRow - 1;
+ for (let j = 0; j < numberOfItemsPerRow; j++) {
+ key += 1;
+ const colorIndex = (rowIndex + j) % (COLORS.length + 1);
+ const color = colorIndex != COLORS.length + 1 ? COLORS[colorIndex] : '';
+ const gradientStop = Math.random() * 100;
+ let glowOnHover = false;
+ let tooltip;
+ if ((rowIndex + j) % 3 === 0) {
+ glowOnHover = true;
+ tooltip = 'Item with key=' + key;
+ }
+ const duration = ITEM_DURATIONS[Math.floor(Math.random() * ITEM_DURATIONS.length)];
+ let start = moment(
+ Math.floor(
+ Math.random() * (maxDate.valueOf() - minDate.valueOf()) + minDate.valueOf()
+ )
+ );
+ let end = start.clone().add(duration);
+
+ // Round to the nearest snap distance
+ const roundedStartSeconds = Math.floor(start.second() / snap) * snap;
+ const roundedEndSeconds = Math.floor(end.second() / snap) * snap;
+ start.second(roundedStartSeconds);
+ end.second(roundedEndSeconds);
+
+ items.push({
+ key: key,
+ title: duration.humanize(),
+ color,
+ row: rowIndex,
+ start: useMoment ? start : start.valueOf(),
+ end: useMoment ? end : end.valueOf(),
+ glowOnHover,
+ gradientStop,
+ tooltip
+ });
+ }
+ return [row, items]
+}
\ No newline at end of file
diff --git a/demo-app/src/stories/scrollbar/Scrollbar.stories.tsx b/demo-app/src/stories/scrollbar/Scrollbar.stories.tsx
new file mode 100644
index 00000000..f11a1b2a
--- /dev/null
+++ b/demo-app/src/stories/scrollbar/Scrollbar.stories.tsx
@@ -0,0 +1,133 @@
+import SplitPane from "react-split-pane";
+import { Direction, Scrollbar } from "@famiprog-foundation/react-gantt";
+import { useRef, useState } from "react";
+import { Alert } from "antd";
+import Measure from 'react-measure';
+
+export default {
+ title: 'Components/Scrollbar'
+};
+
+export const HorizontalScrollBar = () => {
+ const divContentWidth1 = 700;
+ const divContentWidth2 = 700;
+ const totalWidth = 800;
+ const [divWidth1, setDivWidth1] = useState(totalWidth / 2);
+ const [divWidth2, setDivWidth2] = useState(0);
+ const div1 = useRef();
+ const div2 = useRef();
+ return (
+ <>
+
+ Drag the split panes to rezise the colored divs and the coresponding scrollbars
+ >
+ }
+ />
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/demo-app/src/stories/storybook.css b/demo-app/src/stories/storybook.css
new file mode 100644
index 00000000..43e07121
--- /dev/null
+++ b/demo-app/src/stories/storybook.css
@@ -0,0 +1,60 @@
+#root,
+/*
+ For a doc page, the div w/ id="storybook-root" still exists; it has an attribute hidden (which has a selector to make display: none
+ Hence we want this style NOT to be applied IF id = storybook-root AND has attribute hidden
+*/
+#storybook-root:not([hidden]) {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.demo {
+ height: 100%;
+ display: flex;
+ gap: 5px;
+ flex-direction: column;
+}
+
+.story-custom-highlighted-interval-class {
+ opacity: 0.5 !important;
+}
+
+.story-custom-highlighted-weekends-class {
+ background: #ceefed !important;
+}
+
+.story-custom-item-class {
+ opacity: 1;
+ border: #d47b37 3px solid;
+ border-radius: 0;
+}
+
+.story-custom-marker-class {
+ background: #03c61a !important;
+}
+
+.story-custom-now-marker-class {
+ background: #f28de6 !important;
+}
+
+.story-custom-vertical-grid-class {
+ border-left: 1px solid #209ad8 !important;
+}
+
+.story-custom-row {
+ border-bottom: 1px solid #94b9cf !important;
+}
+
+.story-custom-row-even {
+ background-color: #dbe8f0 !important;
+}
+
+.story-custom-row-odd {
+ background-color: #f4f7f8 !important;
+}
+
+.selected-row {
+ background-color: #ffff001f !important;
+}
diff --git a/demo-app/src/stories/table/Table.stories.mdx b/demo-app/src/stories/table/Table.stories.mdx
new file mode 100644
index 00000000..e2b192ad
--- /dev/null
+++ b/demo-app/src/stories/table/Table.stories.mdx
@@ -0,0 +1,28 @@
+import { Meta, ArgsTable } from '@storybook/addon-docs';
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import { encodeApiDocURIForSubpath, parametersDocPage } from '../StorybookUtils';
+
+
+
+## Custom table
+ By default the gantt diagram doesn't have any associated table.
+
+You can add one table that will be displayed in the left side of the gantt diagram by setting the Timeline.table property. It should be a fixed-data-table component. You can check this page for examples of table customizations.
+
+It is mandatory to have set a width for this table
+
+**IMPORTANT:** The cell renderer of your custom table should take in consideration that there could be empty rows (without any data behind) added by gantt just for filling in the remaining empty space
+
+
+
+## `onSplitChange`
+
+The Gantt component is splitted between the table and the actual gantt diagram.
+Initialy the size of the split equals to the table width.
+
+The split works in two modes:
+1. Controlled: `onSplitChange` is provided by the user in order to manage the width of the table by itself.
+2. Uncontrolled: no `onSplitChange` is provided by the user. Gantt internally changes the width of the table when the split changes
+
+
+
diff --git a/demo-app/src/stories/table/Table.stories.tsx b/demo-app/src/stories/table/Table.stories.tsx
new file mode 100644
index 00000000..32b88dd8
--- /dev/null
+++ b/demo-app/src/stories/table/Table.stories.tsx
@@ -0,0 +1,86 @@
+import { ComponentStory } from "@storybook/react";
+import { Fragment, useState } from "react";
+import { Checkbox, Icon } from "semantic-ui-react";
+import { Timeline } from '@famiprog-foundation/react-gantt';
+import { d, manyHumanResources, someTasks } from "../sampleData";
+
+import { Column, DataCell, Table } from "fixed-data-table-2";
+import { DEMO_TABLE_WIDTH, tableScenarios, tableTestIds } from "./TableScenarios";
+import { Alert } from "antd";
+export default {
+ title: 'Features/Table',
+ component: Timeline
+};
+
+export const GanttWithoutTable: ComponentStory = () => {
+
+ return (
+
+
+
+ );
+}
+
+GanttWithoutTable.parameters = {
+ scenarios: [tableScenarios.propertyTable]
+}
+
+var emphasizeStyle = { color: 'red' };
+
+const headerStyle = {
+ color: '#000',
+ fontSize: '12px',
+ lineHeight: '1',
+ background: '#CCFFEE',
+ border: 'none'
+};
+
+export const ProvidingCustomTable: ComponentStory = () => {
+ const [tableWidth, setTableWidth] = useState(DEMO_TABLE_WIDTH);
+ return (
+
+ Table width: {tableWidth} }/>
+ setTableWidth(size)}
+ table={