diff --git a/Glossary_wip.md b/Glossary_wip.md deleted file mode 100644 index fec4da9..0000000 --- a/Glossary_wip.md +++ /dev/null @@ -1,27 +0,0 @@ -# Glossary - -| Term | Definition | -| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| **Behavior-Driven** | A testing methodology that encourages collaboration between developers, QA, and non-technical stakeholders to define test cases. | -| **Data-Driven Specification** | A testing approach where test cases are executed with multiple sets of data to validate functionality. | -| **Generic Test Automation Architecture (gTAA)** | A framework that provides a structured approach to test automation, promoting reusability and maintainability. | -| **Keywords** | Reusable functions or actions defined in the test automation framework. | -| **Keyword-Driven** | A testing approach where test cases are defined using keywords that represent actions or operations. | -| **Library** | A collection of keywords and functions that can be used in test automation. | -| **Libdoc** | A tool used to generate keyword documentation for libraries and resource files. | -| **Rebot** | The main executable used to execute suites and post-process execution results to generate reports. | -| **Resource Files** | Files that contain shared keywords and variables that can be imported into test suites. | -| **Root Suite** | The top-level suite that contains all other suites and test cases. | -| **Suite Directory** | A directory that contains multiple suite files, which can include test cases and tasks organized hierarchically. | -| **Suite File** | A \*.robot file that contains at least one test case or task. | -| **Task** | A unit of work that can be executed, similar to a test case but typically focused on automation tasks. | -| **Task Suite** | Suite files that have at least one task and do not contain any test cases. | -| **Test Automation** | The use of software tools to execute tests automatically, reducing manual effort. | -| **Test Cases Section** | This section defines the executable elements of a suite, specifically test cases. | -| **Test Suite** | Suite files that have at least one test case and do not contain any tasks. | -| **Tasks Section** | This section defines the executable elements of a suite, specifically tasks. | -| **Comments Section** | This section is used to add comments to the suite file or resource file. All content in this section is ignored by Robot Framework. | -| **Keyword Section** | This section allows you to define locally scoped user keywords that can only be used within the same suite where they are defined. | -| **Robot Framework Sections** | Different parts of a Robot Framework suite file that organize the content. | -| **Settings Section** | This section is used to configure various aspects of the test/task suite. | -| **Variables Section** | This section is used to define suite variables that are used in the suite or its tests/tasks or inside their keywords. | diff --git a/LOs.csv b/LOs.csv index f072ba2..83be89a 100644 --- a/LOs.csv +++ b/LOs.csv @@ -50,7 +50,7 @@ LO-2.5.2.3,(K1),Recall the concept of keywords with embedded arguments used in B LO-2.5.2.4,(K1),"Recall how ""Positional or Named Arguments"" are marked in the documentation and their use case.",,, LO-2.5.2.5,(K1),"Recall how ""Variable Number of Positional Arguments"" are marked in the documentation and their use case.",,, LO-2.5.2.6,(K1),"Recall what properties ""Named-Only Arguments"" have and how they are documented.",,, -LO-2.5.2.7,(K1),Recall how free named arguments are marked in documentation.,,, +LO-2.5.2.7,(K1),"Recall how ""Free Named Arguments"" are marked in documentation.",,, LO-2.5.2.8,(K2),Understand the concept of argument types and automatic type conversion.,,, LO-2.5.2.9,(K2),Understand the concept of return type hints.,,, LO-2.5.3,(K2),Understand how to read keyword documentation and how to interpret the examples.,,, diff --git a/README.md b/README.md index 0c81f8c..0d77c7e 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ - [`2.5.2.6 Named-Only Arguments`](website/docs/chapter-02/05_keyword_interface.md#2526-named-only-arguments) - LO-2.5.2.6 (K1) Recall what properties "Named-Only Arguments" have and how they are documented. - [`2.5.2.7 Free Named Arguments`](website/docs/chapter-02/05_keyword_interface.md#2527-free-named-arguments) - - LO-2.5.2.7 (K1) Recall how free named arguments are marked in documentation. + - LO-2.5.2.7 (K1) Recall how "Free Named Arguments" are marked in documentation. - [`2.5.2.8 Argument Types`](website/docs/chapter-02/05_keyword_interface.md#2528-argument-types) - LO-2.5.2.8 (K2) Understand the concept of argument types and automatic type conversion. - [`2.5.2.9 Return Types`](website/docs/chapter-02/05_keyword_interface.md#2529-return-types) diff --git a/website/.gitignore b/website/.gitignore index b2d6de3..4244041 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -8,6 +8,16 @@ .docusaurus .cache-loader +# Build artifacts - TypeScript compiled JS files from TS sources +docusaurus.config.js +sidebars.js +/src/components/**/*.js +/src/pages/**/*.js +/src/theme/**/*.js +# Keep these JS files that are source files, not build artifacts: +!/src/components/Quiz/quizPrebuild.js +!/src/remark/*.js + # Misc .DS_Store .env.local diff --git a/website/docs/chapter-01/04_styles.md b/website/docs/chapter-01/04_styles.md index 5da19d4..3a7b2a8 100644 --- a/website/docs/chapter-01/04_styles.md +++ b/website/docs/chapter-01/04_styles.md @@ -16,7 +16,7 @@ While **Keyword-Driven Testing (KDT)** and **Behavior-Driven Development (BDD)** Both styles can be mixed, even within the same test or task, but it is strongly recommended to have separate styles for separate purposes and not mix them within the same body. One practical solution would be to define acceptance test cases that cover users' expectations in a declarative *Behavior-Driven Style*, while using keywords that are implemented in an imperative *Keyword-Driven style*. -Further system level test cases, that are not covering acceptance criteria could be written in a *Keyword-Driven style*. +Further system level :term[test cases]{term="Test Case"}, that are not covering acceptance criteria could be written in a *Keyword-Driven style*. The approach of both styles is different in that way, that the *Behavior-Driven Style* is a **declarative** specification, diff --git a/website/docs/chapter-02/05_keyword_interface.md b/website/docs/chapter-02/05_keyword_interface.md index 0c7e930..ac13d0a 100644 --- a/website/docs/chapter-02/05_keyword_interface.md +++ b/website/docs/chapter-02/05_keyword_interface.md @@ -70,14 +70,14 @@ All of them can be called positionally or by name. ![Run Process Keyword Documentation](/img/Run_Process_Docs.png) -This keyword has one :term[Mandatory Arguments]{tooltipMd="An **Argument** that must be set.
See [Mandatory Args](chapter-03/03_user_keyword.md)"} `command` which can be called positionally or by name. +This keyword has one Mandatory Argument `command` which can be called positionally or by name. The latter two arguments are optional. -The argument `arguments` is a "Variable Number of Positional Arguments" and can only be set by position. +The argument `arguments` is a :term[Variable Number of Positional Arguments] and can only be set by position. Therefore, if it shall be set, all preceding arguments must be set by position as well. See [2.5.2.5 Variable Number of Positional Arguments](chapter-02/05_keyword_interface.md#2525-variable-number-of-positional-arguments) for more information about this kind of argument. -The argument `configuration` is a "Free Named Argument" and can only be set by names. +The argument `configuration` is a :term[Free Named Argument] and can only be set by names. See [2.5.2.7 Free Named Arguments](chapter-02/05_keyword_interface.md#2527-free-named-arguments) for more information about this kind of argument. @@ -92,11 +92,11 @@ See [2.5.2.7 Free Named Arguments](chapter-02/05_keyword_interface.md#2527-free- This keyword has 2 "Mandatory Arguments" that can be called positionally or by name. The last two arguments are optional. -The argument `groups` is a "Variable Number of Positional Arguments" and can only be set by position. +The argument `groups` is a :term[Variable Number of Positional Arguments] and can only be set by position. Therefore, if it shall be set, all preceding arguments must be set by position as well. See [2.5.2.5 Variable Number of Positional Arguments](chapter-02/05_keyword_interface.md#2525-variable-number-of-positional-arguments) for more information about this kind of argument. -The argument `flags` is a "Named-Only Argument" and can only be set by name. +The argument `flags` is a :term[Named-Only Argument] and can only be set by name. See [2.5.2.6 Named-Only Arguments](chapter-02/05_keyword_interface.md#2526-named-only-arguments) for more information about this kind of argument. @@ -118,20 +118,20 @@ The more business oriented keywords are the less arguments they typically have. Keyword arguments can be grouped into different argument kinds. On the one hand you can group them by their definition attributes and on the other hand by their usage kind. -The relevant distinction of usage kinds is between using **Positional Arguments**, **Named Arguments**, or **Embedded Arguments**. +The relevant distinction of usage kinds is between using :term[Positional Arguments]{term="Positional Argument"}, :term[Named Arguments]{term="Named Argument"}, or :term[Embedded Arguments]{term="Embedded Argument"}. How to use them is described in [2.6 Writing Test|Task and Calling Keywords](chapter-02/06_writing_test.md). Another important information is if an argument is mandatory or optional. See the next two sections for more information about these two kinds of arguments. Most arguments can either be set by their position or by their name. -But there are some kinds of arguments that can only be set positionally, like **Variable Number of Positional Arguments**, or only be set named, like **Named-Only Arguments** or **Free Named Arguments**. +But there are some kinds of arguments that can only be set positionally, like :term[Variable Number of Positional Arguments], or only be set named, like :term[Named-Only Arguments]{term="Named-Only Argument"} or :term[Free Named Arguments]{term="Free Named Argument"}. The order is as follows: -1. **Positional or Named Arguments** (can be mandatory or optional) -2. **Variable Number of Positional Arguments** (optional) -3. **Named-Only Arguments** (can be mandatory or optional) -4. **Free Named Arguments** (optional) +1. :term[Positional or Named Arguments]{term="Positional or Named Argument"} (can be mandatory or optional) +2. :term[Variable Number of Positional Arguments] (optional) +3. :term[Named-Only Arguments]{term="Named-Only Argument"} (can be mandatory or optional) +4. :term[Free Named Arguments]{term="Free Named Argument"} (optional) ### 2.5.2.1 Mandatory Arguments @@ -189,7 +189,7 @@ Arguments that have a default value can be omitted when the keyword is called, c These arguments are listed after the mandatory arguments in the argument interface. Default values are defined and represented in the docs by the equal sign `=` after the argument name and a value after that. -Also "Variable Number of Positional Arguments", represented with a single star (`*`) prefix, and "Free Named Arguments", represented with a double star (`**`) prefix are optional arguments. +Also :term[Variable Number of Positional Arguments], represented with a single star (`*`) prefix, and :term[Free Named Arguments]{term="Free Named Argument"}, represented with a double star (`**`) prefix are optional arguments. E.g. the argument `msg` in the `Should Be Equal` keyword documentation has the default value `None` and `ignore_case` has the default value `False`. @@ -233,7 +233,7 @@ Foundation Page should be Accessible And the url should be https://robotframework.org/foundation ``` The optional prefixes `Given`, `When`, `Then`, `And` and `But` are basically ignored by Robot Framework if a keyword is found matching the rest of the name including the embedded arguments. -In the example test case some keywords are designed so that the arguments are surrounded by double quotes (`"`) for better visibility. +In the example :term[test case] some keywords are designed so that the arguments are surrounded by double quotes (`"`) for better visibility. A mix of embedded arguments and "normal" arguments is possible to fully support BDD. In the keyword documentation the embedded arguments are written in variable syntax with dollar-curly-braces (`${var_name}`) to indicate that they are not part of the keyword name but are arguments. @@ -253,7 +253,7 @@ Recall how "Positional or Named Arguments" are marked in the documentation and t :::: Except for "Positional-Only Arguments", which are not part of this syllabus, -all arguments that are positioned before "Variable Number of Positional Arguments", "Named-Only Arguments", or "Free Named Arguments" in the argument interface of a keyword are "Positional or Named Arguments". +all arguments that are positioned before :term[Variable Number of Positional Arguments], :term[Named-Only Arguments]{term="Named-Only Argument"}, or :term[Free Named Arguments]{term="Free Named Argument"} in the argument interface of a keyword are :term[Positional or Named Arguments]{term="Positional or Named Argument"}. As their name states, they can be set either by their position or by their name, but not by both at the same time for one argument. If an argument shall be set by its position, all preceding arguments must be set by their position as well. @@ -275,7 +275,7 @@ Recall how "Variable Number of Positional Arguments" are marked in the documenta :::: -A special case of optional arguments that can only be set by their position are "Variable Number of Positional Arguments". +A special case of optional arguments that can only be set by their position are :term[Variable Number of Positional Arguments]. These are also referred to as `*args` or `*varargs` in Python. Some keywords need to collect a variable amount of values into one argument, because it is not possible to define the amount of values in advance. @@ -286,8 +286,8 @@ Depending on the command to be executed different amount of arguments are needed This variable argument is marked with a single asterisk `*` before the argument name in the keyword documentation. When calling this keyword, the first positional argument is assigned to `command`, while all subsequent positional arguments are collected into `arguments`. -Because of this behavior, no additional positional arguments can be used after these "Variable Number of Positional Arguments". -As a result, any arguments following these "Variable Number of Positional Arguments" must be named arguments, +Because of this behavior, no additional positional arguments can be used after these :term[Variable Number of Positional Arguments]. +As a result, any arguments following these :term[Variable Number of Positional Arguments] must be named arguments, regardless of whether they are mandatory or optional arguments with a default value. Also see [2.5.1.3 Example Keyword `Get Regexp Matches`](chapter-02/05_keyword_interface.md#2513-example-keyword-get-regexp-matches). @@ -305,15 +305,15 @@ Recall what properties "Named-Only Arguments" have and how they are documented. :::: -All arguments that are defined after a "Variable Number of Positional Arguments" (`*varargs`) are "Named-Only Arguments". -However it is also possible to create "Named-Only Arguments without a preceding "Variable Number of Positional Arguments". +All arguments that are defined after a :term[Variable Number of Positional Arguments] (`*varargs`) are :term[Named-Only Arguments]{term="Named-Only Argument"}. +However it is also possible to create :term[Named-Only Arguments]{term="Named-Only Argument"} without a preceding :term[Variable Number of Positional Arguments]. -"Named-Only Arguments" are marked with a "LABEL" sign `🏷` before the argument name in the keyword documentation. +:term[Named-Only Arguments]{term="Named-Only Argument"} are marked with a "LABEL" sign `🏷` before the argument name in the keyword documentation. -Those arguments can not be set positionally. All positional values would be consumed by the "Variable Number of Positional Arguments". +Those arguments can not be set positionally. All positional values would be consumed by the :term[Variable Number of Positional Arguments]. So they must be called by their name followed by an equal sign `=` and the value of the argument. -"Named-Only Arguments" can be mandatory or optional with a default value. +:term[Named-Only Arguments]{term="Named-Only Argument"} can be mandatory or optional with a default value. ### 2.5.2.7 Free Named Arguments @@ -321,14 +321,14 @@ So they must be called by their name followed by an equal sign `=` and the value :::K1[LO-2.5.2.7] -Recall how free named arguments are marked in documentation. +Recall how "Free Named Arguments" are marked in documentation. ::: :::: -Another special case of "Named-Only Arguments" are "Free Named Arguments." -These arguments are similar to the "Variable Number of Positional Arguments" in that they can collect multiple values. +Another special case of :term[Named-Only Arguments]{term="Named-Only Argument"} are :term[Free Named Arguments]{term="Free Named Argument"}. +These arguments are similar to the :term[Variable Number of Positional Arguments] in that they can collect multiple values. However, instead of collecting positional values, they gather all named values that are not explicitly defined as argument names. In this case all values given to the keyword as arguments, that do contain an unescaped equal sign (`=`) are considered as named arguments. diff --git a/website/docs/chapter-02/06_writing_test.md b/website/docs/chapter-02/06_writing_test.md index 7ebb4a9..1180f2c 100644 --- a/website/docs/chapter-02/06_writing_test.md +++ b/website/docs/chapter-02/06_writing_test.md @@ -76,7 +76,7 @@ Understand the concept of how to set argument values positionally. :::: When calling keywords, arguments can often be set positionally in the order they are defined in the keyword documentation. -An exception to this are "Named-Only Arguments" and "Free Named Arguments" that can only be set by their name. +An exception to this are :term[Named-Only Arguments]{term="Named-Only Argument"} and :term[Free Named Arguments]{term="Free Named Argument"} that can only be set by their name. However, only using positional values can lead to poor readability as you can see in the previous example: `Mixed Positional Arguments` Some keywords do not have an obvious order of arguments. @@ -100,7 +100,7 @@ Click on x and y Click On Coordinates x=82 y=70 ``` -Calling keywords that have a "Variable Number of Positional Arguments" does require to set all preceding arguments by their position if the "Variable Number of Positional Arguments" shall be set. +Calling keywords that have a :term[Variable Number of Positional Arguments] does require to set all preceding arguments by their position if the :term[Variable Number of Positional Arguments] shall be set. Example: ```robotframework @@ -134,7 +134,7 @@ Also setting one optional argument but leaving the others at their default value Named arguments are set by their name followed by an equal sign `=` and the value of the argument. All named arguments must be set after the positional arguments are set but can be set in any order. -Equal signs are valid argument values and could therefore be misinterpreted as named arguments, if the text before the equal sign is an existing argument name or if "Free Named Arguments" are available at the called keyword. +Equal signs are valid argument values and could therefore be misinterpreted as named arguments, if the text before the equal sign is an existing argument name or if :term[Free Named Arguments]{term="Free Named Argument"} are available at the called keyword. To prevent that, an equal sign in argument values can be escaped by a backslash `\`. Example of escaping conflicting equal signs: diff --git a/website/docs/chapter-03/03_user_keyword.md b/website/docs/chapter-03/03_user_keyword.md index 2e5e5d8..7a5f757 100644 --- a/website/docs/chapter-03/03_user_keyword.md +++ b/website/docs/chapter-03/03_user_keyword.md @@ -157,7 +157,7 @@ Understand the purpose and syntax of the [Arguments] setting in User Keywords. User Keywords can accept arguments, which make them more dynamic and reusable in various contexts. The `[Arguments]` setting is used to define the arguments a user keyword expects. -See also Chapter 2 [2.5.2 Keyword Arguments](chapter-02/05_keyword_interface.md#252-keyword-arguments) for an introduction to argument kinds. +See also [2.5.2 Keyword Arguments](chapter-02/05_keyword_interface.md#252-keyword-arguments) for an introduction to argument kinds. Arguments are defined by `[Arguments]` followed by the argument names separated by multiple spaces in the syntax of scalar variables. @@ -350,8 +350,8 @@ the user ${action} ### 3.3.5.4 Other Argument Kinds -Other argument kinds like **Named-Only Arguments**, **Free Named Arguments**, or -**Variable Number of Positional Arguments** should be known, +Other argument kinds like :term[Named-Only Arguments]{term="Named-Only Argument"}, :term[Free Named Arguments]{term="Free Named Argument"}, or +:term[Variable Number of Positional Arguments] should be known, but their definition and usage are not part of this syllabus. diff --git a/website/docs/glossary/Glossary.md b/website/docs/glossary/Glossary.md deleted file mode 100644 index fec4da9..0000000 --- a/website/docs/glossary/Glossary.md +++ /dev/null @@ -1,27 +0,0 @@ -# Glossary - -| Term | Definition | -| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| **Behavior-Driven** | A testing methodology that encourages collaboration between developers, QA, and non-technical stakeholders to define test cases. | -| **Data-Driven Specification** | A testing approach where test cases are executed with multiple sets of data to validate functionality. | -| **Generic Test Automation Architecture (gTAA)** | A framework that provides a structured approach to test automation, promoting reusability and maintainability. | -| **Keywords** | Reusable functions or actions defined in the test automation framework. | -| **Keyword-Driven** | A testing approach where test cases are defined using keywords that represent actions or operations. | -| **Library** | A collection of keywords and functions that can be used in test automation. | -| **Libdoc** | A tool used to generate keyword documentation for libraries and resource files. | -| **Rebot** | The main executable used to execute suites and post-process execution results to generate reports. | -| **Resource Files** | Files that contain shared keywords and variables that can be imported into test suites. | -| **Root Suite** | The top-level suite that contains all other suites and test cases. | -| **Suite Directory** | A directory that contains multiple suite files, which can include test cases and tasks organized hierarchically. | -| **Suite File** | A \*.robot file that contains at least one test case or task. | -| **Task** | A unit of work that can be executed, similar to a test case but typically focused on automation tasks. | -| **Task Suite** | Suite files that have at least one task and do not contain any test cases. | -| **Test Automation** | The use of software tools to execute tests automatically, reducing manual effort. | -| **Test Cases Section** | This section defines the executable elements of a suite, specifically test cases. | -| **Test Suite** | Suite files that have at least one test case and do not contain any tasks. | -| **Tasks Section** | This section defines the executable elements of a suite, specifically tasks. | -| **Comments Section** | This section is used to add comments to the suite file or resource file. All content in this section is ignored by Robot Framework. | -| **Keyword Section** | This section allows you to define locally scoped user keywords that can only be used within the same suite where they are defined. | -| **Robot Framework Sections** | Different parts of a Robot Framework suite file that organize the content. | -| **Settings Section** | This section is used to configure various aspects of the test/task suite. | -| **Variables Section** | This section is used to define suite variables that are used in the suite or its tests/tasks or inside their keywords. | diff --git a/website/docs/glossary/Glossary.mdx b/website/docs/glossary/Glossary.mdx new file mode 100644 index 0000000..ced04b9 --- /dev/null +++ b/website/docs/glossary/Glossary.mdx @@ -0,0 +1,10 @@ +--- +id: interactive-glossary +title: Interactive Glossary +--- + +import GlossaryTable from '@site/src/components/Glossary/GlossaryTable'; + +Use the search boxes to filter by term or perform a fuzzy free-text search across definitions. Click any row or alias to deep-link to a glossary entry. + + diff --git a/website/docs/learning_objectives.md b/website/docs/learning_objectives.md index b5d6012..e0832b2 100644 --- a/website/docs/learning_objectives.md +++ b/website/docs/learning_objectives.md @@ -52,7 +52,7 @@ | [`LO-2.5.2.4`](chapter-02/05_keyword_interface.md#2524-positional-or-named-arguments) | K1 | Recall how "Positional or Named Arguments" are marked in the documentation and their use case. | | [`LO-2.5.2.5`](chapter-02/05_keyword_interface.md#2525-variable-number-of-positional-arguments) | K1 | Recall how "Variable Number of Positional Arguments" are marked in the documentation and their use case. | | [`LO-2.5.2.6`](chapter-02/05_keyword_interface.md#2526-named-only-arguments) | K1 | Recall what properties "Named-Only Arguments" have and how they are documented. | -| [`LO-2.5.2.7`](chapter-02/05_keyword_interface.md#2527-free-named-arguments) | K1 | Recall how free named arguments are marked in documentation. | +| [`LO-2.5.2.7`](chapter-02/05_keyword_interface.md#2527-free-named-arguments) | K1 | Recall how "Free Named Arguments" are marked in documentation. | | [`LO-2.5.2.8`](chapter-02/05_keyword_interface.md#2528-argument-types) | K2 | Understand the concept of argument types and automatic type conversion. | | [`LO-2.5.2.9`](chapter-02/05_keyword_interface.md#2529-return-types) | K2 | Understand the concept of return type hints. | | [`LO-2.5.3`](chapter-02/05_keyword_interface.md#253-keyword-documentation--examples) | K2 | Understand how to read keyword documentation and how to interpret the examples. | diff --git a/website/package-lock.json b/website/package-lock.json index 29f4a7c..aa068bc 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -16,6 +16,8 @@ "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "dompurify": "^3.3.0", + "fuse.js": "^7.1.0", + "marked": "^12.0.2", "prism-react-renderer": "^2.4.1", "quizdown-extended": "^1.2.1", "react": "^19.2.0", @@ -3345,6 +3347,18 @@ } } }, + "node_modules/@docsearch/react/node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/@docusaurus/babel": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", @@ -9561,6 +9575,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fuse.js": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz", + "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -11919,15 +11942,15 @@ } }, "node_modules/marked": { - "version": "16.4.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", - "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 20" + "node": ">= 18" } }, "node_modules/math-intrinsics": { diff --git a/website/package.json b/website/package.json index 4494891..1559bd9 100644 --- a/website/package.json +++ b/website/package.json @@ -26,9 +26,11 @@ "clsx": "^2.1.1", "docusaurus-lunr-search": "^3.6.0", "dompurify": "^3.3.0", + "fuse.js": "^7.1.0", + "marked": "^12.0.2", + "prism-react-renderer": "^2.4.1", "quizdown-extended": "^1.2.1", "react": "^19.2.0", - "prism-react-renderer": "^2.4.1", "react-dom": "^19.2.0", "react-markdown": "^10.1.0", "rehype-raw": "^7.0.0", diff --git a/website/src/components/Glossary/GlossaryTable.module.css b/website/src/components/Glossary/GlossaryTable.module.css new file mode 100644 index 0000000..bd6ebc4 --- /dev/null +++ b/website/src/components/Glossary/GlossaryTable.module.css @@ -0,0 +1,140 @@ +.wrapper { + margin: 1.5rem 0; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.controls { + display: grid; + gap: 0.75rem; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); +} + +.control { + display: flex; + flex-direction: column; + gap: 0.35rem; + font-weight: 600; + color: var(--ifm-color-primary); +} + +.control input { + padding: 0.5rem 0.75rem; + border-radius: 0.35rem; + border: 1px solid var(--ifm-color-emphasis-300); + background: var(--ifm-background-color); + color: var(--ifm-font-color-base); +} + +.tableWrapper { + overflow-x: auto; + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 0.5rem; +} + +.table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; +} + + +th, +td { + padding: 0.85rem 1rem; + text-align: left; + vertical-align: top; +} + +th { + background: var(--ifm-color-emphasis-100); + font-size: 0.95rem; + letter-spacing: 0.01em; +} + +tr:nth-child(even) { + background: var(--ifm-table-stripe-background); +} + +tbody tr { + scroll-margin-top: 72px; /* leave space for sticky header */ +} + +.activeRow { + outline: 2px solid var(--ifm-color-primary); + outline-offset: -2px; + background: var(--ifm-color-emphasis-100); +} + +.termCell { + min-width: 180px; + font-weight: 700; +} + +.clickable { + cursor: pointer; +} + +.termName { + margin-bottom: 0.25rem; +} + +.definitionCell { + width: 100%; +} + + + +.definitionText > :first-child { + margin-top: 0; +} + +.definitionText > :last-child { + margin-bottom: 0; +} + +.pillRow { + display: flex; + gap: 0.4rem; + flex-wrap: wrap; + margin-top: 0.5rem; +} + +.pill { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.15rem 0.6rem; + border-radius: 999px; + font-size: 0.8rem; + border: 1px solid var(--ifm-color-emphasis-300); + background: var(--ifm-color-emphasis-100); + color: var(--ifm-font-color-base); + text-decoration: none; +} + +.pill:hover, +.pill:focus-visible { + border-color: var(--ifm-color-primary); + color: var(--ifm-color-primary); +} + +.abbreviationPill { + font-weight: 700; +} + +.aliasPill { + font-weight: 600; +} + +.aliasLink { + color: var(--ifm-color-primary); + text-decoration: underline; + font-weight: 600; +} + +.aliasLink:hover, +.aliasLink:focus-visible { + color: var(--ifm-color-primary-darker); +} diff --git a/website/src/components/Glossary/GlossaryTable.tsx b/website/src/components/Glossary/GlossaryTable.tsx new file mode 100644 index 0000000..24a1d8c --- /dev/null +++ b/website/src/components/Glossary/GlossaryTable.tsx @@ -0,0 +1,289 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import Fuse from 'fuse.js'; +import clsx from 'clsx'; +import { marked } from 'marked'; +import DOMPurify from 'dompurify'; +import glossaryData from '@site/static/glossary/glossary.json'; +import styles from './GlossaryTable.module.css'; + +export type GlossaryItem = { + term: string; + aliases: string[]; + abbreviation: string; + definition: string; +}; + +export type DisplayEntry = { + term: string; + abbreviation: string; + definition: string; + definitionHtml: string; + canonicalTerm: string; + isAlias: boolean; + slug: string; + targetSlug: string; + aliases: string[]; +}; + +const slugify = (text: string): string => + text + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/(^-+|-+$)/g, ''); + +const sanitizeMarkdown = (markdown: string): string => { + const html = marked.parse(markdown || '', { async: false }) as string; + return typeof window !== 'undefined' ? DOMPurify.sanitize(html) : html; +}; + +const GlossaryTable: React.FC = () => { + const [termQuery, setTermQuery] = useState(''); + const [textQuery, setTextQuery] = useState(''); + const [activeSlug, setActiveSlug] = useState(''); + + const { entries, aliasToCanonicalSlug } = useMemo(() => { + const glossaryItems = glossaryData as GlossaryItem[]; + const termSet = new Set(glossaryItems.map((item) => item.term)); + + const canonicalEntries: DisplayEntry[] = glossaryItems.map((item) => { + const slug = slugify(item.term); + return { + term: item.term, + abbreviation: item.abbreviation, + definition: item.definition, + definitionHtml: sanitizeMarkdown(item.definition), + canonicalTerm: item.term, + isAlias: false, + slug, + targetSlug: slug, + aliases: item.aliases || [], + }; + }); + + const aliasEntries: DisplayEntry[] = glossaryItems.flatMap((item) => { + const canonicalSlug = slugify(item.term); + return (item.aliases || []) + .filter((alias) => !termSet.has(alias)) + .map((alias) => ({ + term: alias, + abbreviation: '', + definition: `See ${item.term}`, + definitionHtml: '', // Alias entries don't need HTML since they use a link + canonicalTerm: item.term, + isAlias: true, + slug: slugify(alias), + targetSlug: canonicalSlug, + aliases: [], + })); + }); + + const aliasMap = new Map(); + canonicalEntries.forEach((entry) => aliasMap.set(entry.slug, entry.targetSlug)); + aliasEntries.forEach((entry) => aliasMap.set(entry.slug, entry.targetSlug)); + + const combined = [...canonicalEntries, ...aliasEntries].sort((a, b) => a.term.localeCompare(b.term)); + return { entries: combined, aliasToCanonicalSlug: aliasMap }; + }, []); + + const fuse = useMemo( + () => + new Fuse(entries, { + keys: [ + { name: 'term', weight: 0.5 }, + { name: 'definition', weight: 0.4 }, + { name: 'abbreviation', weight: 0.1 }, + { name: 'aliases', weight: 0.3 }, + ], + threshold: 0.35, + ignoreLocation: true, + }), + [entries] + ); + + const focusEntry = useCallback( + (slug: string, canonicalTerm?: string) => { + if (!slug || typeof window === 'undefined') { + return; + } + + const targetSlug = slug; + setActiveSlug(targetSlug); + + const url = new URL(window.location.href); + url.hash = targetSlug; + if (canonicalTerm) { + url.searchParams.set('term', canonicalTerm); + } else { + url.searchParams.set('term', targetSlug); + } + window.history.replaceState({}, '', url.toString()); + + const target = document.getElementById(targetSlug); + if (target) { + const top = target.getBoundingClientRect().top + window.scrollY - 70; // account for sticky header + window.scrollTo({ top, behavior: 'smooth' }); + } + }, + [] + ); + + useEffect(() => { + if (typeof window === 'undefined') { + return; + } + + const params = new URLSearchParams(window.location.search); + const termParam = params.get('term'); + const hashParam = window.location.hash ? window.location.hash.replace('#', '') : ''; + const rawSlug = hashParam || (termParam ? slugify(termParam) : ''); + const initialSlug = aliasToCanonicalSlug.get(rawSlug) || rawSlug; + + if (initialSlug) { + setActiveSlug(initialSlug); + // Allow the page to render before scrolling + setTimeout(() => focusEntry(initialSlug, termParam || initialSlug), 50); + } + }, [aliasToCanonicalSlug, focusEntry]); + + const filteredEntries = useMemo(() => { + const normalize = (value: string) => value.toLowerCase(); + let subset = entries; + + if (termQuery.trim()) { + const query = normalize(termQuery.trim()); + subset = subset.filter((entry) => { + return ( + normalize(entry.term).includes(query) || + normalize(entry.canonicalTerm).includes(query) || + (entry.aliases || []).some((alias) => normalize(alias).includes(query)) + ); + }); + } + + if (textQuery.trim()) { + const results = fuse.search(textQuery.trim()); + const allowedSlugs = new Set(); + results.forEach(({ item }) => allowedSlugs.add(item.slug)); + subset = subset.filter((entry) => allowedSlugs.has(entry.slug)); + } + + return subset; + }, [entries, fuse, termQuery, textQuery]); + + return ( +
+
+ + +
+ +
+ + + + + + + + + {filteredEntries.map((entry) => { + const handleClick = () => focusEntry(entry.targetSlug, entry.canonicalTerm); + + return ( + { + if ( + (event.key === 'Enter' || event.key === ' ') && + event.target === event.currentTarget + ) { + event.preventDefault(); + handleClick(); + } + }} + > + + + + ); + })} + +
TermDefinition & Abbreviation
+
{entry.term}
+
+ {entry.isAlias ? ( + // Hyperlink to term in alias definition cell + { + event.preventDefault(); + event.stopPropagation(); + focusEntry(entry.targetSlug, entry.canonicalTerm); + }} + > + See {entry.canonicalTerm} + + ) : ( + <> +
+
+ {entry.abbreviation ? ( + + {entry.abbreviation} + + ) : null} + {(entry.aliases || []).map((alias) => { + const aliasSlug = slugify(alias); + const target = aliasToCanonicalSlug.get(aliasSlug) || aliasSlug; + return ( + // Link to alias term + { + event.preventDefault(); + event.stopPropagation(); + focusEntry(aliasSlug, alias); + }} + > + {alias} + + ); + })} +
+ + )} +
+
+
+ ); +}; + +export default GlossaryTable; diff --git a/website/src/components/Quiz/quizComponents.ts b/website/src/components/Quiz/quizComponents.ts index 21b28d0..c2380a7 100644 --- a/website/src/components/Quiz/quizComponents.ts +++ b/website/src/components/Quiz/quizComponents.ts @@ -1,6 +1,6 @@ /* * This file is automatically generated and will be overridden when running the build process. -* Generated on: 12/5/2025, 1:04:36 PM +* Generated on: 12/7/2025, 12:57:51 PM */ export interface QuizPage { diff --git a/website/src/components/Term.module.css b/website/src/components/Term.module.css new file mode 100644 index 0000000..9b9fe19 --- /dev/null +++ b/website/src/components/Term.module.css @@ -0,0 +1,36 @@ +.termTrigger { + position: relative; + cursor: help; + background: var(--ifm-background-surface-color); + border: 0.1rem solid var(--ifm-color-emphasis-200) !important; + border-radius: var(--ifm-code-border-radius) !important; + padding: 0 var(--ifm-code-padding-horizontal); + vertical-align: middle; +} + +.termTooltip { + position: absolute; + max-width: 420px; + font-weight: 400; + color: var(--ifm-font-color-base); + padding: 10px 12px; + border-radius: 8px; + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); + z-index: 1000; + white-space: normal; +} + +.termTooltipLink { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.15rem 0.6rem; + border-radius: 999px; + font-size: 0.8rem; + border: 1px solid var(--ifm-color-emphasis-300); + background: var(--ifm-color-emphasis-100); + color: var(--ifm-font-color-base); + text-decoration: none; +} diff --git a/website/src/components/Term.tsx b/website/src/components/Term.tsx index ed48584..562f0f7 100644 --- a/website/src/components/Term.tsx +++ b/website/src/components/Term.tsx @@ -1,10 +1,14 @@ import React from "react"; +import {createPortal} from "react-dom"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; // Optional raw HTML support (see notes below): import rehypeRaw from "rehype-raw"; import DOMPurify from "dompurify"; +import styles from "./Term.module.css"; + type TermProps = { /** Text that appears inline in your document (the trigger/label) */ trigger?: string; // used by container form; fine to keep even if you only use inline @@ -26,8 +30,17 @@ export default function Term({ id, children, }: TermProps) { + const {siteConfig} = useDocusaurusContext(); + const baseUrl = (siteConfig?.baseUrl || "/").replace(/\/$/, ""); + const [open, setOpen] = React.useState(false); const ref = React.useRef(null); + const [coords, setCoords] = React.useState<{top: number; left: number; width: number}>({ + top: 0, + left: 0, + width: 0, + }); + const [portalReady, setPortalReady] = React.useState(false); React.useEffect(() => { const onDocClick = (e: MouseEvent) => { @@ -37,6 +50,35 @@ export default function Term({ return () => document.removeEventListener("click", onDocClick); }, []); + React.useEffect(() => { + if (typeof window === "undefined") return; + setPortalReady(true); + }, []); + + const updatePosition = React.useCallback(() => { + if (!ref.current || typeof window === "undefined") return; + const rect = ref.current.getBoundingClientRect(); + const scrollY = window.scrollY || window.pageYOffset; + const scrollX = window.scrollX || window.pageXOffset; + setCoords({ + top: rect.top + scrollY + rect.height + 4, + left: rect.left + scrollX, + width: rect.width, + }); + }, []); + + React.useEffect(() => { + if (!open) return; + updatePosition(); + const handler = () => updatePosition(); + window.addEventListener("scroll", handler, true); + window.addEventListener("resize", handler); + return () => { + window.removeEventListener("scroll", handler, true); + window.removeEventListener("resize", handler); + }; + }, [open, updatePosition]); + const hasTooltip = Boolean(tooltipMd || tooltip || tooltipHtml || children); // If you expect authors to use "\n" in attribute strings, you can normalize them: @@ -55,67 +97,62 @@ export default function Term({ ? setOpen((v) => !v) : null } - style={{ - position: "relative", - cursor: hasTooltip ? "help" : "default", - borderBottom: "1px solid currentcolor", - fontWeight: 600, - color: "var(--ifm-navbar-link-active-color)", - }} + className={styles.termTrigger} aria-haspopup="dialog" aria-expanded={open} > {/* Trigger text; for inline directives, this is the directive label */} {trigger ?? children} - {open && hasTooltip && ( - - {/* Priority: Markdown > plain text > HTML > children */} - {tooltipMdNormalized && ( -

, // example: map elements if you like + {open && hasTooltip && portalReady + ? createPortal( +

- {tooltipMdNormalized} - - )} + {tooltipMdNormalized && ( + , + document.body + ) + : null} ); } diff --git a/website/src/remark/remark-term-directive.js b/website/src/remark/remark-term-directive.js index 74539ae..8acb957 100644 --- a/website/src/remark/remark-term-directive.js +++ b/website/src/remark/remark-term-directive.js @@ -1,13 +1,46 @@ // plugins/remark-term-directive.js import {visit} from "unist-util-visit"; +import glossary from "../../static/glossary/glossary.json"; /** - * Converts :term[Text]{prop="value"} into: - * Text + * Usage examples (inline): + * :term[visual text]{term="Glossary Term"} + * :term[Glossary Term] // falls back to the label if {term} is missing * - * Works for inline (:term[...]) and (optionally) block/containers (:::) if you want them. + * The label between [] becomes the visible text. The target term is resolved in + * this order: {term=...} attribute (preferred), then {target} or {ref}, then the + * label as a last resort. The legacy title ( ... ) syntax is deprecated. + * The tooltip is built from the glossary entry (definition) and includes a link + * to the glossary page. */ export default function remarkTermDirective() { + const normalizeKey = (value = "") => value.trim().toLowerCase(); + + const slugify = (text = "") => + text + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/(^-+|-+$)/g, ""); + + const glossaryByKey = new Map(); + (glossary || []).forEach((entry) => { + const key = normalizeKey(entry.term); + glossaryByKey.set(key, entry); + (entry.aliases || []).forEach((alias) => { + glossaryByKey.set(normalizeKey(alias), entry); + }); + }); + + const baseUrl = (process.env.BASE_URL || "/").replace(/\/$/, ""); + + const toTooltipMd = (entry, fallbackTarget) => { + const termName = entry?.term || fallbackTarget; + const link = termName ? `${baseUrl}/docs/glossary?term=${encodeURIComponent(termName)}` : undefined; + if (!termName) return undefined; + if (!entry) return `[Open glossary entry](${link})`; + return `**${entry.term}**\n\n${entry.definition}\n\n[Open glossary entry](${link})`; + }; + const toAttrs = (attrs = {}) => Object.entries(attrs).map(([name, value]) => ({ type: "mdxJsxAttribute", @@ -20,50 +53,55 @@ export default function remarkTermDirective() { visit(tree, (node, index, parent) => { if (!parent) return; - // Inline form: :term[...] - if (node.type === "textDirective" && node.name === "term") { - const label = - node.label ?? - (node.children && node.children[0] && node.children[0].value) ?? - ""; - const mdxNode = { - type: "mdxJsxTextElement", - name: "Term", - attributes: toAttrs(node.attributes), - children: [{type: "text", value: label}], - }; - parent.children.splice(index, 1, mdxNode); - return index + 1; - } + const isTermDirective = + (node.type === "textDirective" || node.type === "leafDirective" || node.type === "containerDirective") && + node.name === "term"; - // Optional block forms if you ever want them: - // Leaf directive (single block line): :term[Heading]{...} - if (node.type === "leafDirective" && node.name === "term") { - const label = - node.label ?? - (node.children && node.children[0] && node.children[0].value) ?? - ""; - const mdxNode = { - type: "mdxJsxFlowElement", - name: "Term", - attributes: toAttrs(node.attributes), - children: [{type: "text", value: label}], - }; - parent.children.splice(index, 1, mdxNode); - return index + 1; - } + if (!isTermDirective) return; + + const label = + node.label ?? + (node.children && node.children[0] && node.children[0].value) ?? + ""; + + const attrTerm = node.attributes?.term || node.attributes?.target || node.attributes?.ref; + const legacyTitle = node.title; // from ( ... ) syntax + const fallbackLabel = label; + + const targetTerm = + (typeof attrTerm === "string" && attrTerm.trim()) || + (typeof legacyTitle === "string" && legacyTitle.trim()) || + (typeof fallbackLabel === "string" && fallbackLabel.trim()) || + ""; - // Container directive with :::term ... ::: - if (node.type === "containerDirective" && node.name === "term") { - const mdxNode = { - type: "mdxJsxFlowElement", - name: "Term", - attributes: toAttrs(node.attributes), - children: node.children || [], - }; - parent.children.splice(index, 1, mdxNode); - return index + 1; + const glossaryEntry = glossaryByKey.get(normalizeKey(targetTerm)); + if (process.env.NODE_ENV !== "production") { + if (!attrTerm && legacyTitle) { + console.warn("[remark-term-directive] title ( ... ) syntax is deprecated; use {term=...} instead"); + } + if (!glossaryEntry) { + // Dev-only hint when a directive target does not resolve to a glossary entry + console.warn(`[remark-term-directive] missing glossary entry for "${targetTerm}"`); + } } + const tooltipMd = toTooltipMd(glossaryEntry, targetTerm); + const id = slugify(glossaryEntry?.term || targetTerm); + + const baseAttributes = { + trigger: label, + id, + tooltipMd, + }; + + const mdxNode = { + type: node.type === "textDirective" ? "mdxJsxTextElement" : "mdxJsxFlowElement", + name: "Term", + attributes: toAttrs({...node.attributes, ...baseAttributes}), + children: [{type: "text", value: label}], + }; + + parent.children.splice(index, 1, mdxNode); + return index + 1; }); }; } diff --git a/website/src/theme/Admonition/index.tsx b/website/src/theme/Admonition/index.tsx index d524a6d..f589cb3 100644 --- a/website/src/theme/Admonition/index.tsx +++ b/website/src/theme/Admonition/index.tsx @@ -6,9 +6,10 @@ import K2Icon from '@site/static/img/K2.svg'; import K3Icon from '@site/static/img/K3.svg'; import type AdmonitionType from '@theme/Admonition'; +import type {AdmonitionProps} from '@theme/Admonition'; import type {WrapperProps} from '@docusaurus/types'; -type Props = WrapperProps; +type Props = WrapperProps & AdmonitionProps; export default function AdmonitionWrapper(props: Props): ReactNode { if (props.type === 'lo') { diff --git a/website/src/types/docusaurus-theme.d.ts b/website/src/types/docusaurus-theme.d.ts new file mode 100644 index 0000000..0c2050a --- /dev/null +++ b/website/src/types/docusaurus-theme.d.ts @@ -0,0 +1,43 @@ +declare module '@theme/Heading' { + import type {ComponentType, ReactNode, ElementType} from 'react'; + + type HeadingProps = { + as?: ElementType; + className?: string; + id?: string; + children?: ReactNode; + }; + + const Heading: ComponentType; + export default Heading; +} + +declare module '@theme/Admonition' { + import type {ComponentType, ReactNode} from 'react'; + + export type AdmonitionProps = { + readonly type?: string; + readonly title?: ReactNode; + readonly icon?: ReactNode; + children?: ReactNode; + }; + + const Admonition: ComponentType; + export default Admonition; +} + +declare module '@theme/Layout' { + import type {ComponentType, ReactNode} from 'react'; + + export interface Props { + children?: ReactNode; + title?: string; + description?: string; + wrapperClassName?: string; + noFooter?: boolean; + noNavbar?: boolean; + } + + const Layout: ComponentType; + export default Layout; +} diff --git a/website/static/glossary/glossary.json b/website/static/glossary/glossary.json new file mode 100644 index 0000000..a595c57 --- /dev/null +++ b/website/static/glossary/glossary.json @@ -0,0 +1,476 @@ +[ + { + "term": "Acceptance Testing", + "aliases": [], + "abbreviation": "", + "definition": "Validation that a system satisfies agreed business requirements and is ready for deployment or release." + }, + { + "term": "Adaptation Layer", + "aliases": [], + "abbreviation": "", + "definition": "Layer in the Generic Test Automation Architecture (gTAA) that connects Robot Framework to the System Under Test or other automated systems via keyword libraries." + }, + { + "term": "Atomic Element", + "aliases": [], + "abbreviation": "", + "definition": "Execution element without child steps whose status depends solely on its own execution result." + }, + { + "term": "Automation Script", + "aliases": [], + "abbreviation": "", + "definition": "Robot Framework suite, test, task, or keyword collection that automates a defined workflow or behavior." + }, + { + "term": "Argument", + "aliases": [], + "abbreviation": "", + "definition": "Value supplied to a keyword call as positional, named, or embedded input to configure its behavior." + }, + { + "term": "Argument Interface", + "aliases": [], + "abbreviation": "", + "definition": "Ordered specification of a keyword’s arguments, including kinds (for example positional-or-named, named-only, variable positional, free named, embedded), names, default values, and optional type hints." + }, + { + "term": "Behavior-Driven Development", + "aliases": [], + "abbreviation": "BDD", + "definition": "Development approach that describes system behavior in business-readable language, often using Given/When/Then phrasing." + }, + { + "term": "Behavior-Driven Specification", + "aliases": [], + "abbreviation": "", + "definition": "Declarative Robot Framework style where tests|tasks describe system behavior from the user perspective using natural-language-like steps with embedded arguments and optional Given/When/Then/And/But prefixes." + }, + { + "term": "Built-In Variables", + "aliases": [], + "abbreviation": "", + "definition": "Variables provided by Robot Framework that expose execution-related information such as paths, timestamps, and status without explicit definition." + }, + { + "term": "Command Line Interface", + "aliases": ["Robot Framework CLI"], + "abbreviation": "CLI", + "definition": "Interface used to run Robot Framework from the command line (for example with the `robot` command), configure execution options, and pass arguments or variables." + }, + { + "term": "Composite Element", + "aliases": [], + "abbreviation": "", + "definition": "Execution element composed of child elements (for example suites with tests|tasks, tests|tasks with keywords, or user keywords with child steps) whose status is derived from its children." + }, + { + "term": "Control Structure", + "aliases": [], + "abbreviation": "", + "definition": "Statement such as `IF`, `FOR`, `WHILE`, `BREAK`, or `CONTINUE` that controls execution flow inside a test, task, or keyword." + }, + { + "term": "Data-Driven Specification", + "aliases": [], + "abbreviation": "", + "definition": "Specification style where the same logic or test flow is executed multiple times with varying input or expected output data, often implemented with test|task templates." + }, + { + "term": "Definition Layer", + "aliases": [], + "abbreviation": "", + "definition": "Layer in the Generic Test Automation Architecture (gTAA) containing test data such as suites, tests, tasks, resource files, keywords, and variables written in Robot Framework syntax." + }, + { + "term": "Embedded Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument kind defined directly in a keyword name using `${}` syntax whose value must appear in that position in calls, often used in behavior-driven steps." + }, + { + "term": "End-to-End Test", + "aliases": [], + "abbreviation": "", + "definition": "Test that verifies a complete workflow across all relevant components, subsystems, and interfaces to ensure real-world user flows behave as expected." + }, + { + "term": "Execution Artifacts", + "aliases": [], + "abbreviation": "", + "definition": "Files produced by Robot Framework execution—such as `output.xml`, `log.html`, and `report.html`—that document what was executed and with which results." + }, + { + "term": "Execution Layer", + "aliases": [], + "abbreviation": "", + "definition": "Layer in the Generic Test Automation Architecture (gTAA) comprising Robot Framework’s parser, execution engine, logging, and reporting components that interpret test data and run keywords." + }, + { + "term": "Execution Model", + "aliases": [], + "abbreviation": "", + "definition": "Internal representation created after parsing suites, tests, tasks, and keywords that the execution engine uses to perform automation." + }, + { + "term": "Fail Status", + "aliases": [], + "abbreviation": "", + "definition": "Execution status indicating that an element (such as a keyword, test, task, or suite) did not meet its expected outcome or raised an error during execution." + }, + { + "term": "FOR Loop", + "aliases": [], + "abbreviation": "", + "definition": "Control structure used to iterate over items in a list or other iterable and execute a body of keywords for each item." + }, + { + "term": "Free Named Argument", + "aliases": ["**kwargs"], + "abbreviation": "kwargs", + "definition": "Catch-all named argument kind in a keyword specification, marked with **, that gathers all named values not explicitly defined elsewhere into a dictionary." + }, + { + "term": "Generic Test Automation Architecture", + "aliases": ["gTAA"], + "abbreviation": "gTAA", + "definition": "Layered reference architecture for test automation that separates definition, execution, and adaptation layers and describes Robot Framework’s role in an automation solution." + }, + { + "term": "Given / When / Then / And / But", + "aliases": [], + "abbreviation": "", + "definition": "Conventional prefixes in behavior-driven specification style that Robot Framework can ignore when matching keywords if the remaining part of the name matches a keyword." + }, + { + "term": "Global Variable", + "aliases": [], + "abbreviation": "", + "definition": "Variable with global scope that can be accessed from all suites and keywords in a Robot Framework execution." + }, + { + "term": "Higher-Level Suite (Suite Directory)", + "aliases": [], + "abbreviation": "", + "definition": "Directory treated as a suite because it directly or indirectly contains at least one suite file, grouping lower-level suites into a suite tree." + }, + { + "term": "Initialization File (__init__.robot)", + "aliases": [], + "abbreviation": "", + "definition": "Suite file located in a directory that configures that directory as a suite and defines suite-level settings, variables, setups, and teardowns for contained suites." + }, + { + "term": "Inline Comment", + "aliases": [], + "abbreviation": "", + "definition": "Comment at the beginning or end of a line in a Robot Framework file, separated by at least two spaces and starting with # so that it is ignored by the interpreter." + }, + { + "term": "Inline IF", + "aliases": [], + "abbreviation": "", + "definition": "Compact single-line IF statement (`IF [args]`) used to execute one keyword conditionally without an END." + }, + { + "term": "K-Level (Knowledge Level)", + "aliases": [], + "abbreviation": "", + "definition": "Categorization of learning objectives based on Bloom’s Taxonomy: K1 (Remember), K2 (Understand), and K3 (Apply), indicating expected depth of knowledge." + }, + { + "term": "Keyword", + "aliases": [], + "abbreviation": "", + "definition": "Named reusable action or sequence of actions in Robot Framework callable from tests, tasks, or other keywords that may accept arguments and return values." + }, + { + "term": "Keyword Interface", + "aliases": [], + "abbreviation": "", + "definition": "Documented information of a keyword—including name, arguments with kinds and types, return values, documentation, and examples—as exposed by HTML documentation or IDEs." + }, + { + "term": "Keyword-Driven Specification", + "aliases": [], + "abbreviation": "", + "definition": "Imperative Robot Framework style where tests|tasks are written as sequences of keyword calls with arguments, focusing on executed actions and their order." + }, + { + "term": "Keyword Library", + "aliases": ["Library"], + "abbreviation": "", + "definition": "Collection of library keywords implemented typically in Python (or other languages) that Robot Framework imports to interact with external systems, perform computations, or provide utility functions." + }, + { + "term": "List Variable", + "aliases": [], + "abbreviation": "", + "definition": "Robot Framework variable of list type accessed with the `@{}` syntax that holds an ordered collection of values and can be unpacked when passed to keywords." + }, + { + "term": "Local Variable", + "aliases": [], + "abbreviation": "", + "definition": "Variable whose scope is limited to a single keyword, test, or task execution and is not visible outside that body." + }, + { + "term": "Log File (log.html)", + "aliases": [], + "abbreviation": "", + "definition": "Detailed HTML execution log (log.html) generated by Robot Framework that shows keyword-level execution steps, arguments, messages, and statuses." + }, + { + "term": "Mandatory Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument kind in a keyword specification without a default value that must be provided in calls and that precedes optional arguments." + }, + { + "term": "Metadata (Suite Metadata)", + "aliases": [], + "abbreviation": "", + "definition": "Key–value information defined with the Metadata setting in a suite to document attributes such as author, version, or related requirements." + }, + { + "term": "Named-Only Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument kind in a keyword specification that must be provided by name (never positionally), typically defined after a Variable Number of Positional Arguments or explicitly marked, and that can be mandatory or optional." + }, + { + "term": "Named Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument value provided in a keyword call using an explicit name=value pair." + }, + { + "term": "Output File (output.xml)", + "aliases": [], + "abbreviation": "", + "definition": "Machine-readable execution result file (output.xml) produced by Robot Framework that contains the full execution tree, messages, and statistics in XML format." + }, + { + "term": "Optional Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument kind in a keyword specification that may be omitted because it has a default value or is a catch-all (such as Variable Number of Positional Arguments marked with * or Free Named Arguments marked with **)." + }, + { + "term": "Pass Status", + "aliases": [], + "abbreviation": "", + "definition": "Execution status indicating that an element (such as a keyword, test, task, or suite) executed successfully and met its expectations." + }, + { + "term": "Positional Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument value provided in a keyword call solely by its position in the argument list without naming it explicitly." + }, + { + "term": "Positional or Named Argument", + "aliases": [], + "abbreviation": "", + "definition": "Argument kind in a keyword specification that can be set either by position or by name (but not both for the same value) and that may be mandatory or optional." + }, + { + "term": "Report File (report.html)", + "aliases": [], + "abbreviation": "", + "definition": "High-level HTML summary (report.html) of a Robot Framework execution that focuses on statistics and overall pass/fail status of suites and tests|tasks." + }, + { + "term": "Resource File", + "aliases": [], + "abbreviation": "", + "definition": "File (commonly with extension .resource or .robot) that contains user keywords and variables and is imported by suites to share and reuse these artifacts." + }, + { + "term": "Return Statement (RETURN)", + "aliases": [], + "abbreviation": "", + "definition": "Statement used in user keywords to return one or more values that can be assigned to variables in the calling context." + }, + { + "term": "Return Type Hint", + "aliases": [], + "abbreviation": "", + "definition": "Documented indication of the type of value a keyword returns, helping users understand how to use the returned data." + }, + { + "term": "Robotic Process Automation", + "aliases": ["RPA"], + "abbreviation": "RPA", + "definition": "Automation of business processes or tasks normally performed by humans, often across multiple systems, without necessarily focusing on testing." + }, + { + "term": "Robot Framework Foundation", + "aliases": [], + "abbreviation": "", + "definition": "Non-profit association (Robot Framework ry) that stewards the development, ecosystem, governance, and promotion of Robot Framework and its community." + }, + { + "term": "Robot Framework® Certified Professional", + "aliases": ["RFCP"], + "abbreviation": "RFCP", + "definition": "Foundational certification level for Robot Framework that validates understanding of core concepts, syntax, and basic control structures." + }, + { + "term": "Root Suite", + "aliases": [], + "abbreviation": "", + "definition": "Top-level suite in a Robot Framework execution determined by the initial directory or file path passed to the `robot` command." + }, + { + "term": "Scalar Access Syntax (${})", + "aliases": [], + "abbreviation": "", + "definition": "Standard variable access form in Robot Framework used to read values regardless of whether the underlying variable was defined as scalar, list-like, or dictionary-like." + }, + { + "term": "Scalar Variable", + "aliases": [], + "abbreviation": "", + "definition": "Robot Framework variable accessed with the `${}` syntax that holds a single value of any supported data type." + }, + { + "term": "Skip Status", + "aliases": [], + "abbreviation": "", + "definition": "Execution status indicating that an element (such as a test or task) was intentionally not executed, for example due to selection options or an explicit skip." + }, + { + "term": "Standard Library (Robot Framework)", + "aliases": [], + "abbreviation": "", + "definition": "Library shipped with Robot Framework itself providing generic functionality such as operating system interaction, string manipulation, or process handling." + }, + { + "term": "Suite (Test Suite / Task Suite)", + "aliases": [], + "abbreviation": "", + "definition": "Collection of tests or tasks (optionally with local keywords and variables) defined in a .robot file or directory that is executed as a unit by Robot Framework." + }, + { + "term": "Suite File", + "aliases": [], + "abbreviation": "", + "definition": ".robot file that contains at least one test case or task and is therefore treated by Robot Framework as an executable suite." + }, + { + "term": "Suite Setup", + "aliases": [], + "abbreviation": "", + "definition": "Keyword executed once before any tests|tasks in a suite are run, typically used to prepare common preconditions." + }, + { + "term": "Suite Teardown", + "aliases": [], + "abbreviation": "", + "definition": "Keyword executed once after all tests|tasks in a suite have run, typically used to clean up shared resources." + }, + { + "term": "Suite Variable", + "aliases": [], + "abbreviation": "", + "definition": "Variable whose scope covers all tests|tasks and keywords within a specific suite but is not visible outside that suite." + }, + { + "term": "Synthetic Monitoring", + "aliases": ["Active Monitoring"], + "abbreviation": "", + "definition": "Proactive monitoring that runs automated scripts (often using tools like Robot Framework) at regular intervals against live systems to detect issues before real users are affected." + }, + { + "term": "Task", + "aliases": ["Test Case"], + "abbreviation": "", + "definition": "Executable entity in Robot Framework similar to a test case but used for non-testing automation such as RPA workflows, defined in a `*** Tasks ***` section." + }, + { + "term": "Test Setup", + "aliases": ["Task Setup"], + "abbreviation": "", + "definition": "Keyword executed before an individual test or task starts to prepare preconditions specific to that test|task." + }, + { + "term": "Test Teardown", + "aliases": ["Task Teardown"], + "abbreviation": "", + "definition": "Keyword executed after an individual test or task finishes to clean up resources specific to that test|task." + }, + { + "term": "Test Template", + "aliases": ["Task Template"], + "abbreviation": "", + "definition": "Setting that defines a keyword used as a template for multiple tests|tasks, where each row of data calls the template keyword with different arguments." + }, + { + "term": "Test Case", + "aliases": ["Task"], + "abbreviation": "Test", + "definition": "Executable specification in Robot Framework that verifies some aspect of system behavior and is defined in a `*** Test Cases ***` section." + }, + { + "term": "Test Data", + "aliases": [], + "abbreviation": "", + "definition": "Collection of suites, tests, tasks, resource files, keywords, and variables that define what Robot Framework executes." + }, + { + "term": "Test Level", + "aliases": [], + "abbreviation": "", + "definition": "Classification of testing focus (such as unit, component, integration, system, system integration, acceptance, or end-to-end) describing scope and granularity of tests." + }, + { + "term": "Test Tag", + "aliases": ["Task Tag"], + "abbreviation": "", + "definition": "Label assigned to tests or tasks via the Tags setting to categorize them and enable filtering, selection, and reporting." + }, + { + "term": "Test Timeout", + "aliases": ["Task Timeout"], + "abbreviation": "", + "definition": "Maximum allowed execution time for a keyword, test, or task after which Robot Framework marks the element as failed due to timeout." + }, + { + "term": "User Keyword", + "aliases": ["Composite Keyword"], + "abbreviation": "", + "definition": "Keyword defined in Robot Framework syntax (typically in suites or resource files) composed of calls to other keywords and statements, often describing higher-level or business-oriented actions." + }, + { + "term": "Variable Number of Positional Arguments", + "aliases": ["*varargs", "*args"], + "abbreviation": "", + "definition": "Optional argument kind in a keyword specification, marked with a single *, that collects all remaining positional values; once present, any subsequent parameters must be provided as named arguments." + }, + { + "term": "Variable", + "aliases": [], + "abbreviation": "", + "definition": "Named reference to a value or collection of values in Robot Framework used to store data and pass it between keywords, tests, and tasks." + }, + { + "term": "Variable File", + "aliases": [], + "abbreviation": "", + "definition": "File (often a Python module or other supported format) that provides variables which can be imported into suites using the Variables setting." + }, + { + "term": "Variable Scope", + "aliases": [], + "abbreviation": "", + "definition": "Visibility and lifetime of a variable (such as global, suite, test|task, or local) during a Robot Framework execution." + }, + { + "term": "WHILE Loop", + "aliases": [], + "abbreviation": "", + "definition": "Control structure in Robot Framework that repeatedly executes a block of keywords as long as a given condition evaluates to true." + } +] diff --git a/website/tsconfig.json b/website/tsconfig.json index 920d7a6..f5ec699 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -2,7 +2,8 @@ // This file is not used in compilation. It is here just for a nice editor experience. "extends": "@docusaurus/tsconfig", "compilerOptions": { - "baseUrl": "." + "baseUrl": ".", + "types": ["@docusaurus/module-type-aliases"] }, "exclude": [".docusaurus", "build"] }